diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000..45995eb1b0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,138 @@ +name: Bug report +description: Report a focused, reproducible Lime bug +title: "[Bug]: " +labels: [] +body: + - type: markdown + attributes: + value: | + Please report one specific problem per issue. Reports without enough information to reproduce may be closed until the missing details are provided. + + - type: checkboxes + id: checks + attributes: + label: Preflight Checklist + options: + - label: I searched existing open and closed issues for duplicates. + required: true + - label: I tested the latest stable Lime release or the current development branch where possible. + required: true + - label: I reduced this to the smallest project or code sample that still reproduces the issue. + required: true + - label: This issue describes one specific behavior, not several unrelated observations. + required: true + + - type: textarea + id: summary + attributes: + label: Problem Description + description: Describe the specific behavior that appears to be wrong. + validations: + required: true + + - type: textarea + id: versions + attributes: + label: Version Information + description: Include exact versions. Do not write "latest" by itself. + value: | + Lime version: + OpenFL version, if applicable: + Haxe version: + Target/runtime: + validations: + required: true + + - type: textarea + id: environment + attributes: + label: Environment + description: Include relevant OS, architecture, hardware and driver details. + value: | + OS: + Architecture: + GPU/driver, if relevant: + Display refresh rate, if relevant: + validations: + required: true + + - type: textarea + id: repro + attributes: + label: Minimal Reproduction + description: Attach or link a minimal project, or paste the smallest code sample that reproduces the problem. Include project.xml or project.hxp. + placeholder: | + Link to minimal project: + + project.xml / project.hxp: + + Relevant source: + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to Reproduce + description: List exact steps needed to reproduce the issue from a clean checkout/project. + placeholder: | + 1. + 2. + 3. + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Expected Behavior + description: What should happen? + validations: + required: true + + - type: textarea + id: actual + attributes: + label: Actual Behavior + description: What happens instead? + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Logs and Output + description: Paste relevant console output, stack traces or build logs. + render: text + validations: + required: false + + - type: textarea + id: media + attributes: + label: Screenshots or Videos + description: Attach screenshots or videos only if they help demonstrate the reproduced behavior. They do not replace a minimal reproduction. + validations: + required: false + + - type: textarea + id: timing + attributes: + label: Performance, Timing or Rendering Details + description: If this is about frame pacing, timing or rendering, explain how you measured it and list frame rate, vsync, window/fullscreen and display settings. + placeholder: | + Frame rate: + Vsync setting: + Window/fullscreen mode: + Measurement method: + Reproduces on other targets/machines/drivers: + validations: + required: false + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Add any other focused context that may help reproduce or diagnose this issue. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..3ba13e0cec --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000000..143721ab44 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,87 @@ +name: Feature request +description: Propose a focused Lime feature or behavior change +title: "[Feature]: " +labels: [] +body: + - type: markdown + attributes: + value: | + Please use this form for focused feature proposals. If you are reporting broken behavior, use the bug report form instead. + + - type: checkboxes + id: checks + attributes: + label: Preflight Checklist + options: + - label: I searched existing open and closed issues for similar proposals. + required: true + - label: This request describes one focused feature or behavior change. + required: true + - label: This is not a bug report or a request for help debugging project-specific code. + required: true + + - type: textarea + id: problem + attributes: + label: Problem or Use Case + description: What problem would this feature solve? Who needs it, and when? + validations: + required: true + + - type: textarea + id: proposal + attributes: + label: Proposed Behavior + description: Describe the exact behavior, API, project setting or workflow change you are proposing. + validations: + required: true + + - type: textarea + id: targets + attributes: + label: Affected Targets or Backends + description: List the targets, runtimes or backends this proposal affects. + placeholder: | + Native SDL: + HTML5: + HashLink: + HXCPP: + Other: + validations: + required: true + + - type: textarea + id: compatibility + attributes: + label: Compatibility and Defaults + description: Explain whether this should be default behavior, opt-in behavior or a breaking change. Include any compatibility concerns. + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives Considered + description: What existing options, workarounds or alternative designs have you considered? + validations: + required: false + + - type: textarea + id: examples + attributes: + label: Example Usage + description: Show how a project would use this feature, if applicable. + placeholder: | + project.xml / project.hxp: + + Haxe code: + validations: + required: false + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Add any focused context, links or prior discussion that may help evaluate the proposal. + validations: + required: false diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 857907b35e..3ea16a4a54 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,7 +18,7 @@ jobs: - name: Install system dependencies run: | sudo apt-get update - sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev g++-multilib gcc-multilib libasound2-dev libx11-dev libxext-dev libxi-dev libxrandr-dev libxinerama-dev libpulse-dev libmbedtls-dev libpng-dev libturbojpeg-dev libuv1-dev libvorbis-dev + sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev g++-multilib gcc-multilib libasound2-dev libx11-dev libxext-dev libxi-dev libxrandr-dev libxinerama-dev libpulse-dev libmbedtls-dev libpng-dev libturbojpeg-dev libuv1-dev libvorbis-dev libvulkan-dev - uses: krdlab/setup-haxe@v2 with: @@ -110,7 +110,7 @@ jobs: run: | sudo add-apt-repository ppa:haxe/releases -y sudo apt-get update - sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libasound2-dev libx11-dev libxext-dev libxi-dev libxrandr-dev libxinerama-dev libpulse-dev libmbedtls-dev libpng-dev libturbojpeg-dev libuv1-dev libvorbis-dev + sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libasound2-dev libx11-dev libxext-dev libxi-dev libxrandr-dev libxinerama-dev libpulse-dev libmbedtls-dev libpng-dev libturbojpeg-dev libuv1-dev libvorbis-dev libvulkan-dev # krdlab/setup-haxe doesn't support arm64 linux # so this is our workaround for now @@ -135,10 +135,6 @@ jobs: haxelib install hxp --quiet haxelib install utest --quiet - - name: Enable HXCPP compile cache - run: | - echo "HXCPP_COMPILE_CACHE=~/.hxcpp" >> $GITHUB_ENV - - name: Rebuild Lime tools run: | haxelib dev lime ${{ github.workspace }} @@ -182,6 +178,59 @@ jobs: lime create SimpleAudio -verbose -nocolor lime build SimpleAudio linux -release -verbose -nocolor + vulkan-smoke: + runs-on: ubuntu-22.04 + steps: + + - uses: actions/checkout@v6 + with: + submodules: true + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libasound2-dev libx11-dev libx11-xcb1 libxext-dev libxi-dev libxrandr-dev libxinerama-dev libpulse-dev libmbedtls-dev libpng-dev libturbojpeg-dev libuv1-dev libvorbis-dev libvulkan-dev mesa-vulkan-drivers xvfb + + - uses: krdlab/setup-haxe@v2 + with: + haxe-version: ${{ env.HAXE_VERSION }} + + - name: Set HAXEPATH + run: | + echo "HAXEPATH=$HAXE_STD_PATH/.." >> $GITHUB_ENV + + - name: Install Haxe dependencies + run: | + curl --output ../hxcpp-4.3.45.zip --location https://github.com/HaxeFoundation/hxcpp/releases/download/v4.3.45/hxcpp-4.3.45.zip + haxelib --global update haxelib --quiet + haxelib install ../hxcpp-4.3.45.zip --quiet + haxelib install format --quiet + haxelib install hxp --quiet + haxelib install utest --quiet + + - name: Rebuild Lime tools + run: | + haxelib dev lime ${{ github.workspace }} + haxelib run lime rebuild tools -nocolor -verbose -nocffi + haxelib run lime setup -alias -y -nocffi + + - name: Rebuild Lime (Linux default Vulkan) + run: | + lime rebuild linux -64 -release -nocolor -verbose -nocffi + + - name: Build Vulkan smoke test app + working-directory: tests/vulkan-smoke + run: | + lime build linux -release -verbose -nocolor + + - name: Run Vulkan smoke test app + working-directory: tests/vulkan-smoke + run: | + if [ -f /usr/share/vulkan/icd.d/lvp_icd.x86_64.json ]; then + export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/lvp_icd.x86_64.json + fi + SDL_AUDIODRIVER=dummy xvfb-run -a Export/linux/bin/LimeVulkanSmoke + macos: runs-on: macos-14 steps: @@ -200,16 +249,27 @@ jobs: - name: Install HashLink dependencies run: | - arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - pushd project/lib/hashlink - arch -x86_64 /usr/local/bin/brew update - rm /usr/local/bin/2to3* - rm /usr/local/bin/idle3* - rm /usr/local/bin/pydoc3* - rm /usr/local/bin/python3* - rm /usr/local/bin/pip3* - arch -x86_64 /usr/local/bin/brew bundle - popd + set -euxo pipefail + + if [ ! -x /usr/local/bin/brew ]; then + NONINTERACTIVE=1 arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" + fi + + rm -f /usr/local/bin/2to3* + rm -f /usr/local/bin/idle3* + rm -f /usr/local/bin/pydoc3* + rm -f /usr/local/bin/python3* + rm -f /usr/local/bin/pip3* + + for attempt in 1 2 3; do + if arch -x86_64 /usr/local/bin/brew update && arch -x86_64 /usr/local/bin/brew install jpeg-turbo libpng libuv libvorbis; then + break + fi + if [ "$attempt" -eq 3 ]; then + exit 1 + fi + sleep $((attempt * 30)) + done - name: Install Haxe dependencies run: | @@ -229,6 +289,9 @@ jobs: run: | lime rebuild macos -clean -release -64 -nocolor -verbose -nocffi lime rebuild macos -clean -release -arm64 -nocolor -verbose -nocffi + + - name: Rebuild Lime (HashLink macOS) + run: | lime rebuild hl -clean -release -nocolor -verbose -nocffi - uses: actions/upload-artifact@v7 @@ -476,6 +539,11 @@ jobs: run: | lime create SimpleAudio -verbose -nocolor -eval lime build SimpleAudio android -release -verbose -nocolor -eval + + - name: Build Vulkan smoke test app + working-directory: tests/vulkan-smoke + run: | + lime build android -release -verbose -nocolor -eval ios: runs-on: macos-14 steps: @@ -536,7 +604,7 @@ jobs: lime build SimpleAudio ios -release -nosign -verbose -nocolor -eval package-haxelib: - needs: [linux, macos, windows, android, ios] + needs: [linux, vulkan-smoke, macos, windows, android, ios] runs-on: ubuntu-22.04 steps: @@ -728,7 +796,7 @@ jobs: runs-on: windows-latest strategy: matrix: - haxe-version: [4.0.5, 4.1.5, 4.2.5, 4.3.6] + haxe-version: [4.0.5, 4.1.5, 4.2.5, 4.3.7] steps: - uses: actions/checkout@v6 @@ -882,7 +950,7 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - haxe-version: [3.4.7, 4.0.5, 4.1.5, 4.2.5, 4.3.6] + haxe-version: [3.4.7, 4.0.5, 4.1.5, 4.2.5, 4.3.7] steps: - uses: actions/checkout@v6 @@ -996,7 +1064,7 @@ jobs: notify: runs-on: ubuntu-22.04 - needs: [package-haxelib, docs, android, flash-samples, air-samples, hashlink-samples, hashlinkc-samples, html5-samples, ios, linux, macos, neko-samples, windows] + needs: [package-haxelib, docs, android, flash-samples, air-samples, hashlink-samples, hashlinkc-samples, html5-samples, ios, linux, vulkan-smoke, macos, neko-samples, windows] if: ${{ github.repository == 'openfl/lime' && github.event_name != 'pull_request' }} steps: - name: Notify Discord diff --git a/CHANGELOG.md b/CHANGELOG.md index 38d456a168..f3ddcb60e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,38 @@ Changelog ========= +8.4.0 (06/18/2026) +------------------ + +- Added an experimental Vulkan renderer for native Windows, Linux, and Android targets. +- Added `VulkanRenderContext` and Haxe Vulkan bindings for instance, device, swapchain, command, descriptor, memory, and pipeline helpers. +- Added Vulkan bootstrap logging, error details, MSAA resolve support, mapped memory helpers, and descriptor helpers. +- Added configurable application frame timing with `FrameProfile`, `FrameOptions`, `VSyncMode`, busy-wait, time precision, and uncap controls. +- Added `AudioInput` and audio input device APIs with native OpenAL, HTML5, and Flash backends. +- Added SDL_sound decoding and streaming, including inline stream playback, streams with unknown length, and loop counts. +- Added `Window.alwaysOnTop` and transparent window support. +- Added input event timestamps without changing listener signatures. +- Added `Promise.completeAsync()`. +- Added explicit font rendering flags, DPI-aware glyph rendering, unhinted font decomposition, and HarfBuzz FT font change notifications. +- Added project.xml support for Android manifest tags and Gradle plugin entries. +- Added AIR options for Android App Bundles, Android Studio output, and shared runtime deployment. +- Added VAO support on macOS. +- Changed asset copying and embedding to behave consistently across targets. +- Changed OpenAL Soft HRTF to be disabled by default. +- Updated pixman and platform config for LLVM assembly fixes, ARM NEON, Android NDKs, and Apple platforms. +- Updated MojoAL and gamepad mappings. +- Fixed an asset embedding regression. +- Fixed Windows cpp icon resource handling when no icon is generated. +- Fixed GL cleanup and desktop GL object collection. +- Fixed native and HashLink `AudioBuffer` layout mismatches. +- Fixed `AudioBuffer.fromBytes()` and `AudioBuffer.fromBase64()` on HTML5 to avoid forcing HTML5 audio buffers. +- Fixed OpenAL output device recovery. +- Fixed perspective camera matrix calculation. +- Fixed Tizen `appinfo.json` templating. +- Fixed Android architecture parsing for `x86_64` and `x86_32`. +- Fixed SDL_sound ARM64 Linux detection outside Raspberry Pi OS. +- Fixed HTML5 transparent docs generation. + 8.3.2 (05/13/2026) ------------------ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c483f354e6..ae8c283921 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,6 +5,38 @@ We welcome your feedback and input in how to make Lime better! If you are interested in discussing new features, the direction the project or how to integrate some change, please open an issue so we can talk about. +## Issue Reporting Guidelines + +Please keep bug reports focused, reproducible and actionable. A good issue should describe one specific problem and include enough information for maintainers to reproduce it without guessing. + +Before opening an issue: + + 1. Search existing open and closed issues to avoid duplicates. + + 2. Test with the latest stable release and, when possible, the current development branch. + + 3. Reduce the problem to the smallest project or code sample that still reproduces it. + +Bug reports should include: + + 1. The exact Lime version, OpenFL version if applicable, Haxe version and target/runtime. + + 2. The operating system, architecture and relevant hardware or driver details. + + 3. A minimal project or code sample, including `project.xml` or `project.hxp`. + + 4. Exact steps to reproduce the problem. + + 5. The expected behavior and the actual behavior. + + 6. Any relevant logs, console output, screenshots or videos. + +Please do not combine multiple unrelated problems in one issue. Open one issue per behavior so each report can be reproduced, discussed and fixed independently. + +Performance, timing and rendering reports need especially clear reproduction material. Include a minimal project, the exact frame rate/vsync/window settings, how the result was measured and whether the behavior reproduces across targets, machines or drivers. + +Issues based only on broad observations, speculation, generated code that has not been verified, or project-specific behavior without a minimal reproduction may be closed until enough information is provided. + 1. Fork the repository 2. Make the desired change diff --git a/README.md b/README.md index c6803fb1a5..167628b285 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,13 @@ Lime does not include a renderer, but exposes the current context: * DOM * Flash * GL + * Vulkan The GL context is based upon the WebGL standard, implemented for both OpenGL and OpenGL ES as needed. +Native Vulkan support exposes an explicit Vulkan API layer for renderer backends, including native window/swapchain integration and resource/command primitives. +Native Vulkan support is included in standard Windows and Linux C++ Lime builds, including the matching Haxe API define. Apple targets still require an explicit Vulkan-enabled build and MoltenVK packaging. +To request a Vulkan window, use the standard `RenderContextType.VULKAN` context selection or set `` in project XML. +The in-repo `tests/vulkan-smoke` project is used as the current Vulkan CI smoke app. Lime provides a unified audio API, but also provides access to OpenAL for advanced audio on native targets. diff --git a/docs/ImportAll.hx b/docs/ImportAll.hx index e0039724f6..d1fbcc89cf 100644 --- a/docs/ImportAll.hx +++ b/docs/ImportAll.hx @@ -58,6 +58,41 @@ import lime.graphics.PixelFormat; import lime.graphics.RenderContext; import lime.graphics.RenderContextAttributes; import lime.graphics.RenderContextType; +import lime.graphics.VulkanRenderContext; +import lime.graphics.vulkan.VK; +import lime.graphics.vulkan.VKAcquireResult; +import lime.graphics.vulkan.VKBuffer; +import lime.graphics.vulkan.VKCommandBuffer; +import lime.graphics.vulkan.VKCommandPool; +import lime.graphics.vulkan.VKDescriptorPool; +import lime.graphics.vulkan.VKDescriptorPoolSize; +import lime.graphics.vulkan.VKDescriptorSet; +import lime.graphics.vulkan.VKDescriptorSetLayout; +import lime.graphics.vulkan.VKDescriptorSetLayoutBinding; +import lime.graphics.vulkan.VKDevice; +import lime.graphics.vulkan.VKDeviceMemory; +import lime.graphics.vulkan.VKFence; +import lime.graphics.vulkan.VKFramebuffer; +import lime.graphics.vulkan.VKGraphicsPipelineInfo; +import lime.graphics.vulkan.VKImage; +import lime.graphics.vulkan.VKImageView; +import lime.graphics.vulkan.VKInstance; +import lime.graphics.vulkan.VKMemoryRequirements; +import lime.graphics.vulkan.VKPhysicalDevice; +import lime.graphics.vulkan.VKPipeline; +import lime.graphics.vulkan.VKPipelineCache; +import lime.graphics.vulkan.VKPipelineLayout; +import lime.graphics.vulkan.VKQueue; +import lime.graphics.vulkan.VKQueueFamilyInfo; +import lime.graphics.vulkan.VKRenderPass; +import lime.graphics.vulkan.VKRenderer; +import lime.graphics.vulkan.VKSampler; +import lime.graphics.vulkan.VKSemaphore; +import lime.graphics.vulkan.VKShaderModule; +import lime.graphics.vulkan.VKSurface; +import lime.graphics.vulkan.VKSwapchain; +import lime.graphics.vulkan.VKVertexAttribute; +import lime.graphics.vulkan.VKVertexBinding; import lime.graphics.WebGL2RenderContext; import lime.graphics.WebGLRenderContext; import lime.math.ARGB; @@ -87,6 +122,8 @@ import lime.media.vorbis.VorbisInfo; import lime.media.AudioBuffer; import lime.media.AudioContext; import lime.media.AudioContextType; +import lime.media.AudioInput; +import lime.media.AudioInputDevice; import lime.media.AudioManager; import lime.media.AudioSource; import lime.media.FlashAudioContext; diff --git a/externs/air/flash/data/SQLCollationType.hx b/externs/air/flash/data/SQLCollationType.hx index fecbfc8382..0f93c36c1f 100644 --- a/externs/air/flash/data/SQLCollationType.hx +++ b/externs/air/flash/data/SQLCollationType.hx @@ -1,7 +1,6 @@ package flash.data; -@:native("flash.data.SQLCollationType") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLCollationType(String) +@:native("flash.data.SQLCollationType") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLCollationType(String) { var BINARY = "binary"; var NO_CASE = "noCase"; diff --git a/externs/air/flash/data/SQLColumnNameStyle.hx b/externs/air/flash/data/SQLColumnNameStyle.hx index 03cb7a5adf..c25b13fc07 100644 --- a/externs/air/flash/data/SQLColumnNameStyle.hx +++ b/externs/air/flash/data/SQLColumnNameStyle.hx @@ -1,7 +1,6 @@ package flash.data; -@:native("flash.data.SQLColumnNameStyle") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLColumnNameStyle(String) +@:native("flash.data.SQLColumnNameStyle") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLColumnNameStyle(String) { var DEFAULT = "default"; var LONG = "long"; diff --git a/externs/air/flash/data/SQLMode.hx b/externs/air/flash/data/SQLMode.hx index ebddf4c8c9..4b876d2d02 100644 --- a/externs/air/flash/data/SQLMode.hx +++ b/externs/air/flash/data/SQLMode.hx @@ -1,7 +1,6 @@ package flash.data; -@:native("flash.data.SQLMode") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLMode(String) +@:native("flash.data.SQLMode") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLMode(String) { var CREATE = "create"; var READ = "read"; diff --git a/externs/air/flash/data/SQLTransactionLockType.hx b/externs/air/flash/data/SQLTransactionLockType.hx index 36c24bc1a7..47a06a7a79 100644 --- a/externs/air/flash/data/SQLTransactionLockType.hx +++ b/externs/air/flash/data/SQLTransactionLockType.hx @@ -1,7 +1,6 @@ package flash.data; -@:native("flash.data.SQLTransactionLockType") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLTransactionLockType(String) +@:native("flash.data.SQLTransactionLockType") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLTransactionLockType(String) { var DEFERRED = "deferred"; var EXCLUSIVE = "exclusive"; diff --git a/externs/air/flash/desktop/InvokeEventReason.hx b/externs/air/flash/desktop/InvokeEventReason.hx index d06e591c1b..1c053ad26c 100644 --- a/externs/air/flash/desktop/InvokeEventReason.hx +++ b/externs/air/flash/desktop/InvokeEventReason.hx @@ -1,7 +1,6 @@ package flash.desktop; -@:native("flash.desktop.InvokeEventReason") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract InvokeEventReason(String) +@:native("flash.desktop.InvokeEventReason") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract InvokeEventReason(String) { var LOGIN = "login"; var NOTIFICATION = "notification"; diff --git a/externs/air/flash/desktop/NativeDragActions.hx b/externs/air/flash/desktop/NativeDragActions.hx index fe67ff9db7..544ad2f1bf 100644 --- a/externs/air/flash/desktop/NativeDragActions.hx +++ b/externs/air/flash/desktop/NativeDragActions.hx @@ -1,7 +1,6 @@ package flash.desktop; -@:native("flash.desktop.NativeDragActions") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeDragActions(String) +@:native("flash.desktop.NativeDragActions") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeDragActions(String) { var COPY = "copy"; var LINK = "link"; diff --git a/externs/air/flash/desktop/NotificationType.hx b/externs/air/flash/desktop/NotificationType.hx index b2b3dcfb09..c9461c33cf 100644 --- a/externs/air/flash/desktop/NotificationType.hx +++ b/externs/air/flash/desktop/NotificationType.hx @@ -1,7 +1,6 @@ package flash.desktop; -@:native("flash.desktop.NotificationType") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NotificationType(String) +@:native("flash.desktop.NotificationType") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NotificationType(String) { var CRITICAL = "critical"; var INFORMATIONAL = "informational"; diff --git a/externs/air/flash/desktop/SystemIdleMode.hx b/externs/air/flash/desktop/SystemIdleMode.hx index 7fda8df044..c129940766 100644 --- a/externs/air/flash/desktop/SystemIdleMode.hx +++ b/externs/air/flash/desktop/SystemIdleMode.hx @@ -1,7 +1,6 @@ package flash.desktop; -@:native("flash.desktop.SystemIdleMode") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SystemIdleMode(String) +@:native("flash.desktop.SystemIdleMode") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SystemIdleMode(String) { var KEEP_AWAKE = "keepAwake"; var NORMAL = "normal"; diff --git a/externs/air/flash/display/NativeWindowDisplayState.hx b/externs/air/flash/display/NativeWindowDisplayState.hx index 4fb63f10d7..56a073a2e0 100644 --- a/externs/air/flash/display/NativeWindowDisplayState.hx +++ b/externs/air/flash/display/NativeWindowDisplayState.hx @@ -1,7 +1,6 @@ package flash.display; -@:native("flash.display.NativeWindowDisplayState") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowDisplayState(String) +@:native("flash.display.NativeWindowDisplayState") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowDisplayState(String) { var MAXIMIZED = "maximized"; var MINIMIZED = "minimized"; diff --git a/externs/air/flash/display/NativeWindowRenderMode.hx b/externs/air/flash/display/NativeWindowRenderMode.hx index e2d182c5bd..51a135f715 100644 --- a/externs/air/flash/display/NativeWindowRenderMode.hx +++ b/externs/air/flash/display/NativeWindowRenderMode.hx @@ -1,7 +1,6 @@ package flash.display; -@:native("flash.display.NativeWindowRenderMode") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowRenderMode(String) +@:native("flash.display.NativeWindowRenderMode") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowRenderMode(String) { var AUTO = "auto"; var CPU = "cpu"; diff --git a/externs/air/flash/display/NativeWindowResize.hx b/externs/air/flash/display/NativeWindowResize.hx index b3cd1a1f9f..5974784f0f 100644 --- a/externs/air/flash/display/NativeWindowResize.hx +++ b/externs/air/flash/display/NativeWindowResize.hx @@ -1,7 +1,6 @@ package flash.display; -@:native("flash.display.NativeWindowResize") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowResize(String) +@:native("flash.display.NativeWindowResize") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowResize(String) { var BOTTOM = "bottom"; var BOTTOM_LEFT = "bottomLeft"; diff --git a/externs/air/flash/display/NativeWindowSystemChrome.hx b/externs/air/flash/display/NativeWindowSystemChrome.hx index e271969831..367e6d9c22 100644 --- a/externs/air/flash/display/NativeWindowSystemChrome.hx +++ b/externs/air/flash/display/NativeWindowSystemChrome.hx @@ -1,7 +1,6 @@ package flash.display; -@:native("flash.display.NativeWindowSystemChrome") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowSystemChrome(String) +@:native("flash.display.NativeWindowSystemChrome") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowSystemChrome(String) { var ALTERNATE = "alternate"; var NONE = "none"; diff --git a/externs/air/flash/display/NativeWindowType.hx b/externs/air/flash/display/NativeWindowType.hx index 90ff5bb41f..0ffd8af4bc 100644 --- a/externs/air/flash/display/NativeWindowType.hx +++ b/externs/air/flash/display/NativeWindowType.hx @@ -1,7 +1,6 @@ package flash.display; -@:native("flash.display.NativeWindowType") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowType(String) +@:native("flash.display.NativeWindowType") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NativeWindowType(String) { var LIGHTWEIGHT = "lightweight"; var NORMAL = "normal"; diff --git a/externs/air/flash/display/StageAspectRatio.hx b/externs/air/flash/display/StageAspectRatio.hx index 70ede16512..8a308b07bf 100644 --- a/externs/air/flash/display/StageAspectRatio.hx +++ b/externs/air/flash/display/StageAspectRatio.hx @@ -1,7 +1,6 @@ package flash.display; -@:native("flash.display.StageAspectRatio") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract StageAspectRatio(String) +@:native("flash.display.StageAspectRatio") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract StageAspectRatio(String) { var ANY = "any"; var LANDSCAPE = "landscape"; diff --git a/externs/air/flash/display/StageOrientation.hx b/externs/air/flash/display/StageOrientation.hx index d55da84778..2f2a9b34a8 100644 --- a/externs/air/flash/display/StageOrientation.hx +++ b/externs/air/flash/display/StageOrientation.hx @@ -1,7 +1,6 @@ package flash.display; -@:native("flash.display.StageOrientation") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract StageOrientation(String) +@:native("flash.display.StageOrientation") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract StageOrientation(String) { var DEFAULT = "default"; var ROTATED_LEFT = "rotatedLeft"; diff --git a/externs/air/flash/display3D/Context3DProfile.hx b/externs/air/flash/display3D/Context3DProfile.hx index 2c29eea679..a7e697bc09 100644 --- a/externs/air/flash/display3D/Context3DProfile.hx +++ b/externs/air/flash/display3D/Context3DProfile.hx @@ -1,7 +1,6 @@ package flash.display3D; -@:native("flash.display3D.Context3DProfile") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract Context3DProfile(String) +@:native("flash.display3D.Context3DProfile") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract Context3DProfile(String) { var BASELINE = "baseline"; var BASELINE_CONSTRAINED = "baselineConstrained"; diff --git a/externs/air/flash/errors/SQLErrorOperation.hx b/externs/air/flash/errors/SQLErrorOperation.hx index 15e7a651c0..396ba8c237 100644 --- a/externs/air/flash/errors/SQLErrorOperation.hx +++ b/externs/air/flash/errors/SQLErrorOperation.hx @@ -1,7 +1,6 @@ package flash.errors; -@:native("flash.errors.SQLErrorOperation") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLErrorOperation(String) +@:native("flash.errors.SQLErrorOperation") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SQLErrorOperation(String) { var ANALYZE = "analyze"; var ATTACH = "attach"; diff --git a/externs/air/flash/events/TouchEventIntent.hx b/externs/air/flash/events/TouchEventIntent.hx index 19a3c6a0e6..0af83e0428 100644 --- a/externs/air/flash/events/TouchEventIntent.hx +++ b/externs/air/flash/events/TouchEventIntent.hx @@ -1,7 +1,6 @@ package flash.events; -@:native("flash.events.TouchEventIntent") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract TouchEventIntent(String) +@:native("flash.events.TouchEventIntent") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract TouchEventIntent(String) { var ERASER = "eraser"; var PEN = "pen"; diff --git a/externs/air/flash/filesystem/FileMode.hx b/externs/air/flash/filesystem/FileMode.hx index 3041db9b92..6644c1627b 100644 --- a/externs/air/flash/filesystem/FileMode.hx +++ b/externs/air/flash/filesystem/FileMode.hx @@ -1,7 +1,6 @@ package flash.filesystem; -@:native("flash.filesystem.FileMode") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract FileMode(String) +@:native("flash.filesystem.FileMode") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract FileMode(String) { var APPEND = "append"; var READ = "read"; diff --git a/externs/air/flash/media/AudioPlaybackMode.hx b/externs/air/flash/media/AudioPlaybackMode.hx index fdc31990c4..9757dadbe0 100644 --- a/externs/air/flash/media/AudioPlaybackMode.hx +++ b/externs/air/flash/media/AudioPlaybackMode.hx @@ -1,7 +1,6 @@ package flash.media; -@:native("flash.media.AudioPlaybackMode") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract AudioPlaybackMode(String) +@:native("flash.media.AudioPlaybackMode") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract AudioPlaybackMode(String) { var AMBIENT = "ambient"; var MEDIA = "media"; diff --git a/externs/air/flash/media/CameraPosition.hx b/externs/air/flash/media/CameraPosition.hx index 06184cc9ed..754d0051f9 100644 --- a/externs/air/flash/media/CameraPosition.hx +++ b/externs/air/flash/media/CameraPosition.hx @@ -1,7 +1,6 @@ package flash.media; -@:native("flash.media.CameraPosition") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract CameraPosition(String) +@:native("flash.media.CameraPosition") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract CameraPosition(String) { var BACK = "back"; var FRONT = "front"; diff --git a/externs/air/flash/media/MediaType.hx b/externs/air/flash/media/MediaType.hx index 41a10306fb..e925b08397 100644 --- a/externs/air/flash/media/MediaType.hx +++ b/externs/air/flash/media/MediaType.hx @@ -1,7 +1,6 @@ package flash.media; -@:native("flash.media.MediaType") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract MediaType(String) +@:native("flash.media.MediaType") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract MediaType(String) { var IMAGE = "image"; var VIDEO = "video"; diff --git a/externs/air/flash/net/IPVersion.hx b/externs/air/flash/net/IPVersion.hx index ef4a44fcf2..c9d8200955 100644 --- a/externs/air/flash/net/IPVersion.hx +++ b/externs/air/flash/net/IPVersion.hx @@ -1,7 +1,6 @@ package flash.net; -@:native("flash.net.IPVersion") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract IPVersion(String) +@:native("flash.net.IPVersion") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract IPVersion(String) { var IPV4 = "ipv4"; var IPV6 = "ipv6"; diff --git a/externs/air/flash/notifications/NotificationStyle.hx b/externs/air/flash/notifications/NotificationStyle.hx index a2a9f3fdd2..715052bf6d 100644 --- a/externs/air/flash/notifications/NotificationStyle.hx +++ b/externs/air/flash/notifications/NotificationStyle.hx @@ -1,7 +1,6 @@ package flash.notifications; -@:native("flash.notifications.NotificationStyle") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NotificationStyle(String) +@:native("flash.notifications.NotificationStyle") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract NotificationStyle(String) { var ALERT = "alert"; var BADGE = "badge"; diff --git a/externs/air/flash/printing/PaperSize.hx b/externs/air/flash/printing/PaperSize.hx index fe607d1e2a..65e60bdbfa 100644 --- a/externs/air/flash/printing/PaperSize.hx +++ b/externs/air/flash/printing/PaperSize.hx @@ -1,7 +1,6 @@ package flash.printing; -@:native("flash.printing.PaperSize") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract PaperSize(String) +@:native("flash.printing.PaperSize") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract PaperSize(String) { var A4 = "a4"; var A5 = "a5"; diff --git a/externs/air/flash/printing/PrintMethod.hx b/externs/air/flash/printing/PrintMethod.hx index 070fcfcf1c..a6f7ac873a 100644 --- a/externs/air/flash/printing/PrintMethod.hx +++ b/externs/air/flash/printing/PrintMethod.hx @@ -1,7 +1,6 @@ package flash.printing; -@:native("flash.printing.PrintMethod") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract PrintMethod(String) +@:native("flash.printing.PrintMethod") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract PrintMethod(String) { var AUTO = "auto"; var BITMAP = "bitmap"; diff --git a/externs/air/flash/security/ReferencesValidationSetting.hx b/externs/air/flash/security/ReferencesValidationSetting.hx index 08fda5c8ca..b357c649d1 100644 --- a/externs/air/flash/security/ReferencesValidationSetting.hx +++ b/externs/air/flash/security/ReferencesValidationSetting.hx @@ -1,7 +1,6 @@ package flash.security; -@:native("flash.security.ReferencesValidationSetting") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract ReferencesValidationSetting(String) +@:native("flash.security.ReferencesValidationSetting") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract ReferencesValidationSetting(String) { var NEVER = "never"; var VALID_IDENTITY = "validIdentity"; diff --git a/externs/air/flash/security/RevocationCheckSettings.hx b/externs/air/flash/security/RevocationCheckSettings.hx index 09725cea85..11365b4a09 100644 --- a/externs/air/flash/security/RevocationCheckSettings.hx +++ b/externs/air/flash/security/RevocationCheckSettings.hx @@ -1,7 +1,6 @@ package flash.security; -@:native("flash.security.RevocationCheckSettings") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract RevocationCheckSettings(String) +@:native("flash.security.RevocationCheckSettings") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract RevocationCheckSettings(String) { var ALWAYS_REQUIRED = "alwaysRequired"; var BEST_EFFORT = "bestEffort"; diff --git a/externs/air/flash/security/SignatureStatus.hx b/externs/air/flash/security/SignatureStatus.hx index f8c632599e..68e03bcaf9 100644 --- a/externs/air/flash/security/SignatureStatus.hx +++ b/externs/air/flash/security/SignatureStatus.hx @@ -1,7 +1,6 @@ package flash.security; -@:native("flash.security.SignatureStatus") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SignatureStatus(String) +@:native("flash.security.SignatureStatus") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SignatureStatus(String) { var INVALID = "invalid"; var UNKNOWN = "unknown"; diff --git a/externs/air/flash/security/SignerTrustSettings.hx b/externs/air/flash/security/SignerTrustSettings.hx index 0164a3a253..0edf890a94 100644 --- a/externs/air/flash/security/SignerTrustSettings.hx +++ b/externs/air/flash/security/SignerTrustSettings.hx @@ -1,7 +1,6 @@ package flash.security; -@:native("flash.security.SignerTrustSettings") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SignerTrustSettings(String) +@:native("flash.security.SignerTrustSettings") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SignerTrustSettings(String) { var CODE_SIGNING = "codeSigning"; var PLAYLIST_SIGNING = "playlistSigning"; diff --git a/externs/air/flash/text/AutoCapitalize.hx b/externs/air/flash/text/AutoCapitalize.hx index e0bb0169df..472737f7cd 100644 --- a/externs/air/flash/text/AutoCapitalize.hx +++ b/externs/air/flash/text/AutoCapitalize.hx @@ -1,7 +1,6 @@ package flash.text; -@:native("flash.text.AutoCapitalize") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract AutoCapitalize(String) +@:native("flash.text.AutoCapitalize") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract AutoCapitalize(String) { var ALL = "all"; var NONE = "none"; diff --git a/externs/air/flash/text/ReturnKeyLabel.hx b/externs/air/flash/text/ReturnKeyLabel.hx index 3936c1722e..573d048ee3 100644 --- a/externs/air/flash/text/ReturnKeyLabel.hx +++ b/externs/air/flash/text/ReturnKeyLabel.hx @@ -1,7 +1,6 @@ package flash.text; -@:native("flash.text.ReturnKeyLabel") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract ReturnKeyLabel(String) +@:native("flash.text.ReturnKeyLabel") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract ReturnKeyLabel(String) { var DEFAULT = "default"; var DONE = "done"; diff --git a/externs/air/flash/text/SoftKeyboardType.hx b/externs/air/flash/text/SoftKeyboardType.hx index 3a9f747dc4..a6ff23fddb 100644 --- a/externs/air/flash/text/SoftKeyboardType.hx +++ b/externs/air/flash/text/SoftKeyboardType.hx @@ -1,7 +1,6 @@ package flash.text; -@:native("flash.text.SoftKeyboardType") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SoftKeyboardType(String) +@:native("flash.text.SoftKeyboardType") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract SoftKeyboardType(String) { var CONTACT = "contact"; var DEFAULT = "default"; diff --git a/externs/air/flash/text/StageTextClearButtonMode.hx b/externs/air/flash/text/StageTextClearButtonMode.hx index 21f09ecb2b..ade3888cb0 100644 --- a/externs/air/flash/text/StageTextClearButtonMode.hx +++ b/externs/air/flash/text/StageTextClearButtonMode.hx @@ -1,7 +1,6 @@ package flash.text; -@:native("flash.text.StageTextClearButtonMode") -#if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract StageTextClearButtonMode(String) +@:native("flash.text.StageTextClearButtonMode") #if (haxe_ver >= 4.0) extern enum #else @:extern @:enum #end abstract StageTextClearButtonMode(String) { var ALWAYS = "always"; var NEVER = "never"; diff --git a/externs/air/sys/io/FileInput.hx b/externs/air/sys/io/FileInput.hx index 93e2f3b19d..7e3558ed28 100644 --- a/externs/air/sys/io/FileInput.hx +++ b/externs/air/sys/io/FileInput.hx @@ -34,9 +34,9 @@ class FileInput extends haxe.io.Input switch (pos) { case SeekBegin: - // this.pos = p; + // this.pos = p; case SeekEnd: - // this.pos = cast Fs.fstatSync(fd).size + p; + // this.pos = cast Fs.fstatSync(fd).size + p; case SeekCur: // this.pos += p; } diff --git a/externs/air/sys/io/FileOutput.hx b/externs/air/sys/io/FileOutput.hx index cdd3ba2414..e0e96e9d57 100644 --- a/externs/air/sys/io/FileOutput.hx +++ b/externs/air/sys/io/FileOutput.hx @@ -31,9 +31,9 @@ class FileOutput extends haxe.io.Output switch (pos) { case SeekBegin: - // this.pos = p; + // this.pos = p; case SeekEnd: - // this.pos = cast Fs.fstatSync(fd).size + p; + // this.pos = cast Fs.fstatSync(fd).size + p; case SeekCur: // this.pos += p; } diff --git a/include.xml b/include.xml index 04f641e3c6..e38f58019f 100644 --- a/include.xml +++ b/include.xml @@ -24,6 +24,8 @@ + + diff --git a/project/Build.xml b/project/Build.xml index ef9bc7458d..84ef070811 100755 --- a/project/Build.xml +++ b/project/Build.xml @@ -35,10 +35,13 @@ + + + @@ -59,6 +62,10 @@ + + + + @@ -236,6 +243,7 @@ + @@ -270,6 +278,7 @@ + diff --git a/project/include/graphics/vulkan/VKRenderer.h b/project/include/graphics/vulkan/VKRenderer.h new file mode 100644 index 0000000000..ae2b0b8f69 --- /dev/null +++ b/project/include/graphics/vulkan/VKRenderer.h @@ -0,0 +1,160 @@ +#ifndef LIME_GRAPHICS_VULKAN_VKRENDERER_H +#define LIME_GRAPHICS_VULKAN_VKRENDERER_H + +#include +#include +#include +#include +#include + + +namespace lime { + + + class VulkanRenderer { + + public: + + explicit VulkanRenderer (Window* window); + ~VulkanRenderer (); + + bool ClearOverlay (); + bool Create (const char* applicationName); + void Destroy (); + bool Render (float red, float green, float blue, float alpha); + bool Resize (); + bool SetOverlay (const unsigned char* data, int width, int height, int x, int y); + + inline const std::string& GetInfo () const { return info; } + inline const std::string& GetLastError () const { return lastError; } + + private: + + bool CreateCommandBuffers (); + bool CreateCommandPool (); + bool CreateDevice (); + bool CreateFramebuffers (); + bool CreateImageViews (); + bool CreateInstance (const char* applicationName); + bool CreateOverlayBuffer (size_t requiredSize); + bool CreateRenderPass (); + bool CreateSurface (); + bool CreateSwapchain (); + bool CreateSwapchainResources (); + bool CreateSyncObjects (); + void DestroyOverlayResources (); + void DestroySwapchainResources (); + uint32_t FindMemoryType (uint32_t typeFilter, VkMemoryPropertyFlags properties); + bool LoadDeviceProcs (); + bool LoadGlobalProcs (); + bool LoadInstanceProcs (); + bool PickPhysicalDevice (); + bool RecordCommandBuffer (uint32_t imageIndex, float red, float green, float blue, float alpha); + bool RecreateSwapchain (); + void SetError (const std::string& value); + + Window* window; + std::string info; + std::string lastError; + + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; + PFN_vkAllocateMemory vkAllocateMemory; + PFN_vkBindBufferMemory vkBindBufferMemory; + PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage; + PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier; + PFN_vkCreateBuffer vkCreateBuffer; + PFN_vkCreateDevice vkCreateDevice; + PFN_vkCreateFence vkCreateFence; + PFN_vkCreateFramebuffer vkCreateFramebuffer; + PFN_vkCreateImageView vkCreateImageView; + PFN_vkCreateInstance vkCreateInstance; + PFN_vkCreateRenderPass vkCreateRenderPass; + PFN_vkCreateSemaphore vkCreateSemaphore; + PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR; + PFN_vkCreateCommandPool vkCreateCommandPool; + PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers; + PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; + PFN_vkBeginCommandBuffer vkBeginCommandBuffer; + PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass; + PFN_vkCmdEndRenderPass vkCmdEndRenderPass; + PFN_vkDestroyCommandPool vkDestroyCommandPool; + PFN_vkDestroyBuffer vkDestroyBuffer; + PFN_vkDestroyDevice vkDestroyDevice; + PFN_vkDestroyFence vkDestroyFence; + PFN_vkDestroyFramebuffer vkDestroyFramebuffer; + PFN_vkDestroyImageView vkDestroyImageView; + PFN_vkDestroyInstance vkDestroyInstance; + PFN_vkDestroyRenderPass vkDestroyRenderPass; + PFN_vkDestroySemaphore vkDestroySemaphore; + PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; + PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; + PFN_vkDeviceWaitIdle vkDeviceWaitIdle; + PFN_vkEndCommandBuffer vkEndCommandBuffer; + PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties; + PFN_vkFreeMemory vkFreeMemory; + PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements; + PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; + PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion; + PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; + PFN_vkGetDeviceQueue vkGetDeviceQueue; + PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; + PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; + PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties; + PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR; + PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR; + PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR; + PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR; + PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; + PFN_vkMapMemory vkMapMemory; + PFN_vkQueuePresentKHR vkQueuePresentKHR; + PFN_vkQueueSubmit vkQueueSubmit; + PFN_vkResetCommandPool vkResetCommandPool; + PFN_vkResetFences vkResetFences; + PFN_vkUnmapMemory vkUnmapMemory; + PFN_vkWaitForFences vkWaitForFences; + + VkInstance instance; + VkSurfaceKHR surface; + VkPhysicalDevice physicalDevice; + VkPhysicalDeviceProperties physicalDeviceProperties; + VkDevice device; + VkQueue queue; + uint32_t queueFamilyIndex; + VkSwapchainKHR swapchain; + VkFormat swapchainFormat; + VkPresentModeKHR swapchainPresentMode; + int requestedVSyncMode; + VkExtent2D swapchainExtent; + VkRenderPass renderPass; + VkCommandPool commandPool; + VkSemaphore imageAvailableSemaphore; + VkSemaphore renderFinishedSemaphore; + VkFence inFlightFence; + VkBuffer overlayBuffer; + VkDeviceMemory overlayBufferMemory; + bool portabilityEnumerationSupported; + bool portabilitySubsetSupported; + bool swapchainDirty; + size_t overlayBufferCapacity; + unsigned char* overlayMappedData; + uint32_t overlayWidth; + uint32_t overlayHeight; + int overlayX; + int overlayY; + bool overlayEnabled; + + std::vector instanceExtensions; + std::vector deviceExtensions; + std::vector swapchainImages; + std::vector swapchainImageViews; + std::vector framebuffers; + std::vector commandBuffers; + + }; + + +} + + +#endif diff --git a/project/include/media/AudioBuffer.h b/project/include/media/AudioBuffer.h index 5f9a8130e0..5cd3e476d9 100644 --- a/project/include/media/AudioBuffer.h +++ b/project/include/media/AudioBuffer.h @@ -40,6 +40,7 @@ namespace lime { vdynamic* __srcAudio; vdynamic* __srcBuffer; + int __srcBufferContext; vdynamic* __srcCustom; vdynamic* __srcHowl; bool __isDisposed; @@ -63,4 +64,4 @@ namespace lime { } -#endif \ No newline at end of file +#endif diff --git a/project/include/ui/FileDialog.h b/project/include/ui/FileDialog.h index 4a310b3198..1adf918f7b 100644 --- a/project/include/ui/FileDialog.h +++ b/project/include/ui/FileDialog.h @@ -9,14 +9,36 @@ namespace lime { + // Functions in this class return pointers to externally owned memory, which will be reused automatically + // for future dialogs and should not be freed. class FileDialog { public: - static std::wstring* OpenDirectory (std::wstring* title = 0, std::wstring* filter = 0, std::wstring* defaultPath = 0); - static std::wstring* OpenFile (std::wstring* title = 0, std::wstring* filter = 0, std::wstring* defaultPath = 0); - static void OpenFiles (std::vector* files, std::wstring* title = 0, std::wstring* filter = 0, std::wstring* defaultPath = 0); - static std::wstring* SaveFile (std::wstring* title = 0, std::wstring* filter = 0, std::wstring* defaultPath = 0); +#ifdef HX_WINDOWS + using char_t = wchar_t; +#else + using char_t = char; +#endif + + static const char_t* OpenDirectory(const char_t* title = nullptr, const char_t* filter = nullptr, const char_t* defaultPath = nullptr); + static const char_t* OpenFile(const char_t* title = nullptr, const char_t* filter = nullptr, const char_t* defaultPath = nullptr); + + // Use actual string view once we can use c++17 + class string_view { + public: + string_view(const char_t* c_str, size_t length) : c_str(c_str), length(length) {} + + const char_t* data() const { return c_str; } + size_t size() const { return length; } + + private: + const char_t* c_str; + size_t length; + }; + + static std::vector OpenFiles(const char_t* title = nullptr, const char_t* filter = nullptr, const char_t* defaultPath = nullptr); + static const char_t* SaveFile(const char_t* title = nullptr, const char_t* filter = nullptr, const char_t* defaultPath = nullptr); }; @@ -24,4 +46,4 @@ namespace lime { } -#endif \ No newline at end of file +#endif diff --git a/project/include/ui/GamepadEvent.h b/project/include/ui/GamepadEvent.h index 607ef9cfc8..5543da20c2 100644 --- a/project/include/ui/GamepadEvent.h +++ b/project/include/ui/GamepadEvent.h @@ -28,6 +28,7 @@ namespace lime { int id; GamepadEventType type; double axisValue; + int timestamp; static ValuePointer* callback; static ValuePointer* eventObject; @@ -42,4 +43,4 @@ namespace lime { } -#endif \ No newline at end of file +#endif diff --git a/project/include/ui/KeyEvent.h b/project/include/ui/KeyEvent.h index 28e6fcc6fd..8d5ac047c0 100644 --- a/project/include/ui/KeyEvent.h +++ b/project/include/ui/KeyEvent.h @@ -25,6 +25,7 @@ namespace lime { int modifier; KeyEventType type; int windowID; + int timestamp; static ValuePointer* callback; static ValuePointer* eventObject; @@ -39,4 +40,4 @@ namespace lime { } -#endif \ No newline at end of file +#endif diff --git a/project/include/ui/Window.h b/project/include/ui/Window.h index 04321be0b2..81afa74fae 100644 --- a/project/include/ui/Window.h +++ b/project/include/ui/Window.h @@ -11,8 +11,13 @@ #include #include #include +#include #include +#ifdef CreateWindow +#undef CreateWindow +#endif + namespace lime { @@ -68,7 +73,17 @@ namespace lime { virtual bool SetAlwaysOnTop (bool alwaysOnTop) = 0; virtual void WarpMouse (int x, int y) = 0; virtual int GetVSyncInterval () const { return 0; } + virtual int GetRequestedVSyncMode () const { return 0; } virtual double GetRefreshRate () const { return 60.0; } + virtual uint64_t CreateVulkanSurface (uintptr_t instance) { return 0; } + virtual void GetVulkanDrawableSize (int* width, int* height) { + + if (width) *width = 0; + if (height) *height = 0; + + } + virtual bool GetVulkanInstanceExtensions (unsigned int* count, const char** names) { return false; } + virtual void* GetVulkanInstanceProcAddr () { return 0; } Application* currentApplication; int flags; @@ -98,7 +113,9 @@ namespace lime { WINDOW_FLAG_MINIMIZED = 0x00002000, WINDOW_FLAG_MAXIMIZED = 0x00004000, WINDOW_FLAG_ALWAYS_ON_TOP = 0x00008000, - WINDOW_FLAG_COLOR_DEPTH_32_BIT = 0x00010000 + WINDOW_FLAG_COLOR_DEPTH_32_BIT = 0x00010000, + WINDOW_FLAG_VULKAN = 0x00020000, + WINDOW_FLAG_TRANSPARENT = 0x00040000 }; diff --git a/project/lib/custom/pixman/config.h b/project/lib/custom/pixman/pixman-config.h similarity index 87% rename from project/lib/custom/pixman/config.h rename to project/lib/custom/pixman/pixman-config.h index 0fa8ab453f..02ffd50113 100644 --- a/project/lib/custom/pixman/config.h +++ b/project/lib/custom/pixman/pixman-config.h @@ -15,9 +15,6 @@ 3. Update the version number(s) if they've changed. **/ -/* Define if building universal (internal helper macro) */ -/* #undef AC_APPLE_UNIVERSAL_BUILD */ - /* Whether we have alarm() */ #ifdef HX_LINUX #define HAVE_ALARM 1 @@ -32,13 +29,6 @@ /* #undef HAVE_BUILTIN_CLZ */ #endif -/* Define to 1 if you have the header file. */ -#ifndef HX_WINDOWS -#define HAVE_DLFCN_H 1 -#else -/* #undef HAVE_DLFCN_H */ -#endif - /* Whether we have FE_DIVBYZERO */ #ifdef HX_LINUX #define HAVE_FEDIVBYZERO 1 @@ -108,13 +98,6 @@ /* #undef HAVE_LIBPNG */ #endif -/* Define to 1 if you have the header file. */ -#ifdef HX_LINUX -#define HAVE_MEMORY_H 1 -#else -/* #undef HAVE_MEMORY_H */ -#endif - /* Whether we have mmap() */ #ifdef HX_LINUX #define HAVE_MMAP 1 @@ -200,24 +183,6 @@ /* Name of package */ #define PACKAGE "pixman" -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "pixman@lists.freedesktop.org" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "pixman" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "pixman 0.42.2" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "pixman" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "0.42.2" - /* enable output that can be piped to gnuplot */ /* #undef PIXMAN_GNUPLOT */ @@ -252,6 +217,12 @@ /* #undef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR */ #endif +#define ASM_HAVE_SYNTAX_UNIFIED + +#if defined(__APPLE__) +#define ASM_LEADING_UNDERSCORE 1 +#endif + /* use ARM A64_NEON assembly optimizations */ /* #undef USE_ARM_A64_NEON */ @@ -316,9 +287,6 @@ /* #undef USE_X86_MMX */ #endif -/* Version number of package */ -#define VERSION "0.42.2" - /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD @@ -336,6 +304,3 @@ #ifndef __cplusplus /* #undef inline */ #endif - -/* Define to sqrt if you do not have the `sqrtf' function. */ -/* #undef sqrtf */ diff --git a/project/lib/custom/pixman/pixman/pixman-version.h b/project/lib/custom/pixman/pixman/pixman-version.h index 23d30b5500..5767975fcd 100644 --- a/project/lib/custom/pixman/pixman/pixman-version.h +++ b/project/lib/custom/pixman/pixman/pixman-version.h @@ -32,10 +32,10 @@ #endif #define PIXMAN_VERSION_MAJOR 0 -#define PIXMAN_VERSION_MINOR 40 -#define PIXMAN_VERSION_MICRO 1 +#define PIXMAN_VERSION_MINOR 44 +#define PIXMAN_VERSION_MICRO 2 -#define PIXMAN_VERSION_STRING "0.40.1" +#define PIXMAN_VERSION_STRING "0.44.2" #define PIXMAN_VERSION_ENCODE(major, minor, micro) ( \ ((major) * 10000) \ diff --git a/project/lib/custom/sdl/include/SDL_config_linux.h b/project/lib/custom/sdl/include/SDL_config_linux.h index fc5213ebc9..54a9fe5b30 100644 --- a/project/lib/custom/sdl/include/SDL_config_linux.h +++ b/project/lib/custom/sdl/include/SDL_config_linux.h @@ -308,6 +308,9 @@ /* #undef SDL_VIDEO_OPENGL_OSMESA */ /* #undef SDL_VIDEO_OPENGL_OSMESA_DYNAMIC */ +/* Enable Vulkan support */ +#define SDL_VIDEO_VULKAN 1 + /* Enable system power support */ #define SDL_POWER_LINUX 1 /* #undef SDL_POWER_WINDOWS */ diff --git a/project/lib/pixman b/project/lib/pixman index 37216a3283..46655e1567 160000 --- a/project/lib/pixman +++ b/project/lib/pixman @@ -1 +1 @@ -Subproject commit 37216a32839f59e8dcaa4c3951b3fcfc3f07852c +Subproject commit 46655e15671e1ca62d699821d75a85d341d7229c diff --git a/project/lib/pixman-files.xml b/project/lib/pixman-files.xml index ef98744568..cd266b1f0a 100644 --- a/project/lib/pixman-files.xml +++ b/project/lib/pixman-files.xml @@ -1,16 +1,12 @@ - - - + + -
- - -
+ @@ -22,6 +18,7 @@ + @@ -39,7 +36,9 @@ - + + + @@ -73,6 +72,7 @@ +
diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 0fcb20e6e7..2f6abcb4a8 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -16,6 +16,9 @@ #include #include #include +#ifdef LIME_VULKAN +#include +#endif #include #include #include @@ -55,8 +58,12 @@ #endif #include +#include #include +#include #include +#include +#include #ifdef LIME_SDL_SOUND #include @@ -67,3470 +74,12621 @@ DEFINE_KIND (k_finalizer); namespace lime { + static std::string lastVulkanRendererError; + static std::string lastVKError; - void gc_application (value handle) { - - Application* application = (Application*)val_data (handle); - delete application; - } + static void LogVulkanNativeBootstrap (const char* message) { +#ifdef LIME_VULKAN + ::FILE* file = ::fopen ("lime-vulkan-native.log", "a"); + if (file) { - void hl_gc_application (HL_CFFIPointer* handle) { + ::fprintf (file, "%s\n", message ? message : ""); + ::fclose (file); - Application* application = (Application*)handle->ptr; - delete application; + } +#endif } - void gc_file_watcher (value handle) { + static void LogVulkanNativeBootstrap (const std::string& message) { - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)val_data (handle); - delete watcher; - #endif + LogVulkanNativeBootstrap (message.c_str ()); } - void hl_gc_file_watcher (HL_CFFIPointer* handle) { + static uint64_t CombineVulkanHandle (int high, int low) { - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)handle->ptr; - delete watcher; - #endif + return ((uint64_t)(uint32_t)high << 32) | (uint32_t)low; } - void gc_font (value handle) { + static value CreateVulkanHandleValue (uint64_t handleValue) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (handle); - delete font; - #endif + value result = alloc_empty_object (); + alloc_field (result, val_id ("low"), alloc_int ((int32_t)(handleValue & 0xFFFFFFFFULL))); + alloc_field (result, val_id ("high"), alloc_int ((int32_t)(handleValue >> 32))); + return result; } - void hl_gc_font (HL_CFFIPointer* handle) { + static vdynamic* HLCreateVulkanHandleValue (uint64_t handleValue) { - #ifdef LIME_FREETYPE - Font* font = (Font*)handle->ptr; - delete font; - #endif + const int id_low = hl_hash_utf8 ("low"); + const int id_high = hl_hash_utf8 ("high"); + vdynamic* result = (vdynamic*)hl_alloc_dynobj (); + hl_dyn_seti (result, id_low, &hlt_i32, (int32_t)(handleValue & 0xFFFFFFFFULL)); + hl_dyn_seti (result, id_high, &hlt_i32, (int32_t)(handleValue >> 32)); + return result; } - void gc_window (value handle) { +#ifdef LIME_VULKAN + static VkSurfaceKHR UInt64ToVulkanSurface (uint64_t value) { - Window* window = (Window*)val_data (handle); - delete window; + return (VkSurfaceKHR)value; } - void hl_gc_window (HL_CFFIPointer* handle) { - - Window* window = (Window*)handle->ptr; - delete window; + struct ManagedVulkanMappedMemory { - } + VkDevice device; + VkDeviceMemory memory; + VkDeviceSize offset; + VkDeviceSize size; + void* data; + }; - std::string wstring_utf8 (const std::wstring& val) { - std::string out; - unsigned int codepoint = 0; + static std::unordered_map mappedVulkanMemory; + static std::unordered_map > managedVulkanDeviceProcCache; - for (const wchar_t chr : val) { - if (chr >= 0xd800 && chr <= 0xdbff) { + static uint64_t GetManagedVulkanMappedMemoryKey (VkDeviceMemory memory) { - codepoint = ((chr - 0xd800) << 10) + 0x10000; + return (uint64_t)(uintptr_t)memory; - } else { + } - if (chr >= 0xdc00 && chr <= 0xdfff) { - codepoint |= chr - 0xdc00; + static VkDeviceSize NormalizeVulkanRangeSize (uint64_t size) { - } else { + return size == 0 ? VK_WHOLE_SIZE : (VkDeviceSize)size; - codepoint = chr; + } - } - if (codepoint <= 0x7f) { + static void ClearManagedVulkanDeviceProcCache (VkDevice device) { - out.append (1, static_cast (codepoint)); + if (device) managedVulkanDeviceProcCache.erase ((uint64_t)(uintptr_t)device); - } else if (codepoint <= 0x7ff) { + } - out.append (1, static_cast (0xc0 | ((codepoint >> 6) & 0x1f))); - out.append (1, static_cast (0x80 | (codepoint & 0x3f))); - } else if (codepoint <= 0xffff) { + static bool CreateManagedVulkanInstance (Window* targetWindow, const char* applicationName, VkInstance* outInstance) { - out.append (1, static_cast (0xe0 | ((codepoint >> 12) & 0x0f))); - out.append (1, static_cast (0x80 | ((codepoint >> 6) & 0x3f))); - out.append (1, static_cast (0x80 | (codepoint & 0x3f))); + if (!targetWindow || !outInstance) { - } else { + lastVKError = "Missing Vulkan window or output instance"; + return false; - out.append (1, static_cast (0xf0 | ((codepoint >> 18) & 0x07))); - out.append (1, static_cast (0x80 | ((codepoint >> 12) & 0x3f))); - out.append (1, static_cast (0x80 | ((codepoint >> 6) & 0x3f))); - out.append (1, static_cast (0x80 | (codepoint & 0x3f))); + } - } + *outInstance = VK_NULL_HANDLE; - codepoint = 0; + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + if (!vkGetInstanceProcAddr) { - } + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + return false; } - return out; + PFN_vkCreateInstance vkCreateInstance = (PFN_vkCreateInstance)vkGetInstanceProcAddr (VK_NULL_HANDLE, "vkCreateInstance"); + PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties = + (PFN_vkEnumerateInstanceExtensionProperties)vkGetInstanceProcAddr (VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties"); + PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion = + (PFN_vkEnumerateInstanceVersion)vkGetInstanceProcAddr (VK_NULL_HANDLE, "vkEnumerateInstanceVersion"); - } + if (!vkCreateInstance || !vkEnumerateInstanceExtensionProperties) { + lastVKError = "Missing required Vulkan global functions"; + return false; - vbyte* hl_wstring_to_utf8_bytes (const std::wstring& val) { + } - const std::string utf8 (wstring_utf8 (val)); - vbyte* const bytes = hl_alloc_bytes (utf8.size () + 1); - std::memcpy(bytes, utf8.c_str (), utf8.size () + 1); - return bytes; + unsigned int requiredExtensionCount = 0; + if (!targetWindow->GetVulkanInstanceExtensions (&requiredExtensionCount, 0)) { - } + lastVKError = "Failed to query required Vulkan window extensions"; + return false; + } - std::wstring* hxstring_to_wstring (HxString val) { + std::vector requiredExtensions (requiredExtensionCount); + if (requiredExtensionCount > 0 && !targetWindow->GetVulkanInstanceExtensions (&requiredExtensionCount, requiredExtensions.data ())) { - if (val.c_str ()) { + lastVKError = "Failed to fetch required Vulkan window extensions"; + return false; - #ifdef HX_WINDOWS - return new std::wstring (hxs_wchar (val, nullptr)); - #else - const std::string _val (hxs_utf8 (val, nullptr)); - return new std::wstring (_val.begin (), _val.end ()); - #endif + } - } else { + std::vector instanceExtensions; + for (size_t i = 0; i < requiredExtensions.size (); ++i) { - return 0; + instanceExtensions.push_back (requiredExtensions[i]); } - } - + bool portabilityEnumerationSupported = false; + uint32_t availableExtensionCount = 0; + if (vkEnumerateInstanceExtensionProperties (0, &availableExtensionCount, 0) == VK_SUCCESS && availableExtensionCount > 0) { - std::wstring* hxstring_to_wstring (hl_vstring* val) { - - if (val) { + std::vector availableExtensions (availableExtensionCount); + if (vkEnumerateInstanceExtensionProperties (0, &availableExtensionCount, availableExtensions.data ()) == VK_SUCCESS) { - std::string _val = std::string (hl_to_utf8 (val->bytes)); - #ifdef HX_WINDOWS - std::wstring_convert> converter; - return new std::wstring (converter.from_bytes (_val)); - #else - return new std::wstring (_val.begin (), _val.end ()); - #endif + for (size_t i = 0; i < availableExtensions.size (); ++i) { - } else { + #ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME + if (strcmp (availableExtensions[i].extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) { - return 0; + portabilityEnumerationSupported = true; - } + } + #endif - } + } + } - value wstring_to_value (std::wstring* val) { + } - if (val) { + if (portabilityEnumerationSupported) { - #ifdef HX_WINDOWS - return alloc_wstring (val->c_str ()); - #else - std::string _val = std::string (val->begin (), val->end ()); - return alloc_string (_val.c_str ()); + #ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME + instanceExtensions.push_back (VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); #endif - } else { - - return 0; - } - } + uint32_t instanceVersion = VK_API_VERSION_1_0; + if (vkEnumerateInstanceVersion) { + vkEnumerateInstanceVersion (&instanceVersion); - value lime_application_create () { + } - Application* application = CreateApplication (); - return CFFIPointer (application, gc_application); + VkApplicationInfo applicationInfo; + memset (&applicationInfo, 0, sizeof (applicationInfo)); + applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + applicationInfo.pApplicationName = applicationName ? applicationName : "Lime"; + applicationInfo.pEngineName = "Lime"; + applicationInfo.applicationVersion = VK_MAKE_VERSION (1, 0, 0); + applicationInfo.engineVersion = VK_MAKE_VERSION (1, 0, 0); + applicationInfo.apiVersion = instanceVersion >= VK_API_VERSION_1_0 ? VK_API_VERSION_1_0 : instanceVersion; - } + VkInstanceCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &applicationInfo; + createInfo.enabledExtensionCount = (uint32_t)instanceExtensions.size (); + createInfo.ppEnabledExtensionNames = instanceExtensions.empty () ? 0 : instanceExtensions.data (); + #ifdef VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR + if (portabilityEnumerationSupported) { - HL_PRIM HL_CFFIPointer* HL_NAME(hl_application_create) () { + createInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; - Application* application = CreateApplication (); - return HLCFFIPointer (application, (hl_finalizer)hl_gc_application); + } + #endif - } + VkResult result = vkCreateInstance (&createInfo, 0, outInstance); + if (result != VK_SUCCESS) { + lastVKError = "vkCreateInstance failed"; + return false; - void lime_application_event_manager_register (value callback, value eventObject) { + } - ApplicationEvent::callback = new ValuePointer (callback); - ApplicationEvent::eventObject = new ValuePointer (eventObject); + lastVKError.clear (); + return true; } - HL_PRIM void HL_NAME(hl_application_event_manager_register) (vclosure* callback, ApplicationEvent* eventObject) { - - ApplicationEvent::callback = new ValuePointer (callback); - ApplicationEvent::eventObject = new ValuePointer ((vobj*)eventObject); + static std::vector GetVulkanDeviceExtensions (value extensions) { - } + std::vector deviceExtensions; + if (val_is_null (extensions)) { - int lime_application_exec (value application) { + deviceExtensions.push_back (VK_KHR_SWAPCHAIN_EXTENSION_NAME); + return deviceExtensions; - Application* app = (Application*)val_data (application); - return app->Exec (); + } - } + int length = val_array_size (extensions); + for (int i = 0; i < length; ++i) { + value extension = val_array_i (extensions, i); + if (!val_is_null (extension)) { - HL_PRIM int HL_NAME(hl_application_exec) (HL_CFFIPointer* application) { + deviceExtensions.push_back (val_string (extension)); - Application* app = (Application*)application->ptr; - return app->Exec (); + } - } + } + return deviceExtensions; - void lime_application_init (value application) { + } - Application* app = (Application*)val_data (application); - app->Init (); - } + static std::vector GetHLVulkanDeviceExtensions (hl_varray* extensions) { + std::vector deviceExtensions; - HL_PRIM void HL_NAME(hl_application_init) (HL_CFFIPointer* application) { + if (!extensions) { - Application* app = (Application*)application->ptr; - app->Init (); + deviceExtensions.push_back (VK_KHR_SWAPCHAIN_EXTENSION_NAME); + return deviceExtensions; - } + } + int length = extensions->size; + hl_vstring** extensionData = hl_aptr (extensions, hl_vstring*); - int lime_application_quit (value application) { + for (int i = 0; i < length; ++i) { - Application* app = (Application*)val_data (application); - return app->Quit (); + hl_vstring* extension = *extensionData++; + if (extension) { - } + deviceExtensions.push_back (hl_to_utf8 ((const uchar*)extension->bytes)); + } - HL_PRIM int HL_NAME(hl_application_quit) (HL_CFFIPointer* application) { + } - Application* app = (Application*)application->ptr; - return app->Quit (); + return deviceExtensions; } - void lime_application_set_frame_rate (value application, double frameRate) { - - Application* app = (Application*)val_data (application); - app->SetFrameRate (frameRate); + static PFN_vkVoidFunction GetManagedVulkanDeviceProc (Window* targetWindow, VkInstance instance, VkDevice device, const char* name) { - } + if (!targetWindow || !instance || !device || !name) { + lastVKError = "Missing Vulkan window, instance, or device"; + return 0; - HL_PRIM void HL_NAME(hl_application_set_frame_rate) (HL_CFFIPointer* application, double frameRate) { + } - Application* app = (Application*)application->ptr; - app->SetFrameRate (frameRate); + uint64_t deviceKey = (uint64_t)(uintptr_t)device; + std::string procName (name); + std::unordered_map >::iterator deviceCache = + managedVulkanDeviceProcCache.find (deviceKey); + if (deviceCache != managedVulkanDeviceProcCache.end ()) { - } + std::unordered_map::iterator procCache = deviceCache->second.find (procName); + if (procCache != deviceCache->second.end ()) return procCache->second; + } - void lime_application_set_main_loop (value application, int profile, double frameRate, int timePrecision, int busyWait, int uncapMode) { + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + if (!vkGetInstanceProcAddr) { - Application* app = (Application*)val_data (application); - app->SetMainLoop (profile, frameRate, timePrecision, busyWait, uncapMode); + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + return 0; - } + } + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) { - HL_PRIM void HL_NAME(hl_application_set_main_loop) (HL_CFFIPointer* application, int profile, double frameRate, int timePrecision, int busyWait, int uncapMode) { + lastVKError = "Missing Vulkan device proc address function"; + return 0; - Application* app = (Application*)application->ptr; - app->SetMainLoop (profile, frameRate, timePrecision, busyWait, uncapMode); + } - } + PFN_vkVoidFunction proc = vkGetDeviceProcAddr (device, procName.c_str ()); + if (!proc) { + lastVKError = std::string ("Missing Vulkan device function: ") + procName; + return 0; - void lime_application_set_vsync_mode (value application, int vsyncMode) { + } - Application* app = (Application*)val_data (application); - app->SetVSyncMode (vsyncMode); + managedVulkanDeviceProcCache[deviceKey][procName] = proc; + return proc; } - HL_PRIM void HL_NAME(hl_application_set_vsync_mode) (HL_CFFIPointer* application, int vsyncMode) { + static bool UpdateManagedVulkanDescriptorSets (Window* targetWindow, VkInstance instance, VkDevice device, const std::vector& packed) { - Application* app = (Application*)application->ptr; - app->SetVSyncMode (vsyncMode); + if (packed.empty ()) return true; - } + PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets = + (PFN_vkUpdateDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUpdateDescriptorSets"); + if (!vkUpdateDescriptorSets) return false; + int writeCount = packed[0]; + if (writeCount < 0) return false; - bool lime_application_update (value application) { + std::vector bufferInfos; + std::vector imageInfos; + std::vector descriptorWrites; + bufferInfos.reserve ((size_t)writeCount); + imageInfos.reserve ((size_t)writeCount); + descriptorWrites.reserve ((size_t)writeCount); - Application* app = (Application*)val_data (application); - return app->Update (); + size_t index = 1; + for (int i = 0; i < writeCount; ++i) { - } + if (index >= packed.size ()) return false; + int kind = packed[index++]; + VkWriteDescriptorSet write; + memset (&write, 0, sizeof (write)); + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.descriptorCount = 1; - HL_PRIM bool HL_NAME(hl_application_update) (HL_CFFIPointer* application) { + if (kind == 0) { - Application* app = (Application*)application->ptr; - return app->Update (); + if (index + 11 > packed.size ()) return false; + write.dstSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (packed[index], packed[index + 1]); + write.dstBinding = (uint32_t)packed[index + 2]; + write.dstArrayElement = (uint32_t)packed[index + 3]; + write.descriptorType = (VkDescriptorType)packed[index + 4]; - } + VkDescriptorBufferInfo bufferInfo; + memset (&bufferInfo, 0, sizeof (bufferInfo)); + bufferInfo.buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (packed[index + 5], packed[index + 6]); + bufferInfo.offset = (VkDeviceSize)CombineVulkanHandle (packed[index + 7], packed[index + 8]); + bufferInfo.range = NormalizeVulkanRangeSize (CombineVulkanHandle (packed[index + 9], packed[index + 10])); + bufferInfos.push_back (bufferInfo); + write.pBufferInfo = &bufferInfos[bufferInfos.size () - 1]; + index += 11; + } else if (kind == 1) { - value lime_audio_load_bytes (value data, value buffer) { + if (index + 10 > packed.size ()) return false; + write.dstSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (packed[index], packed[index + 1]); + write.dstBinding = (uint32_t)packed[index + 2]; + write.dstArrayElement = (uint32_t)packed[index + 3]; + write.descriptorType = (VkDescriptorType)packed[index + 4]; - Resource resource; - Bytes bytes; + VkDescriptorImageInfo imageInfo; + memset (&imageInfo, 0, sizeof (imageInfo)); + imageInfo.imageView = (VkImageView)(uintptr_t)CombineVulkanHandle (packed[index + 5], packed[index + 6]); + imageInfo.sampler = (VkSampler)(uintptr_t)CombineVulkanHandle (packed[index + 7], packed[index + 8]); + imageInfo.imageLayout = (VkImageLayout)packed[index + 9]; + imageInfos.push_back (imageInfo); + write.pImageInfo = &imageInfos[imageInfos.size () - 1]; + index += 10; - AudioBuffer audioBuffer = AudioBuffer (buffer); + } else { - bytes.Set (data); - resource = Resource (&bytes); + lastVKError = "Invalid Vulkan descriptor write kind"; + return false; - #ifdef LIME_SDL_SOUND - if (SDLSound::Decode (&resource, &audioBuffer)) { + } - return audioBuffer.Value (buffer); + if (!write.dstSet) return false; + descriptorWrites.push_back (write); } - #endif + vkUpdateDescriptorSets (device, (uint32_t)descriptorWrites.size (), descriptorWrites.empty () ? 0 : descriptorWrites.data (), 0, 0); + lastVKError.clear (); + return true; - if (WAV::Decode (&resource, &audioBuffer)) { + } - return audioBuffer.Value (buffer); - } + static bool CreateManagedVulkanDevice (Window* targetWindow, VkInstance instance, VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, + const std::vector& requestedExtensions, VkDevice* outDevice, VkQueue* outQueue) { - #ifdef LIME_OGG - if (OGG::Decode (&resource, &audioBuffer)) { + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: begin"); + if (!targetWindow || !instance || !physicalDevice || !outDevice || !outQueue) { - return audioBuffer.Value (buffer); + lastVKError = "Missing Vulkan instance, physical device, or output device"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: missing input"); + return false; } - #endif - return alloc_null (); + *outDevice = VK_NULL_HANDLE; + *outQueue = VK_NULL_HANDLE; - } + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: acquired vkGetInstanceProcAddr"); + if (!vkGetInstanceProcAddr) { + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: missing vkGetInstanceProcAddr"); + return false; - HL_PRIM AudioBuffer* HL_NAME(hl_audio_load_bytes) (Bytes* data, AudioBuffer* buffer) { + } - Resource resource = Resource (data); + PFN_vkCreateDevice vkCreateDevice = (PFN_vkCreateDevice)vkGetInstanceProcAddr (instance, "vkCreateDevice"); + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties = + (PFN_vkEnumerateDeviceExtensionProperties)vkGetInstanceProcAddr (instance, "vkEnumerateDeviceExtensionProperties"); + PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties = + (PFN_vkGetPhysicalDeviceQueueFamilyProperties)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceQueueFamilyProperties"); + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: loaded device creation procs"); - #ifdef LIME_SDL_SOUND - if (SDLSound::Decode (&resource, buffer)) { + if (!vkCreateDevice || !vkGetDeviceProcAddr || !vkEnumerateDeviceExtensionProperties || !vkGetPhysicalDeviceQueueFamilyProperties) { - return buffer; + lastVKError = "Missing required Vulkan device creation functions"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: missing required procs"); + return false; } - #endif - if (WAV::Decode (&resource, buffer)) { + uint32_t queueFamilyCount = 0; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: query queue family count"); + vkGetPhysicalDeviceQueueFamilyProperties (physicalDevice, &queueFamilyCount, 0); + if (queueFamilyIndex >= queueFamilyCount) { - return buffer; + lastVKError = "Invalid Vulkan queue family index"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: invalid queue family index"); + return false; } - #ifdef LIME_OGG - if (OGG::Decode (&resource, buffer)) { - - return buffer; + float queuePriority = 1.0f; + VkDeviceQueueCreateInfo queueCreateInfo; + memset (&queueCreateInfo, 0, sizeof (queueCreateInfo)); + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.queueFamilyIndex = queueFamilyIndex; + queueCreateInfo.queueCount = 1; + queueCreateInfo.pQueuePriorities = &queuePriority; - } - #endif + std::vector deviceExtensions; + for (size_t i = 0; i < requestedExtensions.size (); ++i) { - return 0; + deviceExtensions.push_back (requestedExtensions[i].c_str ()); - } + } + uint32_t extensionCount = 0; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: enumerate device extension count"); + VkResult extensionResult = vkEnumerateDeviceExtensionProperties (physicalDevice, 0, &extensionCount, 0); + if (extensionResult != VK_SUCCESS) { - value lime_audio_load_file (value data, value buffer) { + lastVKError = "Could not enumerate Vulkan device extensions"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: extension count enumeration failed"); + return false; - Resource resource; + } - AudioBuffer audioBuffer = AudioBuffer (buffer); + std::vector availableExtensions (extensionCount); + if (extensionCount > 0) { - resource = Resource (val_string (data)); + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: enumerate device extensions"); + extensionResult = vkEnumerateDeviceExtensionProperties (physicalDevice, 0, &extensionCount, availableExtensions.data ()); + if (extensionResult != VK_SUCCESS) { - #ifdef LIME_SDL_SOUND - if (SDLSound::Decode (&resource, &audioBuffer)) { + lastVKError = "Could not enumerate Vulkan device extensions"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: extension enumeration failed"); + return false; - return audioBuffer.Value (buffer); + } } + + #ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME + bool portabilitySubsetSupported = false; + bool portabilitySubsetRequested = false; #endif - if (WAV::Decode (&resource, &audioBuffer)) { + for (size_t i = 0; i < requestedExtensions.size (); ++i) { - return audioBuffer.Value (buffer); + bool extensionSupported = false; - } + for (size_t e = 0; e < availableExtensions.size (); ++e) { - #ifdef LIME_OGG - if (OGG::Decode (&resource, &audioBuffer)) { + if (strcmp (availableExtensions[e].extensionName, requestedExtensions[i].c_str ()) == 0) { - return audioBuffer.Value (buffer); + extensionSupported = true; + break; - } - #endif + } - return alloc_null (); + } - } + if (!extensionSupported) { + lastVKError = std::string ("Vulkan physical device does not support ") + requestedExtensions[i]; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: requested extension missing"); + return false; - HL_PRIM AudioBuffer* HL_NAME(hl_audio_load_file) (hl_vstring* data, AudioBuffer* buffer) { + } - Resource resource = Resource (data ? hl_to_utf8 ((const uchar*)data->bytes) : NULL); + #ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME + if (strcmp (requestedExtensions[i].c_str (), VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0) { - #ifdef LIME_SDL_SOUND - if (SDLSound::Decode (&resource, buffer)) { + portabilitySubsetRequested = true; - return buffer; + } + #endif } - #endif - if (WAV::Decode (&resource, buffer)) { - - return buffer; + #ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME + for (size_t i = 0; i < availableExtensions.size (); ++i) { - } + if (strcmp (availableExtensions[i].extensionName, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0) { - #ifdef LIME_OGG - if (OGG::Decode (&resource, buffer)) { + portabilitySubsetSupported = true; + break; - return buffer; + } } - #endif - - return 0; - } + if (portabilitySubsetSupported && !portabilitySubsetRequested) { + deviceExtensions.push_back (VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); - value lime_audio_load (value data, value buffer) { + } + #endif - if (val_is_string (data)) { + VkPhysicalDeviceFeatures deviceFeatures; + memset (&deviceFeatures, 0, sizeof (deviceFeatures)); - return lime_audio_load_file (data, buffer); + VkDeviceCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + createInfo.queueCreateInfoCount = 1; + createInfo.pQueueCreateInfos = &queueCreateInfo; + createInfo.pEnabledFeatures = &deviceFeatures; + createInfo.enabledExtensionCount = (uint32_t)deviceExtensions.size (); + createInfo.ppEnabledExtensionNames = deviceExtensions.empty () ? 0 : deviceExtensions.data (); - } else { + VkResult result = vkCreateDevice (physicalDevice, &createInfo, 0, outDevice); + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: returned from vkCreateDevice"); + if (result != VK_SUCCESS) { - return lime_audio_load_bytes (data, buffer); + lastVKError = "vkCreateDevice failed"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: vkCreateDevice failed"); + return false; } - } - + PFN_vkGetDeviceQueue vkGetDeviceQueue = (PFN_vkGetDeviceQueue)vkGetDeviceProcAddr (*outDevice, "vkGetDeviceQueue"); + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: loaded vkGetDeviceQueue"); + if (!vkGetDeviceQueue) { - value lime_bytes_from_data_pointer (double data, int length, value _bytes) { + PFN_vkDestroyDevice vkDestroyDevice = (PFN_vkDestroyDevice)vkGetDeviceProcAddr (*outDevice, "vkDestroyDevice"); + if (vkDestroyDevice) vkDestroyDevice (*outDevice, 0); + *outDevice = VK_NULL_HANDLE; + lastVKError = "Missing Vulkan device queue function"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: missing vkGetDeviceQueue"); + return false; - uintptr_t ptr = (uintptr_t)data; - Bytes bytes (_bytes); - bytes.Resize (length); + } - if (ptr) { + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: get device queue"); + vkGetDeviceQueue (*outDevice, queueFamilyIndex, 0, outQueue); + if (!*outQueue) { - memcpy (bytes.b, (const void*)ptr, length); + PFN_vkDestroyDevice vkDestroyDevice = (PFN_vkDestroyDevice)vkGetDeviceProcAddr (*outDevice, "vkDestroyDevice"); + if (vkDestroyDevice) vkDestroyDevice (*outDevice, 0); + *outDevice = VK_NULL_HANDLE; + lastVKError = "Failed to get Vulkan device queue"; + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: device queue was null"); + return false; } - return bytes.Value (_bytes); + lastVKError.clear (); + LogVulkanNativeBootstrap ("CreateManagedVulkanDevice: success"); + return true; } - HL_PRIM Bytes* HL_NAME(hl_bytes_from_data_pointer) (double data, int length, Bytes* bytes) { + struct ManagedVulkanSwapchain { - uintptr_t ptr = (uintptr_t)data; - bytes->Resize (length); + VkSwapchainKHR handle; + VkFormat format; + VkColorSpaceKHR colorSpace; + VkExtent2D extent; + VkPresentModeKHR presentMode; + uint32_t imageCount; - if (ptr) { + }; - memcpy (bytes->b, (const void*)ptr, length); - } + static VkPresentModeKHR ChooseManagedVulkanPresentMode (const std::vector& presentModes, VkPresentModeKHR requestedPresentMode) { - return bytes; + bool hasRequested = false; + bool hasFifo = false; + bool hasMailbox = false; + bool hasImmediate = false; - } + for (size_t i = 0; i < presentModes.size (); ++i) { + if (presentModes[i] == requestedPresentMode) hasRequested = true; + if (presentModes[i] == VK_PRESENT_MODE_FIFO_KHR) hasFifo = true; + if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) hasMailbox = true; + if (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) hasImmediate = true; - double lime_bytes_get_data_pointer (value bytes) { + } - Bytes data = Bytes (bytes); - return (uintptr_t)data.b; + if (hasRequested) return requestedPresentMode; + if (hasFifo) return VK_PRESENT_MODE_FIFO_KHR; + if (hasMailbox) return VK_PRESENT_MODE_MAILBOX_KHR; + if (hasImmediate) return VK_PRESENT_MODE_IMMEDIATE_KHR; + return VK_PRESENT_MODE_FIFO_KHR; } - HL_PRIM double HL_NAME(hl_bytes_get_data_pointer) (Bytes* bytes) { + static value CreateVulkanSwapchainValue (const ManagedVulkanSwapchain& swapchain) { - return bytes ? (uintptr_t)bytes->b : 0; + value result = alloc_empty_object (); + alloc_field (result, val_id ("handle"), CreateVulkanHandleValue ((uint64_t)(uintptr_t)swapchain.handle)); + alloc_field (result, val_id ("format"), alloc_int ((int)swapchain.format)); + alloc_field (result, val_id ("colorSpace"), alloc_int ((int)swapchain.colorSpace)); + alloc_field (result, val_id ("width"), alloc_int ((int)swapchain.extent.width)); + alloc_field (result, val_id ("height"), alloc_int ((int)swapchain.extent.height)); + alloc_field (result, val_id ("imageCount"), alloc_int ((int)swapchain.imageCount)); + alloc_field (result, val_id ("presentMode"), alloc_int ((int)swapchain.presentMode)); + return result; } - double lime_bytes_get_data_pointer_offset (value bytes, int offset) { + static vdynamic* HLCreateVulkanSwapchainValue (const ManagedVulkanSwapchain& swapchain) { - if (val_is_null (bytes)) return 0; + const int id_handle = hl_hash_utf8 ("handle"); + const int id_format = hl_hash_utf8 ("format"); + const int id_colorSpace = hl_hash_utf8 ("colorSpace"); + const int id_width = hl_hash_utf8 ("width"); + const int id_height = hl_hash_utf8 ("height"); + const int id_imageCount = hl_hash_utf8 ("imageCount"); + const int id_presentMode = hl_hash_utf8 ("presentMode"); - Bytes data = Bytes (bytes); - return (uintptr_t)data.b + offset; + vdynamic* result = (vdynamic*)hl_alloc_dynobj (); + hl_dyn_setp (result, id_handle, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)swapchain.handle)); + hl_dyn_seti (result, id_format, &hlt_i32, (int)swapchain.format); + hl_dyn_seti (result, id_colorSpace, &hlt_i32, (int)swapchain.colorSpace); + hl_dyn_seti (result, id_width, &hlt_i32, (int)swapchain.extent.width); + hl_dyn_seti (result, id_height, &hlt_i32, (int)swapchain.extent.height); + hl_dyn_seti (result, id_imageCount, &hlt_i32, (int)swapchain.imageCount); + hl_dyn_seti (result, id_presentMode, &hlt_i32, (int)swapchain.presentMode); + return result; } - HL_PRIM double HL_NAME(hl_bytes_get_data_pointer_offset) (Bytes* bytes, int offset) { + static value CreateVulkanAcquireValue (VkResult acquireResult, int imageIndex) { - if (!bytes) return 0; - return (uintptr_t)bytes->b + offset; + value result = alloc_empty_object (); + alloc_field (result, val_id ("result"), alloc_int ((int)acquireResult)); + alloc_field (result, val_id ("imageIndex"), alloc_int (imageIndex)); + return result; } - value lime_bytes_read_file (HxString path, value bytes) { - - Bytes data (bytes); - data.ReadFile (hxs_utf8 (path, nullptr)); - return data.Value (bytes); - - } - + static vdynamic* HLCreateVulkanAcquireValue (VkResult acquireResult, int imageIndex) { - HL_PRIM Bytes* HL_NAME(hl_bytes_read_file) (hl_vstring* path, Bytes* bytes) { + const int id_result = hl_hash_utf8 ("result"); + const int id_imageIndex = hl_hash_utf8 ("imageIndex"); - if (!path) return 0; - bytes->ReadFile (hl_to_utf8 ((const uchar*)path->bytes)); - return bytes; + vdynamic* result = (vdynamic*)hl_alloc_dynobj (); + hl_dyn_seti (result, id_result, &hlt_i32, (int)acquireResult); + hl_dyn_seti (result, id_imageIndex, &hlt_i32, imageIndex); + return result; } - double lime_cffi_get_native_pointer (value handle) { + static value CreateVulkanMemoryRequirementsValue (const VkMemoryRequirements& requirements) { - return (uintptr_t)val_data (handle); + value result = alloc_empty_object (); + alloc_field (result, val_id ("size"), CreateVulkanHandleValue ((uint64_t)requirements.size)); + alloc_field (result, val_id ("alignment"), CreateVulkanHandleValue ((uint64_t)requirements.alignment)); + alloc_field (result, val_id ("memoryTypeBits"), alloc_int ((int)requirements.memoryTypeBits)); + return result; } - HL_PRIM double HL_NAME(hl_cffi_get_native_pointer) (HL_CFFIPointer* handle) { + static vdynamic* HLCreateVulkanMemoryRequirementsValue (const VkMemoryRequirements& requirements) { - return (uintptr_t)handle->ptr; + const int id_size = hl_hash_utf8 ("size"); + const int id_alignment = hl_hash_utf8 ("alignment"); + const int id_memoryTypeBits = hl_hash_utf8 ("memoryTypeBits"); + + vdynamic* result = (vdynamic*)hl_alloc_dynobj (); + hl_dyn_setp (result, id_size, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)requirements.size)); + hl_dyn_setp (result, id_alignment, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)requirements.alignment)); + hl_dyn_seti (result, id_memoryTypeBits, &hlt_i32, (int)requirements.memoryTypeBits); + return result; } - void lime_cffi_finalizer (value abstract) { + static value CreateVulkanMemoryValue (VkDeviceMemory memory, uint32_t memoryTypeIndex) { - val_call0 ((value)val_data (abstract)); + value result = alloc_empty_object (); + alloc_field (result, val_id ("handle"), CreateVulkanHandleValue ((uint64_t)(uintptr_t)memory)); + alloc_field (result, val_id ("memoryTypeIndex"), alloc_int ((int)memoryTypeIndex)); + return result; } - value lime_cffi_set_finalizer (value callback) { + static vdynamic* HLCreateVulkanMemoryValue (VkDeviceMemory memory, uint32_t memoryTypeIndex) { - value abstract = alloc_abstract (k_finalizer, callback); - val_gc (abstract, lime_cffi_finalizer); - return abstract; + const int id_handle = hl_hash_utf8 ("handle"); + const int id_memoryTypeIndex = hl_hash_utf8 ("memoryTypeIndex"); + + vdynamic* result = (vdynamic*)hl_alloc_dynobj (); + hl_dyn_setp (result, id_handle, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)memory)); + hl_dyn_seti (result, id_memoryTypeIndex, &hlt_i32, (int)memoryTypeIndex); + return result; } - void lime_clipboard_event_manager_register (value callback, value eventObject) { + static std::vector GetVulkanIntVector (value data) { - ClipboardEvent::callback = new ValuePointer (callback); - ClipboardEvent::eventObject = new ValuePointer (eventObject); + std::vector result; + if (val_is_null (data)) return result; - } + int length = val_array_size (data); + result.reserve (length); + for (int i = 0; i < length; ++i) { + result.push_back (val_int (val_array_i (data, i))); - HL_PRIM void HL_NAME(hl_clipboard_event_manager_register) (vclosure* callback, ClipboardEvent* eventObject) { + } - ClipboardEvent::callback = new ValuePointer (callback); - ClipboardEvent::eventObject = new ValuePointer ((vobj*)eventObject); + return result; } - value lime_clipboard_get_text () { - - if (Clipboard::HasText ()) { - - const char* text = Clipboard::GetText (); - value _text = alloc_string (text); - - // TODO: Should we free for all backends? (SDL requires it) + static std::vector GetHLVulkanIntVector (hl_varray* data) { - free ((char*)text); - return _text; + std::vector result; + if (!data) return result; - } else { + result.reserve (data->size); + int* values = hl_aptr (data, int); + for (int i = 0; i < data->size; ++i) { - return alloc_null (); + result.push_back (values[i]); } - } + return result; + } - HL_PRIM vbyte* HL_NAME(hl_clipboard_get_text) () { - if (Clipboard::HasText ()) { + static std::vector GetVulkanDoubleVector (value data) { - const char* text = Clipboard::GetText (); - return (vbyte*)text; + std::vector result; + if (val_is_null (data)) return result; - } else { + int length = val_array_size (data); + result.reserve (length); + for (int i = 0; i < length; ++i) { - return 0; + result.push_back (val_number (val_array_i (data, i))); } + return result; + } - void lime_clipboard_set_text (HxString text) { + static std::vector GetHLVulkanDoubleVector (hl_varray* data) { - Clipboard::SetText (hxs_utf8 (text, nullptr)); + std::vector result; + if (!data) return result; - } + result.reserve (data->size); + double* values = hl_aptr (data, double); + for (int i = 0; i < data->size; ++i) { + result.push_back (values[i]); - HL_PRIM void HL_NAME(hl_clipboard_set_text) (hl_vstring* text) { + } - Clipboard::SetText (text ? (const char*)hl_to_utf8 ((const uchar*)text->bytes) : NULL); + return result; } - double lime_data_pointer_offset (double pointer, int offset) { - - return (uintptr_t)pointer + offset; + static bool FindManagedVulkanMemoryType (Window* targetWindow, VkInstance instance, VkPhysicalDevice physicalDevice, uint32_t typeFilter, + VkMemoryPropertyFlags properties, uint32_t* outMemoryTypeIndex) { - } + if (!targetWindow || !instance || !physicalDevice || !outMemoryTypeIndex) { + lastVKError = "Missing Vulkan window, instance, physical device, or memory type output"; + return false; - HL_PRIM double HL_NAME(hl_data_pointer_offset) (double pointer, int offset) { + } - return (uintptr_t)pointer + offset; + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + if (!vkGetInstanceProcAddr) { - } + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + return false; + } - value lime_deflate_compress (value buffer, value bytes) { + PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties = + (PFN_vkGetPhysicalDeviceMemoryProperties)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceMemoryProperties"); + if (!vkGetPhysicalDeviceMemoryProperties) { - #ifdef LIME_ZLIB - Bytes data (buffer); - Bytes result (bytes); + lastVKError = "Missing Vulkan physical device memory properties function"; + return false; - Zlib::Compress (DEFLATE, &data, &result); + } - return result.Value (bytes); - #else - return alloc_null(); - #endif + VkPhysicalDeviceMemoryProperties memoryProperties; + memset (&memoryProperties, 0, sizeof (memoryProperties)); + vkGetPhysicalDeviceMemoryProperties (physicalDevice, &memoryProperties); - } + for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) { + if ((typeFilter & (1u << i)) && (memoryProperties.memoryTypes[i].propertyFlags & properties) == properties) { - HL_PRIM Bytes* HL_NAME(hl_deflate_compress) (Bytes* buffer, Bytes* bytes) { + *outMemoryTypeIndex = i; + lastVKError.clear (); + return true; - #ifdef LIME_ZLIB - Zlib::Compress (DEFLATE, buffer, bytes); - return bytes; - #else - return 0; - #endif + } - } + } + lastVKError = "Failed to find a compatible Vulkan memory type"; + return false; - value lime_deflate_decompress (value buffer, value bytes) { + } - #ifdef LIME_ZLIB - Bytes data (buffer); - Bytes result (bytes); - Zlib::Decompress (DEFLATE, &data, &result); + static bool CreateManagedVulkanSwapchain (Window* targetWindow, VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device, + VkSurfaceKHR surface, uint32_t queueFamilyIndex, int requestedWidth, int requestedHeight, VkPresentModeKHR requestedPresentMode, + VkSwapchainKHR oldSwapchain, ManagedVulkanSwapchain* outSwapchain) { - return result.Value (bytes); - #else - return alloc_null (); - #endif + if (!targetWindow || !instance || !physicalDevice || !device || !surface || !outSwapchain) { - } + lastVKError = "Missing Vulkan window, instance, device, surface, or output swapchain"; + return false; + } - HL_PRIM Bytes* HL_NAME(hl_deflate_decompress) (Bytes* buffer, Bytes* bytes) { + outSwapchain->handle = VK_NULL_HANDLE; + outSwapchain->format = VK_FORMAT_UNDEFINED; + outSwapchain->colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; + outSwapchain->extent.width = 0; + outSwapchain->extent.height = 0; + outSwapchain->presentMode = VK_PRESENT_MODE_FIFO_KHR; + outSwapchain->imageCount = 0; - #ifdef LIME_ZLIB - Zlib::Decompress (DEFLATE, buffer, bytes); - return bytes; - #else - return 0; - #endif + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + if (!vkGetInstanceProcAddr) { - } + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + return false; + } - void lime_drop_event_manager_register (value callback, value eventObject) { + PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR = + (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); + PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR = + (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfaceFormatsKHR"); + PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR = + (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfacePresentModesKHR"); + PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = + (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfaceSupportKHR"); - DropEvent::callback = new ValuePointer (callback); - DropEvent::eventObject = new ValuePointer (eventObject); + if (!vkGetPhysicalDeviceSurfaceCapabilitiesKHR || !vkGetPhysicalDeviceSurfaceFormatsKHR || !vkGetPhysicalDeviceSurfacePresentModesKHR) { - } + lastVKError = "Missing required Vulkan surface functions"; + return false; + } - HL_PRIM void HL_NAME(hl_drop_event_manager_register) (vclosure* callback, DropEvent* eventObject) { + if (vkGetPhysicalDeviceSurfaceSupportKHR) { - DropEvent::callback = new ValuePointer (callback); - DropEvent::eventObject = new ValuePointer ((vobj*)eventObject); + VkBool32 supportsPresent = VK_FALSE; + VkResult supportResult = vkGetPhysicalDeviceSurfaceSupportKHR (physicalDevice, queueFamilyIndex, surface, &supportsPresent); + if (supportResult != VK_SUCCESS || supportsPresent == VK_FALSE) { - } + lastVKError = "Vulkan queue family does not support presenting to this surface"; + return false; + } - value lime_file_dialog_open_directory (HxString title, HxString filter, HxString defaultPath) { + } - #ifdef LIME_TINYFILEDIALOGS + VkSurfaceCapabilitiesKHR capabilities; + memset (&capabilities, 0, sizeof (capabilities)); + VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR (physicalDevice, surface, &capabilities); + if (result != VK_SUCCESS) { - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + lastVKError = "vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed"; + return false; - std::wstring* path = FileDialog::OpenDirectory (_title, _filter, _defaultPath); + } - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + uint32_t formatCount = 0; + result = vkGetPhysicalDeviceSurfaceFormatsKHR (physicalDevice, surface, &formatCount, 0); + if (result != VK_SUCCESS || formatCount == 0) { - if (path) { + lastVKError = "Failed to query Vulkan surface formats"; + return false; - value _path = wstring_to_value (path); - delete path; - return _path; + } - } else { + std::vector formats (formatCount); + result = vkGetPhysicalDeviceSurfaceFormatsKHR (physicalDevice, surface, &formatCount, formats.data ()); + if (result != VK_SUCCESS) { - return alloc_null (); + lastVKError = "vkGetPhysicalDeviceSurfaceFormatsKHR failed"; + return false; } - #endif + VkSurfaceFormatKHR surfaceFormat = formats[0]; + if (formats.size () == 1 && formats[0].format == VK_FORMAT_UNDEFINED) { - return alloc_null (); + surfaceFormat.format = VK_FORMAT_B8G8R8A8_UNORM; + surfaceFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; - } + } else { + for (size_t i = 0; i < formats.size (); ++i) { - HL_PRIM vbyte* HL_NAME(hl_file_dialog_open_directory) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { + if (formats[i].format == VK_FORMAT_B8G8R8A8_UNORM && formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - #ifdef LIME_TINYFILEDIALOGS + surfaceFormat = formats[i]; + break; - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + } - std::wstring* path = FileDialog::OpenDirectory (_title, _filter, _defaultPath); + } - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + } - if (path) { + uint32_t presentModeCount = 0; + result = vkGetPhysicalDeviceSurfacePresentModesKHR (physicalDevice, surface, &presentModeCount, 0); + if (result != VK_SUCCESS) { - vbyte* const result = hl_wstring_to_utf8_bytes (*path); - delete path; - return result; + lastVKError = "Failed to query Vulkan present modes"; + return false; - } else { + } - return NULL; + std::vector presentModes (presentModeCount > 0 ? presentModeCount : 1, VK_PRESENT_MODE_FIFO_KHR); + if (presentModeCount > 0) { - } + result = vkGetPhysicalDeviceSurfacePresentModesKHR (physicalDevice, surface, &presentModeCount, presentModes.data ()); + if (result != VK_SUCCESS) { - #endif + lastVKError = "vkGetPhysicalDeviceSurfacePresentModesKHR failed"; + return false; - return NULL; + } - } + } + int drawableWidth = requestedWidth; + int drawableHeight = requestedHeight; + if (drawableWidth <= 0 || drawableHeight <= 0) { - value lime_file_dialog_open_file (HxString title, HxString filter, HxString defaultPath) { + drawableWidth = 0; + drawableHeight = 0; + targetWindow->GetVulkanDrawableSize (&drawableWidth, &drawableHeight); - #ifdef LIME_TINYFILEDIALOGS + } - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + if (drawableWidth <= 0 || drawableHeight <= 0) { - std::wstring* path = FileDialog::OpenFile (_title, _filter, _defaultPath); + lastVKError = "Vulkan drawable size is zero"; + return false; - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + } - if (path) { + VkExtent2D extent; + if (capabilities.currentExtent.width != UINT32_MAX) { - value _path = wstring_to_value (path); - delete path; - return _path; + extent = capabilities.currentExtent; } else { - return alloc_null (); + extent.width = (uint32_t)(std::max) ((int)capabilities.minImageExtent.width, + (std::min) (drawableWidth, (int)capabilities.maxImageExtent.width)); + extent.height = (uint32_t)(std::max) ((int)capabilities.minImageExtent.height, + (std::min) (drawableHeight, (int)capabilities.maxImageExtent.height)); } - #endif + if ((capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) == 0) { - return alloc_null (); + lastVKError = "Vulkan surface images do not support color attachments"; + return false; - } + } + VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + if (capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) { - HL_PRIM vbyte* HL_NAME(hl_file_dialog_open_file) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { + imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; - #ifdef LIME_TINYFILEDIALOGS + } + if (capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) { - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - std::wstring* path = FileDialog::OpenFile (_title, _filter, _defaultPath); + } - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + uint32_t imageCount = capabilities.minImageCount + 1; + if (capabilities.maxImageCount > 0 && imageCount > capabilities.maxImageCount) { - if (path) { + imageCount = capabilities.maxImageCount; - vbyte* const result = hl_wstring_to_utf8_bytes (*path); - delete path; - return result; + } - } else { + VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + const bool transparentWindow = targetWindow && ((targetWindow->flags & WINDOW_FLAG_TRANSPARENT) != 0); + const VkCompositeAlphaFlagBitsKHR opaqueCompositeAlphaFlags[] = { + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR + }; + const VkCompositeAlphaFlagBitsKHR transparentCompositeAlphaFlags[] = { + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR + }; + const VkCompositeAlphaFlagBitsKHR* compositeAlphaFlags = transparentWindow ? transparentCompositeAlphaFlags : opaqueCompositeAlphaFlags; + const size_t compositeAlphaFlagCount = transparentWindow + ? sizeof (transparentCompositeAlphaFlags) / sizeof (transparentCompositeAlphaFlags[0]) + : sizeof (opaqueCompositeAlphaFlags) / sizeof (opaqueCompositeAlphaFlags[0]); + + for (size_t i = 0; i < compositeAlphaFlagCount; ++i) { + + if (capabilities.supportedCompositeAlpha & compositeAlphaFlags[i]) { + + compositeAlpha = compositeAlphaFlags[i]; + break; - return NULL; + } } - #endif + PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateSwapchainKHR"); + PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkGetSwapchainImagesKHR"); + if (!vkCreateSwapchainKHR || !vkGetSwapchainImagesKHR) return false; + + VkSwapchainCreateInfoKHR createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + createInfo.surface = surface; + createInfo.minImageCount = imageCount; + createInfo.imageFormat = surfaceFormat.format; + createInfo.imageColorSpace = surfaceFormat.colorSpace; + createInfo.imageExtent = extent; + createInfo.imageArrayLayers = 1; + createInfo.imageUsage = imageUsage; + createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + createInfo.preTransform = capabilities.currentTransform; + createInfo.compositeAlpha = compositeAlpha; + createInfo.presentMode = ChooseManagedVulkanPresentMode (presentModes, requestedPresentMode); + createInfo.clipped = VK_TRUE; + createInfo.oldSwapchain = oldSwapchain; + + VkSwapchainKHR swapchain = VK_NULL_HANDLE; + result = vkCreateSwapchainKHR (device, &createInfo, 0, &swapchain); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateSwapchainKHR failed"; + return false; - return NULL; + } - } + uint32_t swapchainImageCount = 0; + result = vkGetSwapchainImagesKHR (device, swapchain, &swapchainImageCount, 0); + if (result != VK_SUCCESS || swapchainImageCount == 0) { + PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroySwapchainKHR"); + if (vkDestroySwapchainKHR) vkDestroySwapchainKHR (device, swapchain, 0); + lastVKError = "Failed to query Vulkan swapchain images"; + return false; - value lime_file_dialog_open_files (HxString title, HxString filter, HxString defaultPath) { + } - #ifdef LIME_TINYFILEDIALOGS + outSwapchain->handle = swapchain; + outSwapchain->format = surfaceFormat.format; + outSwapchain->colorSpace = surfaceFormat.colorSpace; + outSwapchain->extent = extent; + outSwapchain->presentMode = createInfo.presentMode; + outSwapchain->imageCount = swapchainImageCount; + lastVKError.clear (); + return true; - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); - - std::vector files; + } +#endif - FileDialog::OpenFiles (&files, _title, _filter, _defaultPath); - value result = alloc_array (files.size ()); - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + void gc_application (value handle) { - for (int i = 0; i < files.size (); i++) { + Application* application = (Application*)val_data (handle); + delete application; - value _file = wstring_to_value (files[i]); - val_array_set_i (result, i, _file); - delete files[i]; + } - } - #else - value result = alloc_array (0); - #endif + void hl_gc_application (HL_CFFIPointer* handle) { - return result; + Application* application = (Application*)handle->ptr; + delete application; } - HL_PRIM hl_varray* HL_NAME(hl_file_dialog_open_files) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { + void gc_file_watcher (value handle) { - #ifdef LIME_TINYFILEDIALOGS + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)val_data (handle); + delete watcher; + #endif - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + } - std::vector files; - FileDialog::OpenFiles (&files, _title, _filter, _defaultPath); - hl_varray* result = (hl_varray*)hl_alloc_array (&hlt_bytes, files.size ()); - vbyte** resultData = hl_aptr (result, vbyte*); + void hl_gc_file_watcher (HL_CFFIPointer* handle) { - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)handle->ptr; + delete watcher; + #endif - for (int i = 0; i < files.size (); i++) { + } - *resultData++ = hl_wstring_to_utf8_bytes (*files[i]); - delete files[i]; - } + void gc_font (value handle) { - #else - hl_varray* result = hl_alloc_array (&hlt_bytes, 0); + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (handle); + delete font; #endif - return result; + } + + + void hl_gc_font (HL_CFFIPointer* handle) { + + #ifdef LIME_FREETYPE + Font* font = (Font*)handle->ptr; + delete font; + #endif } - value lime_file_dialog_save_file (HxString title, HxString filter, HxString defaultPath) { + void gc_window (value handle) { - #ifdef LIME_TINYFILEDIALOGS + Window* window = (Window*)val_data (handle); + delete window; - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + } - std::wstring* path = FileDialog::SaveFile (_title, _filter, _defaultPath); - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + void hl_gc_window (HL_CFFIPointer* handle) { - if (path) { + Window* window = (Window*)handle->ptr; + delete window; - value _path = wstring_to_value (path); - delete path; - return _path; + } - } else { - return alloc_null (); + std::string wstring_utf8 (const std::wstring& val) { - } + std::string out; + unsigned int codepoint = 0; - #endif + for (const wchar_t chr : val) { - return alloc_null (); + if (chr >= 0xd800 && chr <= 0xdbff) { - } + codepoint = ((chr - 0xd800) << 10) + 0x10000; + } else { - HL_PRIM vbyte* HL_NAME(hl_file_dialog_save_file) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { + if (chr >= 0xdc00 && chr <= 0xdfff) { - #ifdef LIME_TINYFILEDIALOGS + codepoint |= chr - 0xdc00; - std::wstring* _title = hxstring_to_wstring (title); - std::wstring* _filter = hxstring_to_wstring (filter); - std::wstring* _defaultPath = hxstring_to_wstring (defaultPath); + } else { - std::wstring* path = FileDialog::SaveFile (_title, _filter, _defaultPath); + codepoint = chr; - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + } - if (path) { + if (codepoint <= 0x7f) { - vbyte* const result = hl_wstring_to_utf8_bytes (*path); - delete path; - return result; + out.append (1, static_cast (codepoint)); - } else { + } else if (codepoint <= 0x7ff) { - return NULL; + out.append (1, static_cast (0xc0 | ((codepoint >> 6) & 0x1f))); + out.append (1, static_cast (0x80 | (codepoint & 0x3f))); - } + } else if (codepoint <= 0xffff) { - #endif + out.append (1, static_cast (0xe0 | ((codepoint >> 12) & 0x0f))); + out.append (1, static_cast (0x80 | ((codepoint >> 6) & 0x3f))); + out.append (1, static_cast (0x80 | (codepoint & 0x3f))); - return NULL; + } else { - } + out.append (1, static_cast (0xf0 | ((codepoint >> 18) & 0x07))); + out.append (1, static_cast (0x80 | ((codepoint >> 12) & 0x3f))); + out.append (1, static_cast (0x80 | ((codepoint >> 6) & 0x3f))); + out.append (1, static_cast (0x80 | (codepoint & 0x3f))); + } - value lime_file_watcher_create (value callback) { + codepoint = 0; - #ifdef LIME_EFSW - FileWatcher* watcher = new FileWatcher (callback); - return CFFIPointer (watcher, gc_file_watcher); - #else - return alloc_null (); - #endif + } + + } + + return out; } - HL_PRIM HL_CFFIPointer* HL_NAME(hl_file_watcher_create) (vclosure* callback) { + vbyte* hl_wstring_to_utf8_bytes (const std::wstring& val) { - // #ifdef LIME_EFSW - // FileWatcher* watcher = new FileWatcher (callback); - // return HLCFFIPointer (watcher, (hl_finalizer)hl_gc_file_watcher); - // #else - return 0; - // #endif + const std::string utf8 (wstring_utf8 (val)); + vbyte* const bytes = hl_alloc_bytes (utf8.size () + 1); + std::memcpy(bytes, utf8.c_str (), utf8.size () + 1); + return bytes; } - value lime_file_watcher_add_directory (value handle, value path, bool recursive) { + #ifdef HX_WINDOWS + #define hxs_to_fd_str(str) hxs_wchar(str, nullptr) + #define alloc_from_fd_str(str) alloc_wstring(str) + #define alloc_from_fd_str_len(str, len) alloc_wstring_len(str, len) - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)val_data (handle); - return alloc_int (watcher->AddDirectory (val_string (path), recursive)); - #else - return alloc_int (0); - #endif + static const FileDialog::char_t* hl_vstring_to_fd_str (hl_vstring* val) { + if (val) { + return val->bytes; + } + return nullptr; + } + static vbyte* hl_fd_str_to_utf8_bytes(const FileDialog::char_t* src, size_t length) { + // copy first, since hl_to_utf8 has no length parameter, and hl_utf16_to_utf8 is not exposed + FileDialog::char_t* utf16 = (FileDialog::char_t*)hl_copy_bytes((vbyte*)src, (length + 1) * sizeof(FileDialog::char_t)); + utf16[length] = L'\0'; + return (vbyte*)hl_to_utf8(utf16); } + static vbyte* hl_fd_str_to_utf8_bytes(const FileDialog::char_t* src) { + return (vbyte*)hl_to_utf8((uchar*)src); + } - HL_PRIM int HL_NAME(hl_file_watcher_add_directory) (HL_CFFIPointer* handle, hl_vstring* path, bool recursive) { + #else + #define hxs_to_fd_str(str) hxs_utf8(str, nullptr) + #define alloc_from_fd_str(str) alloc_string(str) + #define alloc_from_fd_str_len(str, len) alloc_string_len(str, len) - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)handle->ptr; - return watcher->AddDirectory ((const char*)path, recursive); - #else - return 0; - #endif + static const FileDialog::char_t* hl_vstring_to_fd_str (hl_vstring* val) { + if (val) { + return hl_to_utf8 (val->bytes); + } + return nullptr; + } + static vbyte* hl_fd_str_to_utf8_bytes(const FileDialog::char_t* src, size_t length) { + vbyte* result = hl_copy_bytes((vbyte*)src, length + 1); + result[length] = '\0'; + return result; } + static vbyte* hl_fd_str_to_utf8_bytes(const FileDialog::char_t* src) { + return hl_fd_str_to_utf8_bytes(src, std::strlen(src)); + } + #endif - void lime_file_watcher_remove_directory (value handle, value watchID) { + value lime_application_create () { - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)val_data (handle); - watcher->RemoveDirectory (val_int (watchID)); - #endif + Application* application = CreateApplication (); + return CFFIPointer (application, gc_application); } - HL_PRIM void HL_NAME(hl_file_watcher_remove_directory) (HL_CFFIPointer* handle, int watchID) { + HL_PRIM HL_CFFIPointer* HL_NAME(hl_application_create) () { - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)handle->ptr; - watcher->RemoveDirectory (watchID); - #endif + Application* application = CreateApplication (); + return HLCFFIPointer (application, (hl_finalizer)hl_gc_application); } - void lime_file_watcher_update (value handle) { + void lime_application_event_manager_register (value callback, value eventObject) { - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)val_data (handle); - watcher->Update (); - #endif + ApplicationEvent::callback = new ValuePointer (callback); + ApplicationEvent::eventObject = new ValuePointer (eventObject); } - HL_PRIM void HL_NAME(hl_file_watcher_update) (HL_CFFIPointer* handle) { + HL_PRIM void HL_NAME(hl_application_event_manager_register) (vclosure* callback, ApplicationEvent* eventObject) { - #ifdef LIME_EFSW - FileWatcher* watcher = (FileWatcher*)handle->ptr; - watcher->Update (); - #endif + ApplicationEvent::callback = new ValuePointer (callback); + ApplicationEvent::eventObject = new ValuePointer ((vobj*)eventObject); } - int lime_font_get_ascender (value fontHandle) { + int lime_application_exec (value application) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetAscender (); - #else - return 0; - #endif + Application* app = (Application*)val_data (application); + return app->Exec (); } - HL_PRIM int HL_NAME(hl_font_get_ascender) (HL_CFFIPointer* fontHandle) { + HL_PRIM int HL_NAME(hl_application_exec) (HL_CFFIPointer* application) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetAscender (); - #else - return 0; - #endif + Application* app = (Application*)application->ptr; + return app->Exec (); } - int lime_font_get_descender (value fontHandle) { + void lime_application_init (value application) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetDescender (); - #else - return 0; - #endif + Application* app = (Application*)val_data (application); + app->Init (); } - HL_PRIM int HL_NAME(hl_font_get_descender) (HL_CFFIPointer* fontHandle) { + HL_PRIM void HL_NAME(hl_application_init) (HL_CFFIPointer* application) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetDescender (); - #else - return 0; - #endif + Application* app = (Application*)application->ptr; + app->Init (); } - value lime_font_get_family_name (value fontHandle) { + int lime_application_quit (value application) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - wchar_t *name = font->GetFamilyName (); - value result = alloc_wstring (name); - delete name; - return result; - #else - return alloc_null (); - #endif + Application* app = (Application*)val_data (application); + return app->Quit (); } - HL_PRIM vbyte* HL_NAME(hl_font_get_family_name) (HL_CFFIPointer* fontHandle) { + HL_PRIM int HL_NAME(hl_application_quit) (HL_CFFIPointer* application) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - wchar_t *name = font->GetFamilyName (); - if (!name) - return nullptr; - vbyte* const result = hl_wstring_to_utf8_bytes (name); - delete name; - return result; - #else - return 0; - #endif + Application* app = (Application*)application->ptr; + return app->Quit (); } - int lime_font_get_glyph_index (value fontHandle, HxString character) { + void lime_application_set_frame_rate (value application, double frameRate) { + + Application* app = (Application*)val_data (application); + app->SetFrameRate (frameRate); + + } + + + HL_PRIM void HL_NAME(hl_application_set_frame_rate) (HL_CFFIPointer* application, double frameRate) { + + Application* app = (Application*)application->ptr; + app->SetFrameRate (frameRate); + + } + + + void lime_application_set_main_loop (value application, int profile, double frameRate, int timePrecision, int busyWait, int uncapMode) { + + Application* app = (Application*)val_data (application); + app->SetMainLoop (profile, frameRate, timePrecision, busyWait, uncapMode); + + } + + + HL_PRIM void HL_NAME(hl_application_set_main_loop) (HL_CFFIPointer* application, int profile, double frameRate, int timePrecision, int busyWait, int uncapMode) { + + Application* app = (Application*)application->ptr; + app->SetMainLoop (profile, frameRate, timePrecision, busyWait, uncapMode); + + } + + + void lime_application_set_vsync_mode (value application, int vsyncMode) { + + Application* app = (Application*)val_data (application); + app->SetVSyncMode (vsyncMode); + + } + + + HL_PRIM void HL_NAME(hl_application_set_vsync_mode) (HL_CFFIPointer* application, int vsyncMode) { + + Application* app = (Application*)application->ptr; + app->SetVSyncMode (vsyncMode); + + } + + + bool lime_application_update (value application) { + + Application* app = (Application*)val_data (application); + return app->Update (); + + } + + + HL_PRIM bool HL_NAME(hl_application_update) (HL_CFFIPointer* application) { + + Application* app = (Application*)application->ptr; + return app->Update (); + + } + + + value lime_audio_load_bytes (value data, value buffer) { + + Resource resource; + Bytes bytes; + + AudioBuffer audioBuffer = AudioBuffer (buffer); + + bytes.Set (data); + resource = Resource (&bytes); + + #ifdef LIME_SDL_SOUND + if (SDLSound::Decode (&resource, &audioBuffer)) { + + return audioBuffer.Value (buffer); + + } + #endif + + + if (WAV::Decode (&resource, &audioBuffer)) { + + return audioBuffer.Value (buffer); + + } + + #ifdef LIME_OGG + if (OGG::Decode (&resource, &audioBuffer)) { + + return audioBuffer.Value (buffer); + + } + #endif + + return alloc_null (); + + } + + + HL_PRIM AudioBuffer* HL_NAME(hl_audio_load_bytes) (Bytes* data, AudioBuffer* buffer) { + + Resource resource = Resource (data); + + #ifdef LIME_SDL_SOUND + if (SDLSound::Decode (&resource, buffer)) { + + return buffer; + + } + #endif + + if (WAV::Decode (&resource, buffer)) { + + return buffer; + + } + + #ifdef LIME_OGG + if (OGG::Decode (&resource, buffer)) { + + return buffer; + + } + #endif + + return 0; + + } + + + value lime_audio_load_file (value data, value buffer) { + + Resource resource; + + AudioBuffer audioBuffer = AudioBuffer (buffer); + + resource = Resource (val_string (data)); + + #ifdef LIME_SDL_SOUND + if (SDLSound::Decode (&resource, &audioBuffer)) { + + return audioBuffer.Value (buffer); + + } + #endif + + if (WAV::Decode (&resource, &audioBuffer)) { + + return audioBuffer.Value (buffer); + + } + + #ifdef LIME_OGG + if (OGG::Decode (&resource, &audioBuffer)) { + + return audioBuffer.Value (buffer); + + } + #endif + + return alloc_null (); + + } + + + HL_PRIM AudioBuffer* HL_NAME(hl_audio_load_file) (hl_vstring* data, AudioBuffer* buffer) { + + Resource resource = Resource (data ? hl_to_utf8 ((const uchar*)data->bytes) : NULL); + + #ifdef LIME_SDL_SOUND + if (SDLSound::Decode (&resource, buffer)) { + + return buffer; + + } + #endif + + if (WAV::Decode (&resource, buffer)) { + + return buffer; + + } + + #ifdef LIME_OGG + if (OGG::Decode (&resource, buffer)) { + + return buffer; + + } + #endif + + return 0; + + } + + + value lime_audio_load (value data, value buffer) { + + if (val_is_string (data)) { + + return lime_audio_load_file (data, buffer); + + } else { + + return lime_audio_load_bytes (data, buffer); + + } + + } + + + value lime_bytes_from_data_pointer (double data, int length, value _bytes) { + + uintptr_t ptr = (uintptr_t)data; + Bytes bytes (_bytes); + bytes.Resize (length); + + if (ptr) { + + memcpy (bytes.b, (const void*)ptr, length); + + } + + return bytes.Value (_bytes); + + } + + + HL_PRIM Bytes* HL_NAME(hl_bytes_from_data_pointer) (double data, int length, Bytes* bytes) { + + uintptr_t ptr = (uintptr_t)data; + bytes->Resize (length); + + if (ptr) { + + memcpy (bytes->b, (const void*)ptr, length); + + } + + return bytes; + + } + + + double lime_bytes_get_data_pointer (value bytes) { + + Bytes data = Bytes (bytes); + return (uintptr_t)data.b; + + } + + + HL_PRIM double HL_NAME(hl_bytes_get_data_pointer) (Bytes* bytes) { + + return bytes ? (uintptr_t)bytes->b : 0; + + } + + + double lime_bytes_get_data_pointer_offset (value bytes, int offset) { + + if (val_is_null (bytes)) return 0; + + Bytes data = Bytes (bytes); + return (uintptr_t)data.b + offset; + + } + + + HL_PRIM double HL_NAME(hl_bytes_get_data_pointer_offset) (Bytes* bytes, int offset) { + + if (!bytes) return 0; + return (uintptr_t)bytes->b + offset; + + } + + + value lime_bytes_read_file (HxString path, value bytes) { + + Bytes data (bytes); + data.ReadFile (hxs_utf8 (path, nullptr)); + return data.Value (bytes); + + } + + + HL_PRIM Bytes* HL_NAME(hl_bytes_read_file) (hl_vstring* path, Bytes* bytes) { + + if (!path) return 0; + bytes->ReadFile (hl_to_utf8 ((const uchar*)path->bytes)); + return bytes; + + } + + + double lime_cffi_get_native_pointer (value handle) { + + return (uintptr_t)val_data (handle); + + } + + + HL_PRIM double HL_NAME(hl_cffi_get_native_pointer) (HL_CFFIPointer* handle) { + + return (uintptr_t)handle->ptr; + + } + + + void lime_cffi_finalizer (value abstract) { + + val_call0 ((value)val_data (abstract)); + + } + + + value lime_cffi_set_finalizer (value callback) { + + value abstract = alloc_abstract (k_finalizer, callback); + val_gc (abstract, lime_cffi_finalizer); + return abstract; + + } + + + void lime_clipboard_event_manager_register (value callback, value eventObject) { + + ClipboardEvent::callback = new ValuePointer (callback); + ClipboardEvent::eventObject = new ValuePointer (eventObject); + + } + + + HL_PRIM void HL_NAME(hl_clipboard_event_manager_register) (vclosure* callback, ClipboardEvent* eventObject) { + + ClipboardEvent::callback = new ValuePointer (callback); + ClipboardEvent::eventObject = new ValuePointer ((vobj*)eventObject); + + } + + + value lime_clipboard_get_text () { + + if (Clipboard::HasText ()) { + + const char* text = Clipboard::GetText (); + value _text = alloc_string (text); + + // TODO: Should we free for all backends? (SDL requires it) + + free ((char*)text); + return _text; + + } else { + + return alloc_null (); + + } + + } + + + HL_PRIM vbyte* HL_NAME(hl_clipboard_get_text) () { + + if (Clipboard::HasText ()) { + + const char* text = Clipboard::GetText (); + return (vbyte*)text; + + } else { + + return 0; + + } + + } + + + void lime_clipboard_set_text (HxString text) { + + Clipboard::SetText (hxs_utf8 (text, nullptr)); + + } + + + HL_PRIM void HL_NAME(hl_clipboard_set_text) (hl_vstring* text) { + + Clipboard::SetText (text ? (const char*)hl_to_utf8 ((const uchar*)text->bytes) : NULL); + + } + + + double lime_data_pointer_offset (double pointer, int offset) { + + return (uintptr_t)pointer + offset; + + } + + + HL_PRIM double HL_NAME(hl_data_pointer_offset) (double pointer, int offset) { + + return (uintptr_t)pointer + offset; + + } + + + value lime_deflate_compress (value buffer, value bytes) { + + #ifdef LIME_ZLIB + Bytes data (buffer); + Bytes result (bytes); + + Zlib::Compress (DEFLATE, &data, &result); + + return result.Value (bytes); + #else + return alloc_null(); + #endif + + } + + + HL_PRIM Bytes* HL_NAME(hl_deflate_compress) (Bytes* buffer, Bytes* bytes) { + + #ifdef LIME_ZLIB + Zlib::Compress (DEFLATE, buffer, bytes); + return bytes; + #else + return 0; + #endif + + } + + + value lime_deflate_decompress (value buffer, value bytes) { + + #ifdef LIME_ZLIB + Bytes data (buffer); + Bytes result (bytes); + + Zlib::Decompress (DEFLATE, &data, &result); + + return result.Value (bytes); + #else + return alloc_null (); + #endif + + } + + + HL_PRIM Bytes* HL_NAME(hl_deflate_decompress) (Bytes* buffer, Bytes* bytes) { + + #ifdef LIME_ZLIB + Zlib::Decompress (DEFLATE, buffer, bytes); + return bytes; + #else + return 0; + #endif + + } + + + void lime_drop_event_manager_register (value callback, value eventObject) { + + DropEvent::callback = new ValuePointer (callback); + DropEvent::eventObject = new ValuePointer (eventObject); + + } + + + HL_PRIM void HL_NAME(hl_drop_event_manager_register) (vclosure* callback, DropEvent* eventObject) { + + DropEvent::callback = new ValuePointer (callback); + DropEvent::eventObject = new ValuePointer ((vobj*)eventObject); + + } + + + value lime_file_dialog_open_directory (HxString title, HxString filter, HxString defaultPath) { + + #ifdef LIME_TINYFILEDIALOGS + + const FileDialog::char_t* path = FileDialog::OpenDirectory (hxs_to_fd_str (title), hxs_to_fd_str (filter), hxs_to_fd_str (defaultPath)); + + if (path) { + + return alloc_from_fd_str (path); + + } + + #endif + + return alloc_null (); + + } + + + HL_PRIM vbyte* HL_NAME(hl_file_dialog_open_directory) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { + + #ifdef LIME_TINYFILEDIALOGS + + const FileDialog::char_t* path = FileDialog::OpenDirectory (hl_vstring_to_fd_str (title), hl_vstring_to_fd_str (filter), hl_vstring_to_fd_str (defaultPath)); + + if (path) { + + return hl_fd_str_to_utf8_bytes(path); + + } + + #endif + + return NULL; + + } + + + value lime_file_dialog_open_file (HxString title, HxString filter, HxString defaultPath) { + + #ifdef LIME_TINYFILEDIALOGS + + const FileDialog::char_t* path = FileDialog::OpenFile (hxs_to_fd_str (title), hxs_to_fd_str (filter), hxs_to_fd_str (defaultPath)); + + if (path) { + + return alloc_from_fd_str (path); + + } + + #endif + + return alloc_null (); + + } + + + HL_PRIM vbyte* HL_NAME(hl_file_dialog_open_file) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { + + #ifdef LIME_TINYFILEDIALOGS + + const FileDialog::char_t* path = FileDialog::OpenFile (hl_vstring_to_fd_str (title), hl_vstring_to_fd_str (filter), hl_vstring_to_fd_str (defaultPath)); + + if (path) { + + return hl_fd_str_to_utf8_bytes (path); + + } + + #endif + + return NULL; + + } + + + value lime_file_dialog_open_files (HxString title, HxString filter, HxString defaultPath) { + + #ifdef LIME_TINYFILEDIALOGS + + auto files = FileDialog::OpenFiles (hxs_to_fd_str (title), hxs_to_fd_str (filter), hxs_to_fd_str (defaultPath)); + value result = alloc_array (files.size ()); + + for (int i = 0; i < files.size (); i++) { + + auto file_str = files[i]; + + value file = alloc_from_fd_str_len (file_str.data(), file_str.size()); + val_array_set_i (result, i, file); + + } + + #else + value result = alloc_array (0); + #endif + + return result; + + } + + + HL_PRIM hl_varray* HL_NAME(hl_file_dialog_open_files) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { + + #ifdef LIME_TINYFILEDIALOGS + + auto files = FileDialog::OpenFiles (hl_vstring_to_fd_str (title), hl_vstring_to_fd_str (filter), hl_vstring_to_fd_str (defaultPath)); + hl_varray* result = (hl_varray*)hl_alloc_array (&hlt_bytes, files.size ()); + vbyte** resultData = hl_aptr (result, vbyte*); + + for (int i = 0; i < files.size (); i++) { + + auto file_str = files[i]; + *resultData++ = hl_fd_str_to_utf8_bytes (file_str.data(), file_str.size()); + + } + + #else + hl_varray* result = hl_alloc_array (&hlt_bytes, 0); + #endif + + return result; + + } + + + value lime_file_dialog_save_file (HxString title, HxString filter, HxString defaultPath) { + + #ifdef LIME_TINYFILEDIALOGS + + const FileDialog::char_t* path = FileDialog::SaveFile (hxs_to_fd_str (title), hxs_to_fd_str (filter), hxs_to_fd_str (defaultPath)); + + if (path) { + + return alloc_from_fd_str (path); + + } + + #endif + + return alloc_null (); + + } + + + HL_PRIM vbyte* HL_NAME(hl_file_dialog_save_file) (hl_vstring* title, hl_vstring* filter, hl_vstring* defaultPath) { + + #ifdef LIME_TINYFILEDIALOGS + + const FileDialog::char_t* path = FileDialog::SaveFile (hl_vstring_to_fd_str (title), hl_vstring_to_fd_str (filter), hl_vstring_to_fd_str (defaultPath)); + + if (path) { + + return hl_fd_str_to_utf8_bytes (path); + + } + + #endif + + return NULL; + + } + + + value lime_file_watcher_create (value callback) { + + #ifdef LIME_EFSW + FileWatcher* watcher = new FileWatcher (callback); + return CFFIPointer (watcher, gc_file_watcher); + #else + return alloc_null (); + #endif + + } + + + HL_PRIM HL_CFFIPointer* HL_NAME(hl_file_watcher_create) (vclosure* callback) { + + // #ifdef LIME_EFSW + // FileWatcher* watcher = new FileWatcher (callback); + // return HLCFFIPointer (watcher, (hl_finalizer)hl_gc_file_watcher); + // #else + return 0; + // #endif + + } + + + value lime_file_watcher_add_directory (value handle, value path, bool recursive) { + + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)val_data (handle); + return alloc_int (watcher->AddDirectory (val_string (path), recursive)); + #else + return alloc_int (0); + #endif + + } + + + HL_PRIM int HL_NAME(hl_file_watcher_add_directory) (HL_CFFIPointer* handle, hl_vstring* path, bool recursive) { + + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)handle->ptr; + return watcher->AddDirectory ((const char*)path, recursive); + #else + return 0; + #endif + + } + + + void lime_file_watcher_remove_directory (value handle, value watchID) { + + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)val_data (handle); + watcher->RemoveDirectory (val_int (watchID)); + #endif + + } + + + HL_PRIM void HL_NAME(hl_file_watcher_remove_directory) (HL_CFFIPointer* handle, int watchID) { + + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)handle->ptr; + watcher->RemoveDirectory (watchID); + #endif + + } + + + void lime_file_watcher_update (value handle) { + + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)val_data (handle); + watcher->Update (); + #endif + + } + + + HL_PRIM void HL_NAME(hl_file_watcher_update) (HL_CFFIPointer* handle) { + + #ifdef LIME_EFSW + FileWatcher* watcher = (FileWatcher*)handle->ptr; + watcher->Update (); + #endif + + } + + + int lime_font_get_ascender (value fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetAscender (); + #else + return 0; + #endif + + } + + + HL_PRIM int HL_NAME(hl_font_get_ascender) (HL_CFFIPointer* fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetAscender (); + #else + return 0; + #endif + + } + + + int lime_font_get_descender (value fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetDescender (); + #else + return 0; + #endif + + } + + + HL_PRIM int HL_NAME(hl_font_get_descender) (HL_CFFIPointer* fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetDescender (); + #else + return 0; + #endif + + } + + + value lime_font_get_family_name (value fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + wchar_t *name = font->GetFamilyName (); + value result = alloc_wstring (name); + delete name; + return result; + #else + return alloc_null (); + #endif + + } + + + HL_PRIM vbyte* HL_NAME(hl_font_get_family_name) (HL_CFFIPointer* fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + wchar_t *name = font->GetFamilyName (); + if (!name) + return nullptr; + vbyte* const result = hl_wstring_to_utf8_bytes (name); + delete name; + return result; + #else + return 0; + #endif + + } + + + int lime_font_get_glyph_index (value fontHandle, HxString character) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetGlyphIndex (hxs_utf8 (character, nullptr)); + #else + return -1; + #endif + + } + + + HL_PRIM int HL_NAME(hl_font_get_glyph_index) (HL_CFFIPointer* fontHandle, hl_vstring* character) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetGlyphIndex (character ? (char*)hl_to_utf8 ((const uchar*)character->bytes) : NULL); + #else + return -1; + #endif + + } + + + value lime_font_get_glyph_indices (value fontHandle, HxString characters) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return (value)font->GetGlyphIndices (true, hxs_utf8 (characters, nullptr)); + #else + return alloc_null (); + #endif + + } + + + HL_PRIM hl_varray* HL_NAME(hl_font_get_glyph_indices) (HL_CFFIPointer* fontHandle, hl_vstring* characters) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return (hl_varray*)font->GetGlyphIndices (false, characters ? (char*)hl_to_utf8 ((const uchar*)characters->bytes) : NULL); + #else + return 0; + #endif + + } + + + value lime_font_get_glyph_metrics (value fontHandle, int index) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return (value)font->GetGlyphMetrics (true, index); + #else + return alloc_null (); + #endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_font_get_glyph_metrics) (HL_CFFIPointer* fontHandle, int index) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return (vdynamic*)font->GetGlyphMetrics (false, index); + #else + return 0; + #endif + + } + + + int lime_font_get_height (value fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetHeight (); + #else + return 0; + #endif + + } + + + HL_PRIM int HL_NAME(hl_font_get_height) (HL_CFFIPointer* fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetHeight (); + #else + return 0; + #endif + + } + + + int lime_font_get_num_glyphs (value fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetNumGlyphs (); + #else + return 0; + #endif + + } + + + HL_PRIM int HL_NAME(hl_font_get_num_glyphs) (HL_CFFIPointer* fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetNumGlyphs (); + #else + return 0; + #endif + + } + + + int lime_font_get_underline_position (value fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetUnderlinePosition (); + #else + return 0; + #endif + + } + + + HL_PRIM int HL_NAME(hl_font_get_underline_position) (HL_CFFIPointer* fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetUnderlinePosition (); + #else + return 0; + #endif + + } + + + int lime_font_get_underline_thickness (value fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetUnderlineThickness (); + #else + return 0; + #endif + + } + + + HL_PRIM int HL_NAME(hl_font_get_underline_thickness) (HL_CFFIPointer* fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetUnderlineThickness (); + #else + return 0; + #endif + + } + + + int lime_font_get_strikethrough_position (value fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetStrikethroughPosition (); + #else + return 0; + #endif + + } + + + HL_PRIM int HL_NAME(hl_font_get_strikethrough_position) (HL_CFFIPointer* fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetStrikethroughPosition (); + #else + return 0; + #endif + + } + + + int lime_font_get_strikethrough_thickness (value fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetStrikethroughThickness (); + #else + return 0; + #endif + + } + + + HL_PRIM int HL_NAME(hl_font_get_strikethrough_thickness) (HL_CFFIPointer* fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetStrikethroughThickness (); + #else + return 0; + #endif + + } + + + int lime_font_get_units_per_em (value fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return font->GetUnitsPerEM (); + #else + return 0; + #endif + + } + + + HL_PRIM int HL_NAME(hl_font_get_units_per_em) (HL_CFFIPointer* fontHandle) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return font->GetUnitsPerEM (); + #else + return 0; + #endif + + } + + + value lime_font_load_bytes (value data) { + + #ifdef LIME_FREETYPE + Resource resource; + Bytes bytes; + + bytes.Set (data); + resource = Resource (&bytes); + + Font *font = new Font (&resource, 0); + + if (font) { + + if (font->face) { + + return CFFIPointer (font, gc_font); + + } else { + + delete font; + + } + + } + #endif + + return alloc_null (); + + } + + + HL_PRIM HL_CFFIPointer* HL_NAME(hl_font_load_bytes) (Bytes* data) { + + #ifdef LIME_FREETYPE + Resource resource = Resource (data); + + Font *font = new Font (&resource, 0); + + if (font) { + + if (font->face) { + + return HLCFFIPointer (font, (hl_finalizer)hl_gc_font); + + } else { + + delete font; + + } + + } + #endif + + return 0; + + } + + + value lime_font_load_file (value data) { + + #ifdef LIME_FREETYPE + Resource resource = Resource (val_string (data)); + + Font *font = new Font (&resource, 0); + + if (font) { + + if (font->face) { + + return CFFIPointer (font, gc_font); + + } else { + + delete font; + + } + + } + #endif + + return alloc_null (); + + } + + + HL_PRIM HL_CFFIPointer* HL_NAME(hl_font_load_file) (hl_vstring* data) { + + #ifdef LIME_FREETYPE + Resource resource = Resource (data ? hl_to_utf8 ((const uchar*)data->bytes) : NULL); + + Font *font = new Font (&resource, 0); + + if (font) { + + if (font->face) { + + return HLCFFIPointer (font, (hl_finalizer)hl_gc_font); + + } else { + + delete font; + + } + + } + #endif + + return 0; + + } + + + value lime_font_load (value data) { + + if (val_is_string (data)) { + + return lime_font_load_file (data); + + } else { + + return lime_font_load_bytes (data); + + } + + } + + + value lime_font_outline_decompose (value fontHandle, int size) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return (value)font->Decompose (true, size); + #else + return alloc_null (); + #endif + + } + + + value lime_font_outline_decompose_no_hint (value fontHandle, int size) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + return (value)font->Decompose (true, size, false); + #else + return alloc_null (); + #endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_font_outline_decompose) (HL_CFFIPointer* fontHandle, int size) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return (vdynamic*)font->Decompose (false, size); + #else + return 0; + #endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_font_outline_decompose_no_hint) (HL_CFFIPointer* fontHandle, int size) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + return (vdynamic*)font->Decompose (false, size, false); + #else + return 0; + #endif + + } + + + value lime_font_render_glyph (value fontHandle, int index, value data) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + Bytes bytes (data); + + if (font->RenderGlyph (index, &bytes)) { + + return bytes.Value (data); + + } + #endif + + return alloc_null (); + + } + + + value lime_font_render_glyph_with_flags (value fontHandle, int index, int loadFlags, value data) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + Bytes bytes (data); + + if (font->RenderGlyphWithFlags (index, loadFlags, &bytes)) { + + return bytes.Value (data); + + } + #endif + + return alloc_null (); + + } + + + HL_PRIM Bytes* HL_NAME(hl_font_render_glyph) (HL_CFFIPointer* fontHandle, int index, Bytes* data) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + + if (font->RenderGlyph (index, data)) { + + return data; + + } + #endif + + return NULL; + + } + + + HL_PRIM Bytes* HL_NAME(hl_font_render_glyph_with_flags) (HL_CFFIPointer* fontHandle, int index, int loadFlags, Bytes* data) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + + if (font->RenderGlyphWithFlags (index, loadFlags, data)) { + + return data; + + } + #endif + + return NULL; + + } + + + value lime_font_render_glyphs (value fontHandle, value indices, value data) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + Bytes bytes (data); + + if (font->RenderGlyphs (indices, &bytes)) { + + return bytes.Value (data); + + } + #endif + + return alloc_null (); + + } + + + HL_PRIM Bytes* HL_NAME(hl_font_render_glyphs) (HL_CFFIPointer* fontHandle, hl_varray* indices, Bytes* data) { + + // #ifdef LIME_FREETYPE + // Font *font = (Font*)fontHandle->ptr; + // return font->RenderGlyphs (indices, &bytes); + // #else + return NULL; + // #endif + + } + + + void lime_font_set_size (value fontHandle, int fontSize, int dpi) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)val_data (fontHandle); + font->SetSize (fontSize, dpi); + #endif + + } + + + HL_PRIM void HL_NAME(hl_font_set_size) (HL_CFFIPointer* fontHandle, int fontSize, int dpi) { + + #ifdef LIME_FREETYPE + Font *font = (Font*)fontHandle->ptr; + font->SetSize (fontSize, dpi); + #endif + + } + + + void lime_gamepad_add_mappings (value mappings) { + + int length = val_array_size (mappings); + + for (int i = 0; i < length; i++) { + + Gamepad::AddMapping (val_string (val_array_i (mappings, i))); + + } + + } + + + HL_PRIM void HL_NAME(hl_gamepad_add_mappings) (hl_varray* mappings) { + + int length = mappings->size; + hl_vstring** mappingsData = hl_aptr (mappings, hl_vstring*); + + for (int i = 0; i < length; i++) { + + Gamepad::AddMapping (hl_to_utf8 ((const uchar*)((*mappingsData++)->bytes))); + + } + + } + + + void lime_gamepad_event_manager_register (value callback, value eventObject) { + + GamepadEvent::callback = new ValuePointer (callback); + GamepadEvent::eventObject = new ValuePointer (eventObject); + + } + + + HL_PRIM void HL_NAME(hl_gamepad_event_manager_register) (vclosure* callback, GamepadEvent* eventObject) { + + GamepadEvent::callback = new ValuePointer (callback); + GamepadEvent::eventObject = new ValuePointer ((vobj*)eventObject); + + } + + + value lime_gamepad_get_device_guid (int id) { + + const char* guid = Gamepad::GetDeviceGUID (id); + + if (guid) { + + value result = alloc_string (guid); + delete guid; + return result; + + } else { + + return alloc_null (); + + } + + } + + + HL_PRIM vbyte* HL_NAME(hl_gamepad_get_device_guid) (int id) { + + const char* guid = Gamepad::GetDeviceGUID (id); + + if (guid) { + + return (vbyte*)guid; + + } else { + + return 0; + + } + + } + + + value lime_gamepad_get_device_name (int id) { + + const char* name = Gamepad::GetDeviceName (id); + return name ? alloc_string (name) : alloc_null (); + + } + + + HL_PRIM vbyte* HL_NAME(hl_gamepad_get_device_name) (int id) { + + return (vbyte*)Gamepad::GetDeviceName (id); + + } + + + void lime_gamepad_rumble (int id, double lowFrequencyRumble, double highFrequencyRumble, int duration) { + + Gamepad::Rumble (id, lowFrequencyRumble, highFrequencyRumble, duration); + + } + + + HL_PRIM void HL_NAME(hl_gamepad_rumble) (int id, double lowFrequencyRumble, double highFrequencyRumble, int duration) { + + Gamepad::Rumble (id, lowFrequencyRumble, highFrequencyRumble, duration); + + } + + + value lime_gzip_compress (value buffer, value bytes) { + + #ifdef LIME_ZLIB + Bytes data (buffer); + Bytes result (bytes); + + Zlib::Compress (GZIP, &data, &result); + + return result.Value (bytes); + #else + return alloc_null (); + #endif + + } + + + HL_PRIM Bytes* HL_NAME(hl_gzip_compress) (Bytes* buffer, Bytes* bytes) { + + #ifdef LIME_ZLIB + Zlib::Compress (GZIP, buffer, bytes); + return bytes; + #else + return 0; + #endif + + } + + + value lime_gzip_decompress (value buffer, value bytes) { + + #ifdef LIME_ZLIB + Bytes data (buffer); + Bytes result (bytes); + + Zlib::Decompress (GZIP, &data, &result); + + return result.Value (bytes); + #else + return alloc_null (); + #endif + + } + + + HL_PRIM Bytes* HL_NAME(hl_gzip_decompress) (Bytes* buffer, Bytes* bytes) { + + #ifdef LIME_ZLIB + Zlib::Decompress (GZIP, buffer, bytes); + return bytes; + #else + return 0; + #endif + + } + + + void lime_haptic_vibrate (int period, int duration) { + + #ifdef IPHONE + Haptic::Vibrate (period, duration); + #endif + + } + + + HL_PRIM void HL_NAME(hl_haptic_vibrate) (int period, int duration) { + + #ifdef IPHONE + Haptic::Vibrate (period, duration); + #endif + + } + + + value lime_image_encode (value buffer, int type, int quality, value bytes) { + + ImageBuffer imageBuffer = ImageBuffer (buffer); + Bytes data = Bytes (bytes); + + switch (type) { + + case 0: + + #ifdef LIME_PNG + if (PNG::Encode (&imageBuffer, &data)) { + + return data.Value (bytes); + + } + #endif + break; + + case 1: + + #ifdef LIME_JPEG + if (JPEG::Encode (&imageBuffer, &data, quality)) { + + return data.Value (bytes); + + } + #endif + break; + + default: break; + + } + + return alloc_null (); + + } + + + HL_PRIM Bytes* HL_NAME(hl_image_encode) (ImageBuffer* buffer, int type, int quality, Bytes* bytes) { + + switch (type) { + + case 0: + + #ifdef LIME_PNG + if (PNG::Encode (buffer, bytes)) { + + return bytes; + + } + #endif + break; + + case 1: + + #ifdef LIME_JPEG + if (JPEG::Encode (buffer, bytes, quality)) { + + return bytes; + + } + #endif + break; + + default: break; + + } + + return 0; + + } + + + value lime_image_load_bytes (value data, value buffer) { + + Resource resource; + Bytes bytes; + + ImageBuffer imageBuffer = ImageBuffer (buffer); + + bytes.Set (data); + resource = Resource (&bytes); + + #ifdef LIME_PNG + if (PNG::Decode (&resource, &imageBuffer)) { + + return imageBuffer.Value (buffer); + + } + #endif + + #ifdef LIME_JPEG + if (JPEG::Decode (&resource, &imageBuffer)) { + + return imageBuffer.Value (buffer); + + } + #endif + + return alloc_null (); + + } + + + HL_PRIM ImageBuffer* HL_NAME(hl_image_load_bytes) (Bytes* data, ImageBuffer* buffer) { + + Resource resource = Resource (data); + + #ifdef LIME_PNG + if (PNG::Decode (&resource, buffer)) { + + return buffer; + + } + #endif + + #ifdef LIME_JPEG + if (JPEG::Decode (&resource, buffer)) { + + return buffer; + + } + #endif + + return 0; + + } + + + value lime_image_load_file (value data, value buffer) { + + Resource resource = Resource (val_string (data)); + ImageBuffer imageBuffer = ImageBuffer (buffer); + + #ifdef LIME_PNG + if (PNG::Decode (&resource, &imageBuffer)) { + + return imageBuffer.Value (buffer); + + } + #endif + + #ifdef LIME_JPEG + if (JPEG::Decode (&resource, &imageBuffer)) { + + return imageBuffer.Value (buffer); + + } + #endif + + return alloc_null (); + + } + + + HL_PRIM ImageBuffer* HL_NAME(hl_image_load_file) (hl_vstring* data, ImageBuffer* buffer) { + + Resource resource = Resource (data); + + #ifdef LIME_PNG + if (PNG::Decode (&resource, buffer)) { + + return buffer; + + } + #endif + + #ifdef LIME_JPEG + if (JPEG::Decode (&resource, buffer)) { + + return buffer; + + } + #endif + + return 0; + + } + + + value lime_image_load (value data, value buffer) { + + if (val_is_string (data)) { + + return lime_image_load_file (data, buffer); + + } else { + + return lime_image_load_bytes (data, buffer); + + } + + } + + + void lime_image_data_util_color_transform (value image, value rect, value colorMatrix) { + + Image _image = Image (image); + Rectangle _rect = Rectangle (rect); + ColorMatrix _colorMatrix = ColorMatrix (colorMatrix); + ImageDataUtil::ColorTransform (&_image, &_rect, &_colorMatrix); + + } + + + HL_PRIM void HL_NAME(hl_image_data_util_color_transform) (Image* image, Rectangle* rect, ArrayBufferView* colorMatrix) { + + ColorMatrix _colorMatrix = ColorMatrix (colorMatrix); + ImageDataUtil::ColorTransform (image, rect, &_colorMatrix); + + } + + + void lime_image_data_util_copy_channel (value image, value sourceImage, value sourceRect, value destPoint, int srcChannel, int destChannel) { + + Image _image = Image (image); + Image _sourceImage = Image (sourceImage); + Rectangle _sourceRect = Rectangle (sourceRect); + Vector2 _destPoint = Vector2 (destPoint); + ImageDataUtil::CopyChannel (&_image, &_sourceImage, &_sourceRect, &_destPoint, srcChannel, destChannel); + + } + + + HL_PRIM void HL_NAME(hl_image_data_util_copy_channel) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int srcChannel, int destChannel) { + + ImageDataUtil::CopyChannel (image, sourceImage, sourceRect, destPoint, srcChannel, destChannel); + + } + + + void lime_image_data_util_copy_pixels (value image, value sourceImage, value sourceRect, value destPoint, value alphaImage, value alphaPoint, bool mergeAlpha) { + + Image _image = Image (image); + Image _sourceImage = Image (sourceImage); + Rectangle _sourceRect = Rectangle (sourceRect); + Vector2 _destPoint = Vector2 (destPoint); + + if (val_is_null (alphaImage)) { + + ImageDataUtil::CopyPixels (&_image, &_sourceImage, &_sourceRect, &_destPoint, 0, 0, mergeAlpha); + + } else { + + Image _alphaImage = Image (alphaImage); + Vector2 _alphaPoint = Vector2 (alphaPoint); + + ImageDataUtil::CopyPixels (&_image, &_sourceImage, &_sourceRect, &_destPoint, &_alphaImage, &_alphaPoint, mergeAlpha); + + } + + } + + + HL_PRIM void HL_NAME(hl_image_data_util_copy_pixels) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, Image* alphaImage, Vector2* alphaPoint, bool mergeAlpha) { + + if (!alphaImage) { + + ImageDataUtil::CopyPixels (image, sourceImage, sourceRect, destPoint, NULL, NULL, mergeAlpha); + + } else { + + if (!alphaPoint) { + + Vector2 _alphaPoint = Vector2 (0, 0); + + ImageDataUtil::CopyPixels (image, sourceImage, sourceRect, destPoint, alphaImage, &_alphaPoint, mergeAlpha); + + } else { + + ImageDataUtil::CopyPixels (image, sourceImage, sourceRect, destPoint, alphaImage, alphaPoint, mergeAlpha); + + } + + } + + } + + + void lime_image_data_util_fill_rect (value image, value rect, int rg, int ba) { + + Image _image = Image (image); + Rectangle _rect = Rectangle (rect); + int32_t color = (rg << 16) | ba; + ImageDataUtil::FillRect (&_image, &_rect, color); + + } + + + HL_PRIM void HL_NAME(hl_image_data_util_fill_rect) (Image* image, Rectangle* rect, int rg, int ba) { + + int32_t color = (rg << 16) | ba; + ImageDataUtil::FillRect (image, rect, color); + + } + + + void lime_image_data_util_flood_fill (value image, int x, int y, int rg, int ba) { + + Image _image = Image (image); + int32_t color = (rg << 16) | ba; + ImageDataUtil::FloodFill (&_image, x, y, color); + + } + + + HL_PRIM void HL_NAME(hl_image_data_util_flood_fill) (Image* image, int x, int y, int rg, int ba) { + + int32_t color = (rg << 16) | ba; + ImageDataUtil::FloodFill (image, x, y, color); + + } + + + void lime_image_data_util_get_pixels (value image, value rect, int format, value bytes) { + + Image _image = Image (image); + Rectangle _rect = Rectangle (rect); + PixelFormat _format = (PixelFormat)format; + Bytes pixels = Bytes (bytes); + ImageDataUtil::GetPixels (&_image, &_rect, _format, &pixels); + + } + + + HL_PRIM void HL_NAME(hl_image_data_util_get_pixels) (Image* image, Rectangle* rect, PixelFormat format, Bytes* bytes) { + + ImageDataUtil::GetPixels (image, rect, format, bytes); + + } + + + void lime_image_data_util_merge (value image, value sourceImage, value sourceRect, value destPoint, int redMultiplier, int greenMultiplier, int blueMultiplier, int alphaMultiplier) { + + Image _image = Image (image); + Image _sourceImage = Image (sourceImage); + Rectangle _sourceRect = Rectangle (sourceRect); + Vector2 _destPoint = Vector2 (destPoint); + ImageDataUtil::Merge (&_image, &_sourceImage, &_sourceRect, &_destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier); + + } + + + HL_PRIM void HL_NAME(hl_image_data_util_merge) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int redMultiplier, int greenMultiplier, int blueMultiplier, int alphaMultiplier) { + + ImageDataUtil::Merge (image, sourceImage, sourceRect, destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier); + + } + + + void lime_image_data_util_multiply_alpha (value image) { + + Image _image = Image (image); + ImageDataUtil::MultiplyAlpha (&_image); + + } + + + HL_PRIM void HL_NAME(hl_image_data_util_multiply_alpha) (Image* image) { + + ImageDataUtil::MultiplyAlpha (image); + + } + + + void lime_image_data_util_resize (value image, value buffer, int width, int height) { + + Image _image = Image (image); + ImageBuffer _buffer = ImageBuffer (buffer); + ImageDataUtil::Resize (&_image, &_buffer, width, height); + + } + + + HL_PRIM void HL_NAME(hl_image_data_util_resize) (Image* image, ImageBuffer* buffer, int width, int height) { + + ImageDataUtil::Resize (image, buffer, width, height); + + } + + + void lime_image_data_util_set_format (value image, int format) { + + Image _image = Image (image); + PixelFormat _format = (PixelFormat)format; + ImageDataUtil::SetFormat (&_image, _format); + + } + + + HL_PRIM void HL_NAME(hl_image_data_util_set_format) (Image* image, PixelFormat format) { + + ImageDataUtil::SetFormat (image, format); + + } + + + void lime_image_data_util_set_pixels (value image, value rect, value bytes, int offset, int format, int endian) { + + Image _image = Image (image); + Rectangle _rect = Rectangle (rect); + Bytes _bytes (bytes); + PixelFormat _format = (PixelFormat)format; + Endian _endian = (Endian)endian; + ImageDataUtil::SetPixels (&_image, &_rect, &_bytes, offset, _format, _endian); + + } + + + HL_PRIM void HL_NAME(hl_image_data_util_set_pixels) (Image* image, Rectangle* rect, Bytes* bytes, int offset, PixelFormat format, Endian endian) { + + ImageDataUtil::SetPixels (image, rect, bytes, offset, format, endian); + + } + + + int lime_image_data_util_threshold (value image, value sourceImage, value sourceRect, value destPoint, int operation, int thresholdRG, int thresholdBA, int colorRG, int colorBA, int maskRG, int maskBA, bool copySource) { + + Image _image = Image (image); + Image _sourceImage = Image (sourceImage); + Rectangle _sourceRect = Rectangle (sourceRect); + Vector2 _destPoint = Vector2 (destPoint); + int32_t threshold = (thresholdRG << 16) | thresholdBA; + int32_t color = (colorRG << 16) | colorBA; + int32_t mask = (maskRG << 16) | maskBA; + return ImageDataUtil::Threshold (&_image, &_sourceImage, &_sourceRect, &_destPoint, operation, threshold, color, mask, copySource); + + } + + + HL_PRIM int HL_NAME(hl_image_data_util_threshold) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int operation, int thresholdRG, int thresholdBA, int colorRG, int colorBA, int maskRG, int maskBA, bool copySource) { + + int32_t threshold = (thresholdRG << 16) | thresholdBA; + int32_t color = (colorRG << 16) | colorBA; + int32_t mask = (maskRG << 16) | maskBA; + return ImageDataUtil::Threshold (image, sourceImage, sourceRect, destPoint, operation, threshold, color, mask, copySource); + + } + + + void lime_image_data_util_unmultiply_alpha (value image) { + + Image _image = Image (image); + ImageDataUtil::UnmultiplyAlpha (&_image); + + } + + + HL_PRIM void HL_NAME(hl_image_data_util_unmultiply_alpha) (Image* image) { + + ImageDataUtil::UnmultiplyAlpha (image); + + } + + + double lime_jni_getenv () { + + #ifdef ANDROID + return (uintptr_t)JNI::GetEnv (); + #else + return 0; + #endif + + } + + + HL_PRIM double HL_NAME(hl_jni_getenv) () { + + #ifdef ANDROID + return (uintptr_t)JNI::GetEnv (); + #else + return 0; + #endif + + } + + + void lime_joystick_event_manager_register (value callback, value eventObject) { + + JoystickEvent::callback = new ValuePointer (callback); + JoystickEvent::eventObject = new ValuePointer (eventObject); + + } + + + HL_PRIM void HL_NAME(hl_joystick_event_manager_register) (vclosure* callback, JoystickEvent* eventObject) { + + JoystickEvent::callback = new ValuePointer (callback); + JoystickEvent::eventObject = new ValuePointer ((vobj*)eventObject); + + } + + + value lime_joystick_get_device_guid (int id) { + + const char* guid = Joystick::GetDeviceGUID (id); + return guid ? alloc_string (guid) : alloc_null (); + + } + + + HL_PRIM vbyte* HL_NAME(hl_joystick_get_device_guid) (int id) { + + return (vbyte*)Joystick::GetDeviceGUID (id); + + } + + + value lime_joystick_get_device_name (int id) { + + const char* name = Joystick::GetDeviceName (id); + return name ? alloc_string (name) : alloc_null (); + + } + + + HL_PRIM vbyte* HL_NAME(hl_joystick_get_device_name) (int id) { + + return (vbyte*)Joystick::GetDeviceName (id); + + } + + + int lime_joystick_get_num_axes (int id) { + + return Joystick::GetNumAxes (id); + + } + + + HL_PRIM int HL_NAME(hl_joystick_get_num_axes) (int id) { + + return Joystick::GetNumAxes (id); + + } + + + int lime_joystick_get_num_buttons (int id) { + + return Joystick::GetNumButtons (id); + + } + + + HL_PRIM int HL_NAME(hl_joystick_get_num_buttons) (int id) { + + return Joystick::GetNumButtons (id); + + } + + + int lime_joystick_get_num_hats (int id) { + + return Joystick::GetNumHats (id); + + } + + + HL_PRIM int HL_NAME(hl_joystick_get_num_hats) (int id) { + + return Joystick::GetNumHats (id); + + } + + + value lime_jpeg_decode_bytes (value data, bool decodeData, value buffer) { + + ImageBuffer imageBuffer (buffer); + + Bytes bytes (data); + Resource resource = Resource (&bytes); + + #ifdef LIME_JPEG + if (JPEG::Decode (&resource, &imageBuffer, decodeData)) { + + return imageBuffer.Value (buffer); + + } + #endif + + return alloc_null (); + + } + + + HL_PRIM ImageBuffer* HL_NAME(hl_jpeg_decode_bytes) (Bytes* data, bool decodeData, ImageBuffer* buffer) { + + Resource resource = Resource (data); + + #ifdef LIME_JPEG + if (JPEG::Decode (&resource, buffer, decodeData)) { + + return buffer; + + } + #endif + + return 0; + + } + + + value lime_jpeg_decode_file (HxString path, bool decodeData, value buffer) { + + ImageBuffer imageBuffer (buffer); + Resource resource = Resource (hxs_utf8 (path, nullptr)); + + #ifdef LIME_JPEG + if (JPEG::Decode (&resource, &imageBuffer, decodeData)) { + + return imageBuffer.Value (buffer); + + } + #endif + + return alloc_null (); + + } + + + HL_PRIM ImageBuffer* HL_NAME(hl_jpeg_decode_file) (hl_vstring* path, bool decodeData, ImageBuffer* buffer) { + + Resource resource = Resource (path); + + #ifdef LIME_JPEG + if (JPEG::Decode (&resource, buffer, decodeData)) { + + return buffer; + + } + #endif + + return 0; + + } + + + int lime_key_code_from_scan_code (int scanCode) { + + return KeyCode::FromScanCode (scanCode); + + } + + + HL_PRIM int HL_NAME(hl_key_code_from_scan_code) (int scanCode) { + + return KeyCode::FromScanCode (scanCode); + + } + + + int lime_key_code_to_scan_code (int keyCode) { + + return KeyCode::ToScanCode (keyCode); + + } + + + HL_PRIM int HL_NAME(hl_key_code_to_scan_code) (int keyCode) { + + return KeyCode::ToScanCode (keyCode); + + } + + + void lime_key_event_manager_register (value callback, value eventObject) { + + KeyEvent::callback = new ValuePointer (callback); + KeyEvent::eventObject = new ValuePointer (eventObject); + + } + + + HL_PRIM void HL_NAME(hl_key_event_manager_register) (vclosure* callback, KeyEvent* eventObject) { + + KeyEvent::callback = new ValuePointer (callback); + KeyEvent::eventObject = new ValuePointer ((vobj*)eventObject); + + } + + + value lime_locale_get_system_locale () { + + std::string* locale = Locale::GetSystemLocale (); + + if (!locale) { + + return alloc_null (); + + } else { + + value result = alloc_string (locale->c_str ()); + delete locale; + return result; + + } + + } + + + HL_PRIM vbyte* HL_NAME(hl_locale_get_system_locale) () { + + std::string* locale = Locale::GetSystemLocale (); + + if (!locale) { + + return 0; + + } else { + + int size = locale->size (); + char* _locale = (char*)malloc (size + 1); + strncpy (_locale, locale->c_str (), size); + _locale[size] = '\0'; + delete locale; + + return (vbyte*)_locale; + + } + + } + + + value lime_lzma_compress (value buffer, value bytes) { + + #ifdef LIME_LZMA + Bytes data (buffer); + Bytes result (bytes); + + LZMA::Compress (&data, &result); + + return result.Value (bytes); + #else + return alloc_null (); + #endif + + } + + + HL_PRIM Bytes* HL_NAME(hl_lzma_compress) (Bytes* buffer, Bytes* bytes) { + + #ifdef LIME_LZMA + LZMA::Compress (buffer, bytes); + return bytes; + #else + return 0; + #endif + + } + + + value lime_lzma_decompress (value buffer, value bytes) { + + #ifdef LIME_LZMA + Bytes data (buffer); + Bytes result (bytes); + + LZMA::Decompress (&data, &result); + + return result.Value (bytes); + #else + return alloc_null (); + #endif + + } + + + HL_PRIM Bytes* HL_NAME(hl_lzma_decompress) (Bytes* buffer, Bytes* bytes) { + + #ifdef LIME_LZMA + LZMA::Decompress (buffer, bytes); + return bytes; + #else + return 0; + #endif + + } + + + void lime_mouse_event_manager_register (value callback, value eventObject) { + + MouseEvent::callback = new ValuePointer (callback); + MouseEvent::eventObject = new ValuePointer (eventObject); + + } + + + HL_PRIM void HL_NAME(hl_mouse_event_manager_register) (vclosure* callback, MouseEvent* eventObject) { + + MouseEvent::callback = new ValuePointer (callback); + MouseEvent::eventObject = new ValuePointer ((vobj*)eventObject); + + } + + + void lime_neko_execute (HxString module) { + + #ifdef LIME_NEKO + NekoVM::Execute (module.c_str ()); + #endif + + } + + + void lime_orientation_event_manager_register (value callback, value eventObject) { + + OrientationEvent::callback = new ValuePointer (callback); + OrientationEvent::eventObject = new ValuePointer (eventObject); + System::EnableDeviceOrientationChange(true); + + } + + + HL_PRIM void HL_NAME(hl_orientation_event_manager_register) (vclosure* callback, OrientationEvent* eventObject) { + + OrientationEvent::callback = new ValuePointer (callback); + OrientationEvent::eventObject = new ValuePointer ((vobj*)eventObject); + + } + + + value lime_png_decode_bytes (value data, bool decodeData, value buffer) { + + ImageBuffer imageBuffer (buffer); + Bytes bytes (data); + Resource resource = Resource (&bytes); + + #ifdef LIME_PNG + if (PNG::Decode (&resource, &imageBuffer, decodeData)) { + + return imageBuffer.Value (buffer); + + } + #endif + + return alloc_null (); + + } + + + HL_PRIM ImageBuffer* HL_NAME(hl_png_decode_bytes) (Bytes* data, bool decodeData, ImageBuffer* buffer) { + + Resource resource = Resource (data); + + #ifdef LIME_PNG + if (PNG::Decode (&resource, buffer, decodeData)) { + + return buffer; + + } + #endif + + return 0; + + } + + + value lime_png_decode_file (HxString path, bool decodeData, value buffer) { + + ImageBuffer imageBuffer (buffer); + Resource resource = Resource (hxs_utf8 (path, nullptr)); + + #ifdef LIME_PNG + if (PNG::Decode (&resource, &imageBuffer, decodeData)) { + + return imageBuffer.Value (buffer); + + } + #endif + + return alloc_null (); + + } + + + HL_PRIM ImageBuffer* HL_NAME(hl_png_decode_file) (hl_vstring* path, bool decodeData, ImageBuffer* buffer) { + + Resource resource = Resource (path); + + #ifdef LIME_PNG + if (PNG::Decode (&resource, buffer, decodeData)) { + + return buffer; + + } + #endif + + return 0; + + } + + + void lime_render_event_manager_register (value callback, value eventObject) { + + RenderEvent::callback = new ValuePointer (callback); + RenderEvent::eventObject = new ValuePointer (eventObject); + + } + + + HL_PRIM void HL_NAME(hl_render_event_manager_register) (vclosure* callback, RenderEvent* eventObject) { + + RenderEvent::callback = new ValuePointer (callback); + RenderEvent::eventObject = new ValuePointer ((vobj*)eventObject); + + } + + + void lime_sensor_event_manager_register (value callback, value eventObject) { + + SensorEvent::callback = new ValuePointer (callback); + SensorEvent::eventObject = new ValuePointer (eventObject); + + } + + + HL_PRIM void HL_NAME(hl_sensor_event_manager_register) (vclosure* callback, SensorEvent* eventObject) { + + SensorEvent::callback = new ValuePointer (callback); + SensorEvent::eventObject = new ValuePointer ((vobj*)eventObject); + + } + + + bool lime_system_get_allow_screen_timeout () { + + return System::GetAllowScreenTimeout (); + + } + + + HL_PRIM bool HL_NAME(hl_system_get_allow_screen_timeout) () { + + return System::GetAllowScreenTimeout (); + + } + + + value lime_system_get_device_model () { + + std::wstring* model = System::GetDeviceModel (); + + if (model) { + + value result = alloc_wstring (model->c_str ()); + delete model; + return result; + + } else { + + return alloc_null (); + + } + + } + + + HL_PRIM vbyte* HL_NAME(hl_system_get_device_model) () { + + #ifndef EMSCRIPTEN + + std::wstring* model = System::GetDeviceModel (); + + if (model) { + + vbyte* const result = hl_wstring_to_utf8_bytes (*model); + delete model; + return result; + + } + + #endif + + return 0; + + } + + + value lime_system_get_device_vendor () { + + std::wstring* vendor = System::GetDeviceVendor (); + + if (vendor) { + + value result = alloc_wstring (vendor->c_str ()); + delete vendor; + return result; + + } else { + + return alloc_null (); + + } + + } + + + HL_PRIM vbyte* HL_NAME(hl_system_get_device_vendor) () { + + #ifndef EMSCRIPTEN + + std::wstring* vendor = System::GetDeviceVendor (); + + if (vendor) { + + vbyte* const result = hl_wstring_to_utf8_bytes (*vendor); + delete vendor; + return result; + + } + + #endif + + return 0; + + } + + + value lime_system_get_directory (int type, HxString company, HxString title) { + + std::wstring* path = System::GetDirectory ((SystemDirectory)type, hxs_utf8 (company, nullptr), hxs_utf8 (title, nullptr)); + + if (path) { + + value result = alloc_wstring (path->c_str ()); + delete path; + return result; + + } else { + + return alloc_null (); + + } + + } + + + HL_PRIM vbyte* HL_NAME(hl_system_get_directory) (int type, hl_vstring* company, hl_vstring* title) { + + #ifndef EMSCRIPTEN + + std::wstring* path = System::GetDirectory ((SystemDirectory)type, company ? (char*)hl_to_utf8 ((const uchar*)company->bytes) : NULL, title ? (char*)hl_to_utf8 ((const uchar*)title->bytes) : NULL); + + if (path) { + + vbyte* const result = hl_wstring_to_utf8_bytes (*path); + delete path; + return result; + + } + + #endif + + return 0; + + } + + + value lime_system_get_display (int id) { + + return (value)System::GetDisplay (true, id); + + } + + + HL_PRIM vdynamic* HL_NAME(hl_system_get_display) (int id) { + + return (vdynamic*)System::GetDisplay (false, id); + + } + + + bool lime_system_get_ios_tablet () { + + #ifdef IPHONE + return System::GetIOSTablet (); + #else + return false; + #endif + + } + + + HL_PRIM bool HL_NAME(hl_system_get_ios_tablet) () { + + #ifdef IPHONE + return System::GetIOSTablet (); + #else + return false; + #endif + + } + + + int lime_system_get_num_displays () { + + return System::GetNumDisplays (); + + } + + + HL_PRIM int HL_NAME(hl_system_get_num_displays) () { + + return System::GetNumDisplays (); + + } + + + int lime_system_get_device_orientation () { + + return System::GetDeviceOrientation(); + + } + + + HL_PRIM int HL_NAME(hl_system_get_device_orientation) () { + + return System::GetDeviceOrientation(); + + } + + + value lime_system_get_platform_label () { + + std::wstring* label = System::GetPlatformLabel (); + + if (label) { + + value result = alloc_wstring (label->c_str ()); + delete label; + return result; + + } else { + + return alloc_null (); + + } + + } + + + HL_PRIM vbyte* HL_NAME(hl_system_get_platform_label) () { + + #ifndef EMSCRIPTEN + + std::wstring* label = System::GetPlatformLabel (); + + if (label) { + + vbyte* const result = hl_wstring_to_utf8_bytes (*label); + delete label; + return result; + + } + + #endif + + return 0; + + } + + + value lime_system_get_platform_name () { + + std::wstring* name = System::GetPlatformName (); + + if (name) { + + value result = alloc_wstring (name->c_str ()); + delete name; + return result; + + } else { + + return 0; + + } + + } + + + HL_PRIM vbyte* HL_NAME(hl_system_get_platform_name) () { + + #ifndef EMSCRIPTEN + + std::wstring* name = System::GetPlatformName (); + + if (name) { + + vbyte* const result = hl_wstring_to_utf8_bytes (*name); + delete name; + return result; + + } + + #endif + + return 0; + + } + + + value lime_system_get_platform_version () { + + std::wstring* version = System::GetPlatformVersion (); + + if (version) { + + value result = alloc_wstring (version->c_str ()); + delete version; + return result; + + } else { + + return alloc_null (); + + } + + } + + + HL_PRIM vbyte* HL_NAME(hl_system_get_platform_version) () { + + #ifndef EMSCRIPTEN + + std::wstring* version = System::GetPlatformVersion (); + + if (version) { + + vbyte* const result = hl_wstring_to_utf8_bytes (*version); + delete version; + return result; + } + + #endif + + return 0; + + } + + + double lime_system_get_timer () { + + return System::GetTimer (); + + } + + + HL_PRIM double HL_NAME(hl_system_get_timer) () { + + return System::GetTimer (); + + } + + + int lime_system_get_windows_console_mode (int handleType) { + + #if defined (HX_WINDOWS) && !defined (HX_WINRT) + return System::GetWindowsConsoleMode (handleType); + #else + return 0; + #endif + + } + + + HL_PRIM int HL_NAME(hl_system_get_windows_console_mode) (int handleType) { + + #if defined (HX_WINDOWS) && !defined (HX_WINRT) + return System::GetWindowsConsoleMode (handleType); + #else + return 0; + #endif + + } + + + void lime_system_open_file (HxString path) { + + #ifdef IPHONE + System::OpenFile (path.c_str ()); + #endif + + } + + + HL_PRIM void HL_NAME(hl_system_open_file) (vbyte* path) { + + #ifdef IPHONE + System::OpenFile ((char*)path); + #endif + + } + + + void lime_system_open_url (HxString url, HxString target) { + + #ifdef IPHONE + System::OpenURL (url.c_str (), target.c_str ()); + #endif + + } + + + HL_PRIM void HL_NAME(hl_system_open_url) (vbyte* url, vbyte* target) { + + #ifdef IPHONE + System::OpenURL ((char*)url, (char*)target); + #endif + + } + + + bool lime_system_set_allow_screen_timeout (bool allow) { + + return System::SetAllowScreenTimeout (allow); + + } + + + HL_PRIM bool HL_NAME(hl_system_set_allow_screen_timeout) (bool allow) { + + return System::SetAllowScreenTimeout (allow); + + } + + + bool lime_system_set_windows_console_mode (int handleType, int mode) { + + #if defined (HX_WINDOWS) && !defined (HX_WINRT) + return System::SetWindowsConsoleMode (handleType, mode); + #else + return false; + #endif + + } + + + HL_PRIM bool HL_NAME(hl_system_set_windows_console_mode) (int handleType, int mode) { + + #if defined (HX_WINDOWS) && !defined (HX_WINRT) + return System::SetWindowsConsoleMode (handleType, mode); + #else + return false; + #endif + + } + + + void lime_text_event_manager_register (value callback, value eventObject) { + + TextEvent::callback = new ValuePointer (callback); + TextEvent::eventObject = new ValuePointer (eventObject); + + } + + + HL_PRIM void HL_NAME(hl_text_event_manager_register) (vclosure* callback, TextEvent* eventObject) { + + TextEvent::callback = new ValuePointer (callback); + TextEvent::eventObject = new ValuePointer ((vobj*)eventObject); + + } + + + void lime_touch_event_manager_register (value callback, value eventObject) { + + TouchEvent::callback = new ValuePointer (callback); + TouchEvent::eventObject = new ValuePointer (eventObject); + + } + + + HL_PRIM void HL_NAME(hl_touch_event_manager_register) (vclosure* callback, TouchEvent* eventObject) { + + TouchEvent::callback = new ValuePointer (callback); + TouchEvent::eventObject = new ValuePointer ((vobj*)eventObject); + + } + + + void lime_window_alert (value window, HxString message, HxString title) { + + Window* targetWindow = (Window*)val_data (window); + targetWindow->Alert (hxs_utf8 (message, nullptr), hxs_utf8 (title, nullptr)); + + } + + + HL_PRIM void HL_NAME(hl_window_alert) (HL_CFFIPointer* window, hl_vstring* message, hl_vstring* title) { + + Window* targetWindow = (Window*)window->ptr; + const char *cmessage = message ? hl_to_utf8(message->bytes) : nullptr; + const char *ctitle = title ? hl_to_utf8(title->bytes) : nullptr; + targetWindow->Alert (cmessage, ctitle); + + } + + + void lime_window_close (value window) { + + Window* targetWindow = (Window*)val_data (window); + targetWindow->Close (); + + } + + + HL_PRIM void HL_NAME(hl_window_close) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + targetWindow->Close (); + + } + + + void lime_window_context_flip (value window) { + + ((Window*)val_data (window))->ContextFlip (); + + } + + + HL_PRIM void HL_NAME(hl_window_context_flip) (HL_CFFIPointer* window) { + + ((Window*)window->ptr)->ContextFlip (); + + } + + + value lime_window_context_lock (value window) { + + return (value)((Window*)val_data (window))->ContextLock (true); + + } + + + HL_PRIM vdynamic* HL_NAME(hl_window_context_lock) (HL_CFFIPointer* window) { + + return (vdynamic*)((Window*)window->ptr)->ContextLock (false); + + } + + + void lime_window_context_make_current (value window) { + + ((Window*)val_data (window))->ContextMakeCurrent (); + + } + + + HL_PRIM void HL_NAME(hl_window_context_make_current) (HL_CFFIPointer* window) { + + ((Window*)window->ptr)->ContextMakeCurrent (); + + } + + + void lime_window_context_unlock (value window) { + + ((Window*)val_data (window))->ContextUnlock (); + + } + + + HL_PRIM void HL_NAME(hl_window_context_unlock) (HL_CFFIPointer* window) { + + ((Window*)window->ptr)->ContextUnlock (); + + } + + + value lime_window_create (value application, int width, int height, int flags, HxString title) { + + Window* window = CreateWindow ((Application*)val_data (application), width, height, flags, hxs_utf8 (title, nullptr)); + return CFFIPointer (window, gc_window); + + } + + + HL_PRIM HL_CFFIPointer* HL_NAME(hl_window_create) (HL_CFFIPointer* application, int width, int height, int flags, hl_vstring* title) { + + Window* window = CreateWindow ((Application*)application->ptr, width, height, flags, (const char*)hl_to_utf8 ((const uchar*)title->bytes)); + return HLCFFIPointer (window, (hl_finalizer)hl_gc_window); + + } + + + void lime_window_event_manager_register (value callback, value eventObject) { + + WindowEvent::callback = new ValuePointer (callback); + WindowEvent::eventObject = new ValuePointer (eventObject); + + } + + + HL_PRIM void HL_NAME(hl_window_event_manager_register) (vclosure* callback, WindowEvent* eventObject) { + + WindowEvent::callback = new ValuePointer (callback); + WindowEvent::eventObject = new ValuePointer ((vobj*)eventObject); + + } + + + void lime_window_focus (value window) { + + Window* targetWindow = (Window*)val_data (window); + targetWindow->Focus (); + + } + + + HL_PRIM void HL_NAME(hl_window_focus) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + targetWindow->Focus (); + + } + + + double lime_window_get_context (value window) { + + Window* targetWindow = (Window*)val_data (window); + return (uintptr_t)targetWindow->GetContext (); + + } + + + HL_PRIM double HL_NAME(hl_window_get_context) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + return (uintptr_t)targetWindow->GetContext (); + + } + + + value lime_window_get_context_type (value window) { + + Window* targetWindow = (Window*)val_data (window); + const char* type = targetWindow->GetContextType (); + return type ? alloc_string (type) : alloc_null (); + + } + + + HL_PRIM vbyte* HL_NAME(hl_window_get_context_type) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + return (vbyte*)targetWindow->GetContextType (); + + } + + + value lime_window_get_vulkan_instance_extensions (value window) { + + Window* targetWindow = (Window*)val_data (window); + unsigned int count = 0; + + if (!targetWindow->GetVulkanInstanceExtensions (&count, 0) || count == 0) { + + return alloc_array (0); + + } + + std::vector names (count); + if (!targetWindow->GetVulkanInstanceExtensions (&count, names.data ())) { + + return alloc_array (0); + + } + + value result = alloc_array (count); + + for (unsigned int i = 0; i < count; ++i) { + + val_array_set_i (result, i, alloc_string (names[i])); + + } + + return result; + + } + + + HL_PRIM hl_varray* HL_NAME(hl_window_get_vulkan_instance_extensions) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + unsigned int count = 0; + + if (!targetWindow->GetVulkanInstanceExtensions (&count, 0) || count == 0) { + + return hl_alloc_array (&hlt_bytes, 0); + + } + + std::vector names (count); + if (!targetWindow->GetVulkanInstanceExtensions (&count, names.data ())) { + + return hl_alloc_array (&hlt_bytes, 0); + + } + + hl_varray* result = (hl_varray*)hl_alloc_array (&hlt_bytes, count); + vbyte** resultData = hl_aptr (result, vbyte*); + + for (unsigned int i = 0; i < count; ++i) { + + *resultData++ = hl_copy_bytes ((const vbyte*)names[i], (int)std::strlen (names[i]) + 1); + + } + + return result; + + } + + + value lime_window_get_vulkan_drawable_size (value window) { + + Window* targetWindow = (Window*)val_data (window); + int width = 0; + int height = 0; + targetWindow->GetVulkanDrawableSize (&width, &height); + + value result = alloc_empty_object (); + alloc_field (result, val_id ("width"), alloc_int (width)); + alloc_field (result, val_id ("height"), alloc_int (height)); + return result; + + } + + + HL_PRIM vdynamic* HL_NAME(hl_window_get_vulkan_drawable_size) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + int width = 0; + int height = 0; + targetWindow->GetVulkanDrawableSize (&width, &height); + + const int id_width = hl_hash_utf8 ("width"); + const int id_height = hl_hash_utf8 ("height"); + vdynamic* result = (vdynamic*)hl_alloc_dynobj(); + hl_dyn_seti (result, id_width, &hlt_i32, width); + hl_dyn_seti (result, id_height, &hlt_i32, height); + return result; + + } + + + value lime_window_get_vulkan_instance_proc_addr (value window) { + + Window* targetWindow = (Window*)val_data (window); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)targetWindow->GetVulkanInstanceProcAddr ()); + + } + + + HL_PRIM vdynamic* HL_NAME(hl_window_get_vulkan_instance_proc_addr) (HL_CFFIPointer* window) { + + Window* targetWindow = (Window*)window->ptr; + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)targetWindow->GetVulkanInstanceProcAddr ()); + + } + + + value lime_window_create_vulkan_surface (value window, int instanceHigh, int instanceLow) { + + Window* targetWindow = (Window*)val_data (window); + uint64_t surface = targetWindow->CreateVulkanSurface ((uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow)); + + if (!surface) { + + return alloc_null (); + + } + + return CreateVulkanHandleValue (surface); + + } + + + HL_PRIM vdynamic* HL_NAME(hl_window_create_vulkan_surface) (HL_CFFIPointer* window, int instanceHigh, int instanceLow) { + + Window* targetWindow = (Window*)window->ptr; + uint64_t surface = targetWindow->CreateVulkanSurface ((uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow)); + + if (!surface) { + + return 0; + + } + + return HLCreateVulkanHandleValue (surface); + + } + + + value lime_vk_create_instance (value window, HxString applicationName) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = VK_NULL_HANDLE; + + if (!CreateManagedVulkanInstance (targetWindow, applicationName.c_str () ? hxs_utf8 (applicationName, nullptr) : 0, &instance)) { + + return alloc_null (); + + } + + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)instance); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_instance) (HL_CFFIPointer* window, hl_vstring* applicationName) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = VK_NULL_HANDLE; + const char* applicationNameUTF8 = applicationName ? (const char*)hl_to_utf8 ((const uchar*)applicationName->bytes) : 0; + + if (!CreateManagedVulkanInstance (targetWindow, applicationNameUTF8, &instance)) { + + return 0; + + } + + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)instance); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_instance (value window, int instanceHigh, int instanceLow) { + +#ifdef LIME_VULKAN + if (instanceHigh == 0 && instanceLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + PFN_vkDestroyInstance vkDestroyInstance = (PFN_vkDestroyInstance)vkGetInstanceProcAddr (instance, "vkDestroyInstance"); + if (vkDestroyInstance) { + + vkDestroyInstance (instance, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_instance) (HL_CFFIPointer* window, int instanceHigh, int instanceLow) { + +#ifdef LIME_VULKAN + if (instanceHigh == 0 && instanceLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + PFN_vkDestroyInstance vkDestroyInstance = (PFN_vkDestroyInstance)vkGetInstanceProcAddr (instance, "vkDestroyInstance"); + if (vkDestroyInstance) { + + vkDestroyInstance (instance, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + void lime_vk_destroy_surface (value window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + +#ifdef LIME_VULKAN + if (instanceHigh == 0 && instanceLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + if (!surface) return; + + PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)vkGetInstanceProcAddr (instance, "vkDestroySurfaceKHR"); + if (vkDestroySurfaceKHR) { + + vkDestroySurfaceKHR (instance, surface, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_surface) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + +#ifdef LIME_VULKAN + if (instanceHigh == 0 && instanceLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + if (!surface) return; + + PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)vkGetInstanceProcAddr (instance, "vkDestroySurfaceKHR"); + if (vkDestroySurfaceKHR) { + + vkDestroySurfaceKHR (instance, surface, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_get_physical_devices (value window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + + if (!targetWindow || !instance) { + + lastVKError = "Missing Vulkan window or instance"; + return alloc_null (); + + } + + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + if (!vkGetInstanceProcAddr) { + + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + return alloc_null (); + + } + + PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices)vkGetInstanceProcAddr (instance, + "vkEnumeratePhysicalDevices"); + PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)vkGetInstanceProcAddr (instance, + "vkGetPhysicalDeviceProperties"); + PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties = + (PFN_vkGetPhysicalDeviceQueueFamilyProperties)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceQueueFamilyProperties"); + PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = + (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfaceSupportKHR"); + + if (!vkEnumeratePhysicalDevices || !vkGetPhysicalDeviceProperties || !vkGetPhysicalDeviceQueueFamilyProperties) { + + lastVKError = "Missing required Vulkan instance functions"; + return alloc_null (); + + } + + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + uint32_t deviceCount = 0; + VkResult result = vkEnumeratePhysicalDevices (instance, &deviceCount, 0); + + if (result != VK_SUCCESS) { + + lastVKError = "vkEnumeratePhysicalDevices failed"; + return alloc_null (); + + } + + value devices = alloc_array (deviceCount); + if (deviceCount == 0) { + + lastVKError.clear (); + return devices; + + } + + std::vector physicalDevices (deviceCount); + result = vkEnumeratePhysicalDevices (instance, &deviceCount, physicalDevices.data ()); + + if (result != VK_SUCCESS) { + + lastVKError = "vkEnumeratePhysicalDevices returned incomplete data"; + return alloc_null (); + + } + + const int id_handle = val_id ("handle"); + const int id_name = val_id ("name"); + const int id_apiVersion = val_id ("apiVersion"); + const int id_driverVersion = val_id ("driverVersion"); + const int id_vendorID = val_id ("vendorID"); + const int id_deviceID = val_id ("deviceID"); + const int id_deviceType = val_id ("deviceType"); + const int id_framebufferColorSampleCounts = val_id ("framebufferColorSampleCounts"); + const int id_framebufferDepthSampleCounts = val_id ("framebufferDepthSampleCounts"); + const int id_framebufferNoAttachmentsSampleCounts = val_id ("framebufferNoAttachmentsSampleCounts"); + const int id_framebufferStencilSampleCounts = val_id ("framebufferStencilSampleCounts"); + const int id_maxPushConstantsSize = val_id ("maxPushConstantsSize"); + const int id_minStorageBufferOffsetAlignment = val_id ("minStorageBufferOffsetAlignment"); + const int id_minUniformBufferOffsetAlignment = val_id ("minUniformBufferOffsetAlignment"); + const int id_nonCoherentAtomSize = val_id ("nonCoherentAtomSize"); + const int id_queueFamilies = val_id ("queueFamilies"); + + const int id_index = val_id ("index"); + const int id_flags = val_id ("flags"); + const int id_queueCount = val_id ("queueCount"); + const int id_timestampValidBits = val_id ("timestampValidBits"); + const int id_supportsGraphics = val_id ("supportsGraphics"); + const int id_supportsCompute = val_id ("supportsCompute"); + const int id_supportsTransfer = val_id ("supportsTransfer"); + const int id_supportsPresent = val_id ("supportsPresent"); + + for (uint32_t i = 0; i < deviceCount; ++i) { + + VkPhysicalDeviceProperties properties; + memset (&properties, 0, sizeof (properties)); + vkGetPhysicalDeviceProperties (physicalDevices[i], &properties); + + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, 0); + std::vector queueFamilies (queueFamilyCount); + if (queueFamilyCount > 0) { + + vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, queueFamilies.data ()); + + } + + value queueFamilyArray = alloc_array (queueFamilyCount); + + for (uint32_t q = 0; q < queueFamilyCount; ++q) { + + VkBool32 supportsPresent = VK_FALSE; + if (surface && vkGetPhysicalDeviceSurfaceSupportKHR) { + + vkGetPhysicalDeviceSurfaceSupportKHR (physicalDevices[i], q, surface, &supportsPresent); + + } + + value queueFamilyObject = alloc_empty_object (); + alloc_field (queueFamilyObject, id_index, alloc_int (q)); + alloc_field (queueFamilyObject, id_flags, alloc_int (queueFamilies[q].queueFlags)); + alloc_field (queueFamilyObject, id_queueCount, alloc_int (queueFamilies[q].queueCount)); + alloc_field (queueFamilyObject, id_timestampValidBits, alloc_int (queueFamilies[q].timestampValidBits)); + alloc_field (queueFamilyObject, id_supportsGraphics, alloc_bool ((queueFamilies[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)); + alloc_field (queueFamilyObject, id_supportsCompute, alloc_bool ((queueFamilies[q].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0)); + alloc_field (queueFamilyObject, id_supportsTransfer, alloc_bool ((queueFamilies[q].queueFlags & VK_QUEUE_TRANSFER_BIT) != 0)); + alloc_field (queueFamilyObject, id_supportsPresent, alloc_bool (supportsPresent != VK_FALSE)); + val_array_set_i (queueFamilyArray, q, queueFamilyObject); + + } + + value deviceObject = alloc_empty_object (); + alloc_field (deviceObject, id_handle, CreateVulkanHandleValue ((uint64_t)(uintptr_t)physicalDevices[i])); + alloc_field (deviceObject, id_name, alloc_string (properties.deviceName)); + alloc_field (deviceObject, id_apiVersion, alloc_int (properties.apiVersion)); + alloc_field (deviceObject, id_driverVersion, alloc_int (properties.driverVersion)); + alloc_field (deviceObject, id_vendorID, alloc_int (properties.vendorID)); + alloc_field (deviceObject, id_deviceID, alloc_int (properties.deviceID)); + alloc_field (deviceObject, id_deviceType, alloc_int (properties.deviceType)); + alloc_field (deviceObject, id_framebufferColorSampleCounts, alloc_int ((int)properties.limits.framebufferColorSampleCounts)); + alloc_field (deviceObject, id_framebufferDepthSampleCounts, alloc_int ((int)properties.limits.framebufferDepthSampleCounts)); + alloc_field (deviceObject, id_framebufferNoAttachmentsSampleCounts, alloc_int ((int)properties.limits.framebufferNoAttachmentsSampleCounts)); + alloc_field (deviceObject, id_framebufferStencilSampleCounts, alloc_int ((int)properties.limits.framebufferStencilSampleCounts)); + alloc_field (deviceObject, id_maxPushConstantsSize, alloc_int ((int)properties.limits.maxPushConstantsSize)); + alloc_field (deviceObject, id_minStorageBufferOffsetAlignment, + CreateVulkanHandleValue ((uint64_t)properties.limits.minStorageBufferOffsetAlignment)); + alloc_field (deviceObject, id_minUniformBufferOffsetAlignment, + CreateVulkanHandleValue ((uint64_t)properties.limits.minUniformBufferOffsetAlignment)); + alloc_field (deviceObject, id_nonCoherentAtomSize, CreateVulkanHandleValue ((uint64_t)properties.limits.nonCoherentAtomSize)); + alloc_field (deviceObject, id_queueFamilies, queueFamilyArray); + val_array_set_i (devices, i, deviceObject); + + } + + lastVKError.clear (); + return devices; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_array (0); +#endif + + } + + + HL_PRIM hl_varray* HL_NAME(hl_vk_get_physical_devices) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int surfaceHigh, int surfaceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + + if (!targetWindow || !instance) { + + lastVKError = "Missing Vulkan window or instance"; + return 0; + + } + + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr (); + if (!vkGetInstanceProcAddr) { + + lastVKError = "SDL did not expose vkGetInstanceProcAddr"; + return 0; + + } + + PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices)vkGetInstanceProcAddr (instance, + "vkEnumeratePhysicalDevices"); + PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)vkGetInstanceProcAddr (instance, + "vkGetPhysicalDeviceProperties"); + PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties = + (PFN_vkGetPhysicalDeviceQueueFamilyProperties)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceQueueFamilyProperties"); + PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = + (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)vkGetInstanceProcAddr (instance, "vkGetPhysicalDeviceSurfaceSupportKHR"); + + if (!vkEnumeratePhysicalDevices || !vkGetPhysicalDeviceProperties || !vkGetPhysicalDeviceQueueFamilyProperties) { + + lastVKError = "Missing required Vulkan instance functions"; + return 0; + + } + + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + uint32_t deviceCount = 0; + VkResult result = vkEnumeratePhysicalDevices (instance, &deviceCount, 0); + + if (result != VK_SUCCESS) { + + lastVKError = "vkEnumeratePhysicalDevices failed"; + return 0; + + } + + hl_varray* devices = (hl_varray*)hl_alloc_array (&hlt_dynobj, deviceCount); + if (deviceCount == 0) { + + lastVKError.clear (); + return devices; + + } + + std::vector physicalDevices (deviceCount); + result = vkEnumeratePhysicalDevices (instance, &deviceCount, physicalDevices.data ()); + + if (result != VK_SUCCESS) { + + lastVKError = "vkEnumeratePhysicalDevices returned incomplete data"; + return 0; + + } + + vdynamic** deviceData = hl_aptr (devices, vdynamic*); + + const int id_handle = hl_hash_utf8 ("handle"); + const int id_name = hl_hash_utf8 ("name"); + const int id_apiVersion = hl_hash_utf8 ("apiVersion"); + const int id_driverVersion = hl_hash_utf8 ("driverVersion"); + const int id_vendorID = hl_hash_utf8 ("vendorID"); + const int id_deviceID = hl_hash_utf8 ("deviceID"); + const int id_deviceType = hl_hash_utf8 ("deviceType"); + const int id_framebufferColorSampleCounts = hl_hash_utf8 ("framebufferColorSampleCounts"); + const int id_framebufferDepthSampleCounts = hl_hash_utf8 ("framebufferDepthSampleCounts"); + const int id_framebufferNoAttachmentsSampleCounts = hl_hash_utf8 ("framebufferNoAttachmentsSampleCounts"); + const int id_framebufferStencilSampleCounts = hl_hash_utf8 ("framebufferStencilSampleCounts"); + const int id_maxPushConstantsSize = hl_hash_utf8 ("maxPushConstantsSize"); + const int id_minStorageBufferOffsetAlignment = hl_hash_utf8 ("minStorageBufferOffsetAlignment"); + const int id_minUniformBufferOffsetAlignment = hl_hash_utf8 ("minUniformBufferOffsetAlignment"); + const int id_nonCoherentAtomSize = hl_hash_utf8 ("nonCoherentAtomSize"); + const int id_queueFamilies = hl_hash_utf8 ("queueFamilies"); + + const int id_index = hl_hash_utf8 ("index"); + const int id_flags = hl_hash_utf8 ("flags"); + const int id_queueCount = hl_hash_utf8 ("queueCount"); + const int id_timestampValidBits = hl_hash_utf8 ("timestampValidBits"); + const int id_supportsGraphics = hl_hash_utf8 ("supportsGraphics"); + const int id_supportsCompute = hl_hash_utf8 ("supportsCompute"); + const int id_supportsTransfer = hl_hash_utf8 ("supportsTransfer"); + const int id_supportsPresent = hl_hash_utf8 ("supportsPresent"); + + for (uint32_t i = 0; i < deviceCount; ++i) { + + VkPhysicalDeviceProperties properties; + memset (&properties, 0, sizeof (properties)); + vkGetPhysicalDeviceProperties (physicalDevices[i], &properties); + + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, 0); + std::vector queueFamilies (queueFamilyCount); + if (queueFamilyCount > 0) { + + vkGetPhysicalDeviceQueueFamilyProperties (physicalDevices[i], &queueFamilyCount, queueFamilies.data ()); + + } + + hl_varray* queueFamilyArray = (hl_varray*)hl_alloc_array (&hlt_dynobj, queueFamilyCount); + vdynamic** queueFamilyData = hl_aptr (queueFamilyArray, vdynamic*); + + for (uint32_t q = 0; q < queueFamilyCount; ++q) { + + VkBool32 supportsPresent = VK_FALSE; + if (surface && vkGetPhysicalDeviceSurfaceSupportKHR) { + + vkGetPhysicalDeviceSurfaceSupportKHR (physicalDevices[i], q, surface, &supportsPresent); + + } + + vdynamic* queueFamilyObject = (vdynamic*)hl_alloc_dynobj (); + *queueFamilyData++ = queueFamilyObject; + hl_dyn_seti (queueFamilyObject, id_index, &hlt_i32, q); + hl_dyn_seti (queueFamilyObject, id_flags, &hlt_i32, queueFamilies[q].queueFlags); + hl_dyn_seti (queueFamilyObject, id_queueCount, &hlt_i32, queueFamilies[q].queueCount); + hl_dyn_seti (queueFamilyObject, id_timestampValidBits, &hlt_i32, queueFamilies[q].timestampValidBits); + hl_dyn_seti (queueFamilyObject, id_supportsGraphics, &hlt_bool, (queueFamilies[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0); + hl_dyn_seti (queueFamilyObject, id_supportsCompute, &hlt_bool, (queueFamilies[q].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0); + hl_dyn_seti (queueFamilyObject, id_supportsTransfer, &hlt_bool, (queueFamilies[q].queueFlags & VK_QUEUE_TRANSFER_BIT) != 0); + hl_dyn_seti (queueFamilyObject, id_supportsPresent, &hlt_bool, supportsPresent != VK_FALSE); + + } + + vdynamic* deviceObject = (vdynamic*)hl_alloc_dynobj (); + *deviceData++ = deviceObject; + hl_dyn_setp (deviceObject, id_handle, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)physicalDevices[i])); + hl_dyn_setp (deviceObject, id_name, &hlt_bytes, hl_copy_bytes ((const vbyte*)properties.deviceName, (int)std::strlen (properties.deviceName) + 1)); + hl_dyn_seti (deviceObject, id_apiVersion, &hlt_i32, properties.apiVersion); + hl_dyn_seti (deviceObject, id_driverVersion, &hlt_i32, properties.driverVersion); + hl_dyn_seti (deviceObject, id_vendorID, &hlt_i32, properties.vendorID); + hl_dyn_seti (deviceObject, id_deviceID, &hlt_i32, properties.deviceID); + hl_dyn_seti (deviceObject, id_deviceType, &hlt_i32, properties.deviceType); + hl_dyn_seti (deviceObject, id_framebufferColorSampleCounts, &hlt_i32, properties.limits.framebufferColorSampleCounts); + hl_dyn_seti (deviceObject, id_framebufferDepthSampleCounts, &hlt_i32, properties.limits.framebufferDepthSampleCounts); + hl_dyn_seti (deviceObject, id_framebufferNoAttachmentsSampleCounts, &hlt_i32, properties.limits.framebufferNoAttachmentsSampleCounts); + hl_dyn_seti (deviceObject, id_framebufferStencilSampleCounts, &hlt_i32, properties.limits.framebufferStencilSampleCounts); + hl_dyn_seti (deviceObject, id_maxPushConstantsSize, &hlt_i32, properties.limits.maxPushConstantsSize); + hl_dyn_setp (deviceObject, id_minStorageBufferOffsetAlignment, &hlt_dynobj, + HLCreateVulkanHandleValue ((uint64_t)properties.limits.minStorageBufferOffsetAlignment)); + hl_dyn_setp (deviceObject, id_minUniformBufferOffsetAlignment, &hlt_dynobj, + HLCreateVulkanHandleValue ((uint64_t)properties.limits.minUniformBufferOffsetAlignment)); + hl_dyn_setp (deviceObject, id_nonCoherentAtomSize, &hlt_dynobj, + HLCreateVulkanHandleValue ((uint64_t)properties.limits.nonCoherentAtomSize)); + hl_dyn_setp (deviceObject, id_queueFamilies, &hlt_array, queueFamilyArray); + + } + + lastVKError.clear (); + return devices; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return (hl_varray*)hl_alloc_array (&hlt_dynobj, 0); +#endif + + } + + + value lime_vk_create_device (value window, int instanceHigh, int instanceLow, int physicalDeviceHigh, int physicalDeviceLow, int queueFamilyIndex, + value extensions) { + +#ifdef LIME_VULKAN + LogVulkanNativeBootstrap ("lime_vk_create_device: begin"); + if (val_is_null (window)) { + + lastVKError = "Missing Lime window for Vulkan device creation"; + LogVulkanNativeBootstrap ("lime_vk_create_device: null window"); + return alloc_null (); + + } + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); + LogVulkanNativeBootstrap ("lime_vk_create_device: decoded handles"); + std::vector deviceExtensions = GetVulkanDeviceExtensions (extensions); + LogVulkanNativeBootstrap ("lime_vk_create_device: decoded extensions"); + VkDevice device = VK_NULL_HANDLE; + VkQueue queue = VK_NULL_HANDLE; + + if (!CreateManagedVulkanDevice (targetWindow, instance, physicalDevice, queueFamilyIndex, deviceExtensions, &device, &queue)) { + + LogVulkanNativeBootstrap ("lime_vk_create_device: CreateManagedVulkanDevice failed"); + return alloc_null (); + + } + + LogVulkanNativeBootstrap ("lime_vk_create_device: create result object"); + value result = alloc_empty_object (); + alloc_field (result, val_id ("handle"), CreateVulkanHandleValue ((uint64_t)(uintptr_t)device)); + alloc_field (result, val_id ("queue"), CreateVulkanHandleValue ((uint64_t)(uintptr_t)queue)); + alloc_field (result, val_id ("queueFamilyIndex"), alloc_int (queueFamilyIndex)); + LogVulkanNativeBootstrap ("lime_vk_create_device: success"); + return result; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_device) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int physicalDeviceHigh, + int physicalDeviceLow, int queueFamilyIndex, hl_varray* extensions) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); + std::vector deviceExtensions = GetHLVulkanDeviceExtensions (extensions); + VkDevice device = VK_NULL_HANDLE; + VkQueue queue = VK_NULL_HANDLE; + + if (!CreateManagedVulkanDevice (targetWindow, instance, physicalDevice, queueFamilyIndex, deviceExtensions, &device, &queue)) { + + return 0; + + } + + const int id_handle = hl_hash_utf8 ("handle"); + const int id_queue = hl_hash_utf8 ("queue"); + const int id_queueFamilyIndex = hl_hash_utf8 ("queueFamilyIndex"); + vdynamic* result = (vdynamic*)hl_alloc_dynobj (); + hl_dyn_setp (result, id_handle, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)device)); + hl_dyn_setp (result, id_queue, &hlt_dynobj, HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)queue)); + hl_dyn_seti (result, id_queueFamilyIndex, &hlt_i32, queueFamilyIndex); + return result; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_device (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + if (deviceHigh == 0 && deviceLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) return; + + PFN_vkDestroyDevice vkDestroyDevice = (PFN_vkDestroyDevice)vkGetDeviceProcAddr (device, "vkDestroyDevice"); + if (vkDestroyDevice) { + + ClearManagedVulkanDeviceProcCache (device); + vkDestroyDevice (device, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_device) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + if (deviceHigh == 0 && deviceLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr) return; + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) return; + + PFN_vkDestroyDevice vkDestroyDevice = (PFN_vkDestroyDevice)vkGetDeviceProcAddr (device, "vkDestroyDevice"); + if (vkDestroyDevice) { + + ClearManagedVulkanDeviceProcCache (device); + vkDestroyDevice (device, 0); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_device_wait_idle (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr || !instance || !device) { + + lastVKError = "Missing Vulkan window, instance, or device"; + return false; + + } + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) { + + lastVKError = "Missing Vulkan device proc address function"; + return false; + + } + + PFN_vkDeviceWaitIdle vkDeviceWaitIdle = (PFN_vkDeviceWaitIdle)vkGetDeviceProcAddr (device, "vkDeviceWaitIdle"); + if (!vkDeviceWaitIdle) { + + lastVKError = "Missing Vulkan device wait idle function"; + return false; + + } + + VkResult result = vkDeviceWaitIdle (device); + if (result != VK_SUCCESS) { + + lastVKError = "vkDeviceWaitIdle failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_device_wait_idle) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr || !instance || !device) { + + lastVKError = "Missing Vulkan window, instance, or device"; + return false; + + } + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) { + + lastVKError = "Missing Vulkan device proc address function"; + return false; + + } + + PFN_vkDeviceWaitIdle vkDeviceWaitIdle = (PFN_vkDeviceWaitIdle)vkGetDeviceProcAddr (device, "vkDeviceWaitIdle"); + if (!vkDeviceWaitIdle) { + + lastVKError = "Missing Vulkan device wait idle function"; + return false; + + } + + VkResult result = vkDeviceWaitIdle (device); + if (result != VK_SUCCESS) { + + lastVKError = "vkDeviceWaitIdle failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_queue_wait_idle (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, int queueLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr || !instance || !device || !queue) { + + lastVKError = "Missing Vulkan window, instance, device, or queue"; + return false; + + } + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) { + + lastVKError = "Missing Vulkan device proc address function"; + return false; + + } + + PFN_vkQueueWaitIdle vkQueueWaitIdle = (PFN_vkQueueWaitIdle)vkGetDeviceProcAddr (device, "vkQueueWaitIdle"); + if (!vkQueueWaitIdle) { + + lastVKError = "Missing Vulkan queue wait idle function"; + return false; + + } + + VkResult result = vkQueueWaitIdle (queue); + if (result != VK_SUCCESS) { + + lastVKError = "vkQueueWaitIdle failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_queue_wait_idle) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, + int queueLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = targetWindow ? (PFN_vkGetInstanceProcAddr)targetWindow->GetVulkanInstanceProcAddr () : 0; + if (!vkGetInstanceProcAddr || !instance || !device || !queue) { + + lastVKError = "Missing Vulkan window, instance, device, or queue"; + return false; + + } + + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr (instance, "vkGetDeviceProcAddr"); + if (!vkGetDeviceProcAddr) { + + lastVKError = "Missing Vulkan device proc address function"; + return false; + + } + + PFN_vkQueueWaitIdle vkQueueWaitIdle = (PFN_vkQueueWaitIdle)vkGetDeviceProcAddr (device, "vkQueueWaitIdle"); + if (!vkQueueWaitIdle) { + + lastVKError = "Missing Vulkan queue wait idle function"; + return false; + + } + + VkResult result = vkQueueWaitIdle (queue); + if (result != VK_SUCCESS) { + + lastVKError = "vkQueueWaitIdle failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_create_command_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueFamilyIndex, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateCommandPool vkCreateCommandPool = (PFN_vkCreateCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateCommandPool"); + if (!vkCreateCommandPool) return alloc_null (); + + VkCommandPoolCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + createInfo.flags = flags; + createInfo.queueFamilyIndex = queueFamilyIndex; + + VkCommandPool commandPool = VK_NULL_HANDLE; + VkResult result = vkCreateCommandPool (device, &createInfo, 0, &commandPool); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateCommandPool failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)commandPool); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_command_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int queueFamilyIndex, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateCommandPool vkCreateCommandPool = (PFN_vkCreateCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateCommandPool"); + if (!vkCreateCommandPool) return 0; + + VkCommandPoolCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + createInfo.flags = flags; + createInfo.queueFamilyIndex = queueFamilyIndex; + + VkCommandPool commandPool = VK_NULL_HANDLE; + VkResult result = vkCreateCommandPool (device, &createInfo, 0, &commandPool); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateCommandPool failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)commandPool); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_command_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, + int commandPoolLow) { + +#ifdef LIME_VULKAN + if (commandPoolHigh == 0 && commandPoolLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkDestroyCommandPool vkDestroyCommandPool = (PFN_vkDestroyCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyCommandPool"); + if (vkDestroyCommandPool) vkDestroyCommandPool (device, commandPool, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_command_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandPoolHigh, int commandPoolLow) { + +#ifdef LIME_VULKAN + if (commandPoolHigh == 0 && commandPoolLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkDestroyCommandPool vkDestroyCommandPool = (PFN_vkDestroyCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyCommandPool"); + if (vkDestroyCommandPool) vkDestroyCommandPool (device, commandPool, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_reset_command_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, + int commandPoolLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkResetCommandPool vkResetCommandPool = (PFN_vkResetCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkResetCommandPool"); + if (!vkResetCommandPool) return false; + + VkResult result = vkResetCommandPool (device, commandPool, flags); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetCommandPool failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_reset_command_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandPoolHigh, int commandPoolLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkResetCommandPool vkResetCommandPool = (PFN_vkResetCommandPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkResetCommandPool"); + if (!vkResetCommandPool) return false; + + VkResult result = vkResetCommandPool (device, commandPool, flags); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetCommandPool failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_allocate_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, + int commandPoolLow, int level) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers = (PFN_vkAllocateCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkAllocateCommandBuffers"); + if (!vkAllocateCommandBuffers) return alloc_null (); + + VkCommandBufferAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocateInfo.commandPool = commandPool; + allocateInfo.level = (VkCommandBufferLevel)level; + allocateInfo.commandBufferCount = 1; + + VkCommandBuffer commandBuffer = VK_NULL_HANDLE; + VkResult result = vkAllocateCommandBuffers (device, &allocateInfo, &commandBuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkAllocateCommandBuffers failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)commandBuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_allocate_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandPoolHigh, int commandPoolLow, int level) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers = (PFN_vkAllocateCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkAllocateCommandBuffers"); + if (!vkAllocateCommandBuffers) return 0; + + VkCommandBufferAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocateInfo.commandPool = commandPool; + allocateInfo.level = (VkCommandBufferLevel)level; + allocateInfo.commandBufferCount = 1; + + VkCommandBuffer commandBuffer = VK_NULL_HANDLE; + VkResult result = vkAllocateCommandBuffers (device, &allocateInfo, &commandBuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkAllocateCommandBuffers failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)commandBuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_free_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandPoolHigh, + int commandPoolLow, int commandBufferHigh, int commandBufferLow) { + +#ifdef LIME_VULKAN + if (commandBufferHigh == 0 && commandBufferLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkFreeCommandBuffers vkFreeCommandBuffers = (PFN_vkFreeCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkFreeCommandBuffers"); + if (vkFreeCommandBuffers) vkFreeCommandBuffers (device, commandPool, 1, &commandBuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_free_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandPoolHigh, int commandPoolLow, int commandBufferHigh, int commandBufferLow) { + +#ifdef LIME_VULKAN + if (commandBufferHigh == 0 && commandBufferLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandPool commandPool = (VkCommandPool)(uintptr_t)CombineVulkanHandle (commandPoolHigh, commandPoolLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkFreeCommandBuffers vkFreeCommandBuffers = (PFN_vkFreeCommandBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkFreeCommandBuffers"); + if (vkFreeCommandBuffers) vkFreeCommandBuffers (device, commandPool, 1, &commandBuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_begin_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkBeginCommandBuffer vkBeginCommandBuffer = (PFN_vkBeginCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkBeginCommandBuffer"); + if (!vkBeginCommandBuffer) return false; + + VkCommandBufferBeginInfo beginInfo; + memset (&beginInfo, 0, sizeof (beginInfo)); + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = flags; + + VkResult result = vkBeginCommandBuffer (commandBuffer, &beginInfo); + if (result != VK_SUCCESS) { + + lastVKError = "vkBeginCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_begin_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkBeginCommandBuffer vkBeginCommandBuffer = (PFN_vkBeginCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkBeginCommandBuffer"); + if (!vkBeginCommandBuffer) return false; + + VkCommandBufferBeginInfo beginInfo; + memset (&beginInfo, 0, sizeof (beginInfo)); + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = flags; + + VkResult result = vkBeginCommandBuffer (commandBuffer, &beginInfo); + if (result != VK_SUCCESS) { + + lastVKError = "vkBeginCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_end_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkEndCommandBuffer vkEndCommandBuffer = (PFN_vkEndCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkEndCommandBuffer"); + if (!vkEndCommandBuffer) return false; + + VkResult result = vkEndCommandBuffer (commandBuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkEndCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_end_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkEndCommandBuffer vkEndCommandBuffer = (PFN_vkEndCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkEndCommandBuffer"); + if (!vkEndCommandBuffer) return false; + + VkResult result = vkEndCommandBuffer (commandBuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkEndCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_reset_command_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkResetCommandBuffer vkResetCommandBuffer = (PFN_vkResetCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkResetCommandBuffer"); + if (!vkResetCommandBuffer) return false; + + VkResult result = vkResetCommandBuffer (commandBuffer, flags); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_reset_command_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + PFN_vkResetCommandBuffer vkResetCommandBuffer = (PFN_vkResetCommandBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkResetCommandBuffer"); + if (!vkResetCommandBuffer) return false; + + VkResult result = vkResetCommandBuffer (commandBuffer, flags); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetCommandBuffer failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_create_semaphore (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateSemaphore vkCreateSemaphore = (PFN_vkCreateSemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateSemaphore"); + if (!vkCreateSemaphore) return alloc_null (); + + VkSemaphoreCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + VkSemaphore semaphore = VK_NULL_HANDLE; + VkResult result = vkCreateSemaphore (device, &createInfo, 0, &semaphore); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateSemaphore failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)semaphore); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_semaphore) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateSemaphore vkCreateSemaphore = (PFN_vkCreateSemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateSemaphore"); + if (!vkCreateSemaphore) return 0; + + VkSemaphoreCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + VkSemaphore semaphore = VK_NULL_HANDLE; + VkResult result = vkCreateSemaphore (device, &createInfo, 0, &semaphore); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateSemaphore failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)semaphore); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_semaphore (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int semaphoreHigh, + int semaphoreLow) { + +#ifdef LIME_VULKAN + if (semaphoreHigh == 0 && semaphoreLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSemaphore semaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (semaphoreHigh, semaphoreLow); + PFN_vkDestroySemaphore vkDestroySemaphore = (PFN_vkDestroySemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroySemaphore"); + if (vkDestroySemaphore) vkDestroySemaphore (device, semaphore, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_semaphore) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int semaphoreHigh, int semaphoreLow) { + +#ifdef LIME_VULKAN + if (semaphoreHigh == 0 && semaphoreLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSemaphore semaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (semaphoreHigh, semaphoreLow); + PFN_vkDestroySemaphore vkDestroySemaphore = (PFN_vkDestroySemaphore)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroySemaphore"); + if (vkDestroySemaphore) vkDestroySemaphore (device, semaphore, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_create_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateFence vkCreateFence = (PFN_vkCreateFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateFence"); + if (!vkCreateFence) return alloc_null (); + + VkFenceCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + createInfo.flags = flags; + + VkFence fence = VK_NULL_HANDLE; + VkResult result = vkCreateFence (device, &createInfo, 0, &fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateFence failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)fence); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateFence vkCreateFence = (PFN_vkCreateFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateFence"); + if (!vkCreateFence) return 0; + + VkFenceCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + createInfo.flags = flags; + + VkFence fence = VK_NULL_HANDLE; + VkResult result = vkCreateFence (device, &createInfo, 0, &fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateFence failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)fence); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, int fenceLow) { + +#ifdef LIME_VULKAN + if (fenceHigh == 0 && fenceLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkDestroyFence vkDestroyFence = (PFN_vkDestroyFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyFence"); + if (vkDestroyFence) vkDestroyFence (device, fence, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, + int fenceLow) { + +#ifdef LIME_VULKAN + if (fenceHigh == 0 && fenceLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkDestroyFence vkDestroyFence = (PFN_vkDestroyFence)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyFence"); + if (vkDestroyFence) vkDestroyFence (device, fence, 0); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_wait_for_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, int fenceLow, + int timeoutHigh, int timeoutLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + uint64_t timeout = CombineVulkanHandle (timeoutHigh, timeoutLow); + PFN_vkWaitForFences vkWaitForFences = (PFN_vkWaitForFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkWaitForFences"); + if (!vkWaitForFences) return false; + + VkResult result = vkWaitForFences (device, 1, &fence, VK_TRUE, timeout); + if (result != VK_SUCCESS) { + + lastVKError = "vkWaitForFences failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_wait_for_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, + int fenceLow, int timeoutHigh, int timeoutLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + uint64_t timeout = CombineVulkanHandle (timeoutHigh, timeoutLow); + PFN_vkWaitForFences vkWaitForFences = (PFN_vkWaitForFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkWaitForFences"); + if (!vkWaitForFences) return false; + + VkResult result = vkWaitForFences (device, 1, &fence, VK_TRUE, timeout); + if (result != VK_SUCCESS) { + + lastVKError = "vkWaitForFences failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_reset_fence (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, int fenceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkResetFences vkResetFences = (PFN_vkResetFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkResetFences"); + if (!vkResetFences) return false; + + VkResult result = vkResetFences (device, 1, &fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetFences failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_reset_fence) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int fenceHigh, + int fenceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkResetFences vkResetFences = (PFN_vkResetFences)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkResetFences"); + if (!vkResetFences) return false; + + VkResult result = vkResetFences (device, 1, &fence); + if (result != VK_SUCCESS) { + + lastVKError = "vkResetFences failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_queue_submit (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, int queueLow, + int commandBufferHigh, int commandBufferLow, int fenceHigh, int fenceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkQueueSubmit vkQueueSubmit = (PFN_vkQueueSubmit)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkQueueSubmit"); + if (!vkQueueSubmit) return false; + + VkSubmitInfo submitInfo; + memset (&submitInfo, 0, sizeof (submitInfo)); + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + + VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); + if (result != VK_SUCCESS) { + + char error[64]; + ::snprintf (error, sizeof (error), "vkQueueSubmit failed: %d", (int)result); + lastVKError = error; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_queue_submit) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, + int queueLow, int commandBufferHigh, int commandBufferLow, int fenceHigh, int fenceLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + PFN_vkQueueSubmit vkQueueSubmit = (PFN_vkQueueSubmit)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkQueueSubmit"); + if (!vkQueueSubmit) return false; + + VkSubmitInfo submitInfo; + memset (&submitInfo, 0, sizeof (submitInfo)); + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + + VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); + if (result != VK_SUCCESS) { + + char error[64]; + ::snprintf (error, sizeof (error), "vkQueueSubmit failed: %d", (int)result); + lastVKError = error; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_allocate_memory (value window, int instanceHigh, int instanceLow, int physicalDeviceHigh, int physicalDeviceLow, int deviceHigh, + int deviceLow, int sizeHigh, int sizeLow, int memoryTypeBits, int properties) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + uint64_t size = CombineVulkanHandle (sizeHigh, sizeLow); + uint32_t memoryTypeIndex = 0; + if (!FindManagedVulkanMemoryType (targetWindow, instance, physicalDevice, (uint32_t)memoryTypeBits, (VkMemoryPropertyFlags)properties, + &memoryTypeIndex)) { + + return alloc_null (); + + } + + PFN_vkAllocateMemory vkAllocateMemory = (PFN_vkAllocateMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkAllocateMemory"); + if (!vkAllocateMemory) return alloc_null (); + + VkMemoryAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocateInfo.allocationSize = (VkDeviceSize)size; + allocateInfo.memoryTypeIndex = memoryTypeIndex; + + VkDeviceMemory memory = VK_NULL_HANDLE; + VkResult result = vkAllocateMemory (device, &allocateInfo, 0, &memory); + if (result != VK_SUCCESS) { + + lastVKError = "vkAllocateMemory failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanMemoryValue (memory, memoryTypeIndex); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_allocate_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int physicalDeviceHigh, + int physicalDeviceLow, int deviceHigh, int deviceLow, int sizeHigh, int sizeLow, int memoryTypeBits, int properties) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + uint64_t size = CombineVulkanHandle (sizeHigh, sizeLow); + uint32_t memoryTypeIndex = 0; + if (!FindManagedVulkanMemoryType (targetWindow, instance, physicalDevice, (uint32_t)memoryTypeBits, (VkMemoryPropertyFlags)properties, + &memoryTypeIndex)) { + + return 0; + + } + + PFN_vkAllocateMemory vkAllocateMemory = (PFN_vkAllocateMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkAllocateMemory"); + if (!vkAllocateMemory) return 0; + + VkMemoryAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocateInfo.allocationSize = (VkDeviceSize)size; + allocateInfo.memoryTypeIndex = memoryTypeIndex; + + VkDeviceMemory memory = VK_NULL_HANDLE; + VkResult result = vkAllocateMemory (device, &allocateInfo, 0, &memory); + if (result != VK_SUCCESS) { + + lastVKError = "vkAllocateMemory failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanMemoryValue (memory, memoryTypeIndex); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_free_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, int memoryLow) { + +#ifdef LIME_VULKAN + if (memoryHigh == 0 && memoryLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkFreeMemory vkFreeMemory = (PFN_vkFreeMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkFreeMemory"); + if (vkFreeMemory) { + + uint64_t mapKey = GetManagedVulkanMappedMemoryKey (memory); + std::unordered_map::iterator mapped = mappedVulkanMemory.find (mapKey); + if (mapped != mappedVulkanMemory.end ()) { + + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (vkUnmapMemory) vkUnmapMemory (device, memory); + mappedVulkanMemory.erase (mapped); + + } + + vkFreeMemory (device, memory, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_free_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int memoryHigh, int memoryLow) { + +#ifdef LIME_VULKAN + if (memoryHigh == 0 && memoryLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkFreeMemory vkFreeMemory = (PFN_vkFreeMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkFreeMemory"); + if (vkFreeMemory) { + + uint64_t mapKey = GetManagedVulkanMappedMemoryKey (memory); + std::unordered_map::iterator mapped = mappedVulkanMemory.find (mapKey); + if (mapped != mappedVulkanMemory.end ()) { + + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (vkUnmapMemory) vkUnmapMemory (device, memory); + mappedVulkanMemory.erase (mapped); + + } + + vkFreeMemory (device, memory, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_upload_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, int memoryLow, + int offsetHigh, int offsetLow, value bytes, int byteOffset, int byteLength) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t offset = CombineVulkanHandle (offsetHigh, offsetLow); + Bytes data (bytes); + if (!memory || !data.b || byteOffset < 0 || byteLength < 0 || byteOffset + byteLength > data.length) { + + lastVKError = "Invalid Vulkan memory upload range"; + return false; + + } + + PFN_vkMapMemory vkMapMemory = (PFN_vkMapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkMapMemory"); + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (!vkMapMemory || !vkUnmapMemory) return false; + + void* mappedData = 0; + VkResult result = vkMapMemory (device, memory, (VkDeviceSize)offset, (VkDeviceSize)byteLength, 0, &mappedData); + if (result != VK_SUCCESS || !mappedData) { + + lastVKError = "vkMapMemory failed"; + return false; + + } + + memcpy (mappedData, data.b + byteOffset, byteLength); + vkUnmapMemory (device, memory); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_upload_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int memoryHigh, int memoryLow, int offsetHigh, int offsetLow, Bytes* bytes, int byteOffset, int byteLength) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t offset = CombineVulkanHandle (offsetHigh, offsetLow); + if (!memory || !bytes || !bytes->b || byteOffset < 0 || byteLength < 0 || byteOffset + byteLength > bytes->length) { + + lastVKError = "Invalid Vulkan memory upload range"; + return false; + + } + + PFN_vkMapMemory vkMapMemory = (PFN_vkMapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkMapMemory"); + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (!vkMapMemory || !vkUnmapMemory) return false; + + void* mappedData = 0; + VkResult result = vkMapMemory (device, memory, (VkDeviceSize)offset, (VkDeviceSize)byteLength, 0, &mappedData); + if (result != VK_SUCCESS || !mappedData) { + + lastVKError = "vkMapMemory failed"; + return false; + + } + + memcpy (mappedData, bytes->b + byteOffset, byteLength); + vkUnmapMemory (device, memory); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_download_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, int memoryLow, + int offsetHigh, int offsetLow, value bytes, int byteOffset, int byteLength) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t offset = CombineVulkanHandle (offsetHigh, offsetLow); + Bytes data (bytes); + if (!memory || !data.b || byteOffset < 0 || byteLength < 0 || byteOffset + byteLength > data.length) { + + lastVKError = "Invalid Vulkan memory download range"; + return false; + + } + + PFN_vkMapMemory vkMapMemory = (PFN_vkMapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkMapMemory"); + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (!vkMapMemory || !vkUnmapMemory) return false; + + void* mappedData = 0; + VkResult result = vkMapMemory (device, memory, (VkDeviceSize)offset, (VkDeviceSize)byteLength, 0, &mappedData); + if (result != VK_SUCCESS || !mappedData) { + + lastVKError = "vkMapMemory failed"; + return false; + + } + + memcpy (data.b + byteOffset, mappedData, byteLength); + vkUnmapMemory (device, memory); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_download_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int memoryHigh, int memoryLow, int offsetHigh, int offsetLow, Bytes* bytes, int byteOffset, int byteLength) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t offset = CombineVulkanHandle (offsetHigh, offsetLow); + if (!memory || !bytes || !bytes->b || byteOffset < 0 || byteLength < 0 || byteOffset + byteLength > bytes->length) { + + lastVKError = "Invalid Vulkan memory download range"; + return false; + + } + + PFN_vkMapMemory vkMapMemory = (PFN_vkMapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkMapMemory"); + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (!vkMapMemory || !vkUnmapMemory) return false; + + void* mappedData = 0; + VkResult result = vkMapMemory (device, memory, (VkDeviceSize)offset, (VkDeviceSize)byteLength, 0, &mappedData); + if (result != VK_SUCCESS || !mappedData) { + + lastVKError = "vkMapMemory failed"; + return false; + + } + + memcpy (bytes->b + byteOffset, mappedData, byteLength); + vkUnmapMemory (device, memory); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_map_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, int memoryLow, + int offsetHigh, int offsetLow, int sizeHigh, int sizeLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + VkDeviceSize offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + VkDeviceSize size = NormalizeVulkanRangeSize (CombineVulkanHandle (sizeHigh, sizeLow)); + if (!memory) return false; + + uint64_t mapKey = GetManagedVulkanMappedMemoryKey (memory); + if (mappedVulkanMemory.find (mapKey) != mappedVulkanMemory.end ()) { + + lastVKError.clear (); + return true; + + } + + PFN_vkMapMemory vkMapMemory = (PFN_vkMapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkMapMemory"); + if (!vkMapMemory) return false; + + void* mappedData = 0; + VkResult result = vkMapMemory (device, memory, offset, size, (VkMemoryMapFlags)flags, &mappedData); + if (result != VK_SUCCESS || !mappedData) { + + lastVKError = "vkMapMemory failed"; + return false; + + } + + ManagedVulkanMappedMemory mapped; + mapped.device = device; + mapped.memory = memory; + mapped.offset = offset; + mapped.size = size; + mapped.data = mappedData; + mappedVulkanMemory[mapKey] = mapped; + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_map_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int memoryHigh, int memoryLow, int offsetHigh, int offsetLow, int sizeHigh, int sizeLow, int flags) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + VkDeviceSize offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + VkDeviceSize size = NormalizeVulkanRangeSize (CombineVulkanHandle (sizeHigh, sizeLow)); + if (!memory) return false; + + uint64_t mapKey = GetManagedVulkanMappedMemoryKey (memory); + if (mappedVulkanMemory.find (mapKey) != mappedVulkanMemory.end ()) { + + lastVKError.clear (); + return true; + + } + + PFN_vkMapMemory vkMapMemory = (PFN_vkMapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkMapMemory"); + if (!vkMapMemory) return false; + + void* mappedData = 0; + VkResult result = vkMapMemory (device, memory, offset, size, (VkMemoryMapFlags)flags, &mappedData); + if (result != VK_SUCCESS || !mappedData) { + + lastVKError = "vkMapMemory failed"; + return false; + + } + + ManagedVulkanMappedMemory mapped; + mapped.device = device; + mapped.memory = memory; + mapped.offset = offset; + mapped.size = size; + mapped.data = mappedData; + mappedVulkanMemory[mapKey] = mapped; + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + void lime_vk_unmap_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, int memoryLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t mapKey = GetManagedVulkanMappedMemoryKey (memory); + std::unordered_map::iterator mapped = mappedVulkanMemory.find (mapKey); + if (mapped == mappedVulkanMemory.end ()) return; + + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (!vkUnmapMemory) return; + + vkUnmapMemory (device, memory); + mappedVulkanMemory.erase (mapped); + lastVKError.clear (); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_unmap_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int memoryHigh, int memoryLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t mapKey = GetManagedVulkanMappedMemoryKey (memory); + std::unordered_map::iterator mapped = mappedVulkanMemory.find (mapKey); + if (mapped == mappedVulkanMemory.end ()) return; + + PFN_vkUnmapMemory vkUnmapMemory = (PFN_vkUnmapMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUnmapMemory"); + if (!vkUnmapMemory) return; + + vkUnmapMemory (device, memory); + mappedVulkanMemory.erase (mapped); + lastVKError.clear (); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + bool lime_vk_write_mapped_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, int memoryLow, + int offsetHigh, int offsetLow, value bytes, int byteOffset, int byteLength) { + +#ifdef LIME_VULKAN + Bytes data (bytes); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t offset = CombineVulkanHandle (offsetHigh, offsetLow); + if (!memory || !data.b || byteOffset < 0 || byteLength < 0 || byteOffset + byteLength > data.length) { + + lastVKError = "Invalid mapped Vulkan memory write range"; + return false; + + } + + std::unordered_map::iterator mapped = mappedVulkanMemory.find (GetManagedVulkanMappedMemoryKey (memory)); + if (mapped == mappedVulkanMemory.end ()) { + + lastVKError = "Vulkan memory is not mapped"; + return false; + + } + + if (offset < mapped->second.offset) { + + lastVKError = "Mapped Vulkan memory write offset is outside the mapped range"; + return false; + + } + + uint64_t relativeOffset = offset - mapped->second.offset; + if (mapped->second.size != VK_WHOLE_SIZE && relativeOffset + (uint64_t)byteLength > (uint64_t)mapped->second.size) { + + lastVKError = "Mapped Vulkan memory write exceeds the mapped range"; + return false; + + } + + memcpy ((unsigned char*)mapped->second.data + relativeOffset, data.b + byteOffset, byteLength); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_write_mapped_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int memoryHigh, int memoryLow, int offsetHigh, int offsetLow, Bytes* bytes, int byteOffset, int byteLength) { + +#ifdef LIME_VULKAN + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + uint64_t offset = CombineVulkanHandle (offsetHigh, offsetLow); + if (!memory || !bytes || !bytes->b || byteOffset < 0 || byteLength < 0 || byteOffset + byteLength > bytes->length) { + + lastVKError = "Invalid mapped Vulkan memory write range"; + return false; + + } + + std::unordered_map::iterator mapped = mappedVulkanMemory.find (GetManagedVulkanMappedMemoryKey (memory)); + if (mapped == mappedVulkanMemory.end ()) { + + lastVKError = "Vulkan memory is not mapped"; + return false; + + } + + if (offset < mapped->second.offset) { + + lastVKError = "Mapped Vulkan memory write offset is outside the mapped range"; + return false; + + } + + uint64_t relativeOffset = offset - mapped->second.offset; + if (mapped->second.size != VK_WHOLE_SIZE && relativeOffset + (uint64_t)byteLength > (uint64_t)mapped->second.size) { + + lastVKError = "Mapped Vulkan memory write exceeds the mapped range"; + return false; + + } + + memcpy ((unsigned char*)mapped->second.data + relativeOffset, bytes->b + byteOffset, byteLength); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_flush_mapped_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, + int memoryLow, int offsetHigh, int offsetLow, int sizeHigh, int sizeLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges = + (PFN_vkFlushMappedMemoryRanges)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkFlushMappedMemoryRanges"); + if (!vkFlushMappedMemoryRanges || !memory) return false; + + VkMappedMemoryRange range; + memset (&range, 0, sizeof (range)); + range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range.memory = memory; + range.offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + range.size = NormalizeVulkanRangeSize (CombineVulkanHandle (sizeHigh, sizeLow)); + VkResult result = vkFlushMappedMemoryRanges (device, 1, &range); + if (result != VK_SUCCESS) { + + lastVKError = "vkFlushMappedMemoryRanges failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_flush_mapped_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int memoryHigh, int memoryLow, int offsetHigh, int offsetLow, int sizeHigh, int sizeLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges = + (PFN_vkFlushMappedMemoryRanges)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkFlushMappedMemoryRanges"); + if (!vkFlushMappedMemoryRanges || !memory) return false; + + VkMappedMemoryRange range; + memset (&range, 0, sizeof (range)); + range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range.memory = memory; + range.offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + range.size = NormalizeVulkanRangeSize (CombineVulkanHandle (sizeHigh, sizeLow)); + VkResult result = vkFlushMappedMemoryRanges (device, 1, &range); + if (result != VK_SUCCESS) { + + lastVKError = "vkFlushMappedMemoryRanges failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + bool lime_vk_invalidate_mapped_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int memoryHigh, + int memoryLow, int offsetHigh, int offsetLow, int sizeHigh, int sizeLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges = + (PFN_vkInvalidateMappedMemoryRanges)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkInvalidateMappedMemoryRanges"); + if (!vkInvalidateMappedMemoryRanges || !memory) return false; + + VkMappedMemoryRange range; + memset (&range, 0, sizeof (range)); + range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range.memory = memory; + range.offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + range.size = NormalizeVulkanRangeSize (CombineVulkanHandle (sizeHigh, sizeLow)); + VkResult result = vkInvalidateMappedMemoryRanges (device, 1, &range); + if (result != VK_SUCCESS) { + + lastVKError = "vkInvalidateMappedMemoryRanges failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_invalidate_mapped_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int memoryHigh, int memoryLow, int offsetHigh, int offsetLow, int sizeHigh, int sizeLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges = + (PFN_vkInvalidateMappedMemoryRanges)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkInvalidateMappedMemoryRanges"); + if (!vkInvalidateMappedMemoryRanges || !memory) return false; + + VkMappedMemoryRange range; + memset (&range, 0, sizeof (range)); + range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range.memory = memory; + range.offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + range.size = NormalizeVulkanRangeSize (CombineVulkanHandle (sizeHigh, sizeLow)); + VkResult result = vkInvalidateMappedMemoryRanges (device, 1, &range); + if (result != VK_SUCCESS) { + + lastVKError = "vkInvalidateMappedMemoryRanges failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_create_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int sizeHigh, int sizeLow, int usage) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateBuffer vkCreateBuffer = (PFN_vkCreateBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateBuffer"); + if (!vkCreateBuffer) return alloc_null (); + + VkBufferCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + createInfo.size = (VkDeviceSize)CombineVulkanHandle (sizeHigh, sizeLow); + createInfo.usage = (VkBufferUsageFlags)usage; + createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VkBuffer buffer = VK_NULL_HANDLE; + VkResult result = vkCreateBuffer (device, &createInfo, 0, &buffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateBuffer failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)buffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int sizeHigh, int sizeLow, int usage) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateBuffer vkCreateBuffer = (PFN_vkCreateBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateBuffer"); + if (!vkCreateBuffer) return 0; + + VkBufferCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + createInfo.size = (VkDeviceSize)CombineVulkanHandle (sizeHigh, sizeLow); + createInfo.usage = (VkBufferUsageFlags)usage; + createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VkBuffer buffer = VK_NULL_HANDLE; + VkResult result = vkCreateBuffer (device, &createInfo, 0, &buffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateBuffer failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)buffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int bufferHigh, int bufferLow) { + +#ifdef LIME_VULKAN + if (bufferHigh == 0 && bufferLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + PFN_vkDestroyBuffer vkDestroyBuffer = (PFN_vkDestroyBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyBuffer"); + if (vkDestroyBuffer) { + + vkDestroyBuffer (device, buffer, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int bufferHigh, int bufferLow) { + +#ifdef LIME_VULKAN + if (bufferHigh == 0 && bufferLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + PFN_vkDestroyBuffer vkDestroyBuffer = (PFN_vkDestroyBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyBuffer"); + if (vkDestroyBuffer) { + + vkDestroyBuffer (device, buffer, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_get_buffer_memory_requirements (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int bufferHigh, + int bufferLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements = + (PFN_vkGetBufferMemoryRequirements)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkGetBufferMemoryRequirements"); + if (!vkGetBufferMemoryRequirements || !buffer) return alloc_null (); + + VkMemoryRequirements requirements; + memset (&requirements, 0, sizeof (requirements)); + vkGetBufferMemoryRequirements (device, buffer, &requirements); + lastVKError.clear (); + return CreateVulkanMemoryRequirementsValue (requirements); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_get_buffer_memory_requirements) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, + int deviceHigh, int deviceLow, int bufferHigh, int bufferLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements = + (PFN_vkGetBufferMemoryRequirements)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkGetBufferMemoryRequirements"); + if (!vkGetBufferMemoryRequirements || !buffer) return 0; + + VkMemoryRequirements requirements; + memset (&requirements, 0, sizeof (requirements)); + vkGetBufferMemoryRequirements (device, buffer, &requirements); + lastVKError.clear (); + return HLCreateVulkanMemoryRequirementsValue (requirements); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + bool lime_vk_bind_buffer_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int bufferHigh, int bufferLow, + int memoryHigh, int memoryLow, int offsetHigh, int offsetLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkBindBufferMemory vkBindBufferMemory = (PFN_vkBindBufferMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkBindBufferMemory"); + if (!vkBindBufferMemory || !buffer || !memory) return false; + + VkResult result = vkBindBufferMemory (device, buffer, memory, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow)); + if (result != VK_SUCCESS) { + + lastVKError = "vkBindBufferMemory failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_bind_buffer_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int bufferHigh, int bufferLow, int memoryHigh, int memoryLow, int offsetHigh, int offsetLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkBindBufferMemory vkBindBufferMemory = (PFN_vkBindBufferMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkBindBufferMemory"); + if (!vkBindBufferMemory || !buffer || !memory) return false; + + VkResult result = vkBindBufferMemory (device, buffer, memory, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow)); + if (result != VK_SUCCESS) { + + lastVKError = "vkBindBufferMemory failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_create_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int width, int height, int depth, + int mipLevels, int arrayLayers, int format, int imageType, int tiling, int usage, int samples) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateImage vkCreateImage = (PFN_vkCreateImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateImage"); + if (!vkCreateImage) return alloc_null (); + + VkImageCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + createInfo.imageType = (VkImageType)imageType; + createInfo.format = (VkFormat)format; + createInfo.extent.width = (uint32_t)width; + createInfo.extent.height = (uint32_t)height; + createInfo.extent.depth = (uint32_t)depth; + createInfo.mipLevels = (uint32_t)mipLevels; + createInfo.arrayLayers = (uint32_t)arrayLayers; + createInfo.samples = (VkSampleCountFlagBits)samples; + createInfo.tiling = (VkImageTiling)tiling; + createInfo.usage = (VkImageUsageFlags)usage; + createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + if ((VkImageViewType)imageType == VK_IMAGE_VIEW_TYPE_CUBE || arrayLayers == 6) { + + createInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + + } + + VkImage image = VK_NULL_HANDLE; + VkResult result = vkCreateImage (device, &createInfo, 0, &image); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateImage failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)image); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int width, int height, int depth, int mipLevels, int arrayLayers, int format, int imageType, int tiling, int usage, int samples) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateImage vkCreateImage = (PFN_vkCreateImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateImage"); + if (!vkCreateImage) return 0; + + VkImageCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + createInfo.imageType = (VkImageType)imageType; + createInfo.format = (VkFormat)format; + createInfo.extent.width = (uint32_t)width; + createInfo.extent.height = (uint32_t)height; + createInfo.extent.depth = (uint32_t)depth; + createInfo.mipLevels = (uint32_t)mipLevels; + createInfo.arrayLayers = (uint32_t)arrayLayers; + createInfo.samples = (VkSampleCountFlagBits)samples; + createInfo.tiling = (VkImageTiling)tiling; + createInfo.usage = (VkImageUsageFlags)usage; + createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + if ((VkImageViewType)imageType == VK_IMAGE_VIEW_TYPE_CUBE || arrayLayers == 6) { + + createInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + + } + + VkImage image = VK_NULL_HANDLE; + VkResult result = vkCreateImage (device, &createInfo, 0, &image); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateImage failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)image); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int imageHigh, int imageLow) { + +#ifdef LIME_VULKAN + if (imageHigh == 0 && imageLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + PFN_vkDestroyImage vkDestroyImage = (PFN_vkDestroyImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyImage"); + if (vkDestroyImage) { + + vkDestroyImage (device, image, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int imageHigh, int imageLow) { + +#ifdef LIME_VULKAN + if (imageHigh == 0 && imageLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + PFN_vkDestroyImage vkDestroyImage = (PFN_vkDestroyImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyImage"); + if (vkDestroyImage) { + + vkDestroyImage (device, image, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_get_image_memory_requirements (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int imageHigh, + int imageLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements = + (PFN_vkGetImageMemoryRequirements)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkGetImageMemoryRequirements"); + if (!vkGetImageMemoryRequirements || !image) return alloc_null (); + + VkMemoryRequirements requirements; + memset (&requirements, 0, sizeof (requirements)); + vkGetImageMemoryRequirements (device, image, &requirements); + lastVKError.clear (); + return CreateVulkanMemoryRequirementsValue (requirements); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_get_image_memory_requirements) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int imageHigh, int imageLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements = + (PFN_vkGetImageMemoryRequirements)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkGetImageMemoryRequirements"); + if (!vkGetImageMemoryRequirements || !image) return 0; + + VkMemoryRequirements requirements; + memset (&requirements, 0, sizeof (requirements)); + vkGetImageMemoryRequirements (device, image, &requirements); + lastVKError.clear (); + return HLCreateVulkanMemoryRequirementsValue (requirements); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + bool lime_vk_bind_image_memory (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int imageHigh, int imageLow, + int memoryHigh, int memoryLow, int offsetHigh, int offsetLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkBindImageMemory vkBindImageMemory = (PFN_vkBindImageMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkBindImageMemory"); + if (!vkBindImageMemory || !image || !memory) return false; + + VkResult result = vkBindImageMemory (device, image, memory, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow)); + if (result != VK_SUCCESS) { + + lastVKError = "vkBindImageMemory failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + HL_PRIM bool HL_NAME(hl_vk_bind_image_memory) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int imageHigh, int imageLow, int memoryHigh, int memoryLow, int offsetHigh, int offsetLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + VkDeviceMemory memory = (VkDeviceMemory)(uintptr_t)CombineVulkanHandle (memoryHigh, memoryLow); + PFN_vkBindImageMemory vkBindImageMemory = (PFN_vkBindImageMemory)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkBindImageMemory"); + if (!vkBindImageMemory || !image || !memory) return false; + + VkResult result = vkBindImageMemory (device, image, memory, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow)); + if (result != VK_SUCCESS) { + + lastVKError = "vkBindImageMemory failed"; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + + } + + + value lime_vk_create_swapchain (value window, int instanceHigh, int instanceLow, int physicalDeviceHigh, int physicalDeviceLow, int deviceHigh, + int deviceLow, int surfaceHigh, int surfaceLow, int queueFamilyIndex, int width, int height, int presentMode, int oldSwapchainHigh, + int oldSwapchainLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + VkSwapchainKHR oldSwapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (oldSwapchainHigh, oldSwapchainLow); + ManagedVulkanSwapchain swapchain; + + if (!CreateManagedVulkanSwapchain (targetWindow, instance, physicalDevice, device, surface, (uint32_t)queueFamilyIndex, width, height, + (VkPresentModeKHR)presentMode, oldSwapchain, &swapchain)) { + + return alloc_null (); + + } + + return CreateVulkanSwapchainValue (swapchain); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_swapchain) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int physicalDeviceHigh, + int physicalDeviceLow, int deviceHigh, int deviceLow, int surfaceHigh, int surfaceLow, int queueFamilyIndex, int width, int height, + int presentMode, int oldSwapchainHigh, int oldSwapchainLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkPhysicalDevice physicalDevice = (VkPhysicalDevice)(uintptr_t)CombineVulkanHandle (physicalDeviceHigh, physicalDeviceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSurfaceKHR surface = UInt64ToVulkanSurface (CombineVulkanHandle (surfaceHigh, surfaceLow)); + VkSwapchainKHR oldSwapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (oldSwapchainHigh, oldSwapchainLow); + ManagedVulkanSwapchain swapchain; + + if (!CreateManagedVulkanSwapchain (targetWindow, instance, physicalDevice, device, surface, (uint32_t)queueFamilyIndex, width, height, + (VkPresentModeKHR)presentMode, oldSwapchain, &swapchain)) { + + return 0; + + } + + return HLCreateVulkanSwapchainValue (swapchain); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } + + + void lime_vk_destroy_swapchain (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int swapchainHigh, int swapchainLow) { + +#ifdef LIME_VULKAN + if (swapchainHigh == 0 && swapchainLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroySwapchainKHR"); + if (vkDestroySwapchainKHR) { + + vkDestroySwapchainKHR (device, swapchain, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + HL_PRIM void HL_NAME(hl_vk_destroy_swapchain) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int swapchainHigh, int swapchainLow) { + +#ifdef LIME_VULKAN + if (swapchainHigh == 0 && swapchainLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroySwapchainKHR"); + if (vkDestroySwapchainKHR) { + + vkDestroySwapchainKHR (device, swapchain, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + + } + + + value lime_vk_get_swapchain_images (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int swapchainHigh, + int swapchainLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkGetSwapchainImagesKHR"); + if (!vkGetSwapchainImagesKHR || !swapchain) return alloc_null (); + + uint32_t imageCount = 0; + VkResult result = vkGetSwapchainImagesKHR (device, swapchain, &imageCount, 0); + if (result != VK_SUCCESS) { + + lastVKError = "Failed to query Vulkan swapchain image count"; + return alloc_null (); + + } + + value images = alloc_array (imageCount); + if (imageCount == 0) { + + lastVKError.clear (); + return images; + + } - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetGlyphIndex (hxs_utf8 (character, nullptr)); - #else - return -1; - #endif + std::vector swapchainImages (imageCount); + result = vkGetSwapchainImagesKHR (device, swapchain, &imageCount, swapchainImages.data ()); + if (result != VK_SUCCESS) { + + lastVKError = "vkGetSwapchainImagesKHR failed"; + return alloc_null (); + + } + + for (uint32_t i = 0; i < imageCount; ++i) { + + val_array_set_i (images, i, CreateVulkanHandleValue ((uint64_t)(uintptr_t)swapchainImages[i])); + + } + + lastVKError.clear (); + return images; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_array (0); +#endif } - HL_PRIM int HL_NAME(hl_font_get_glyph_index) (HL_CFFIPointer* fontHandle, hl_vstring* character) { + HL_PRIM hl_varray* HL_NAME(hl_vk_get_swapchain_images) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int swapchainHigh, int swapchainLow) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetGlyphIndex (character ? (char*)hl_to_utf8 ((const uchar*)character->bytes) : NULL); - #else - return -1; - #endif +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkGetSwapchainImagesKHR"); + if (!vkGetSwapchainImagesKHR || !swapchain) return 0; + + uint32_t imageCount = 0; + VkResult result = vkGetSwapchainImagesKHR (device, swapchain, &imageCount, 0); + if (result != VK_SUCCESS) { + + lastVKError = "Failed to query Vulkan swapchain image count"; + return 0; + + } + + hl_varray* images = (hl_varray*)hl_alloc_array (&hlt_dynobj, imageCount); + if (imageCount == 0) { + + lastVKError.clear (); + return images; + + } + + std::vector swapchainImages (imageCount); + result = vkGetSwapchainImagesKHR (device, swapchain, &imageCount, swapchainImages.data ()); + if (result != VK_SUCCESS) { + + lastVKError = "vkGetSwapchainImagesKHR failed"; + return 0; + + } + + vdynamic** imageData = hl_aptr (images, vdynamic*); + for (uint32_t i = 0; i < imageCount; ++i) { + + *imageData++ = HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)swapchainImages[i]); + + } + + lastVKError.clear (); + return images; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return (hl_varray*)hl_alloc_array (&hlt_dynobj, 0); +#endif } - value lime_font_get_glyph_indices (value fontHandle, HxString characters) { + value lime_vk_acquire_next_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int swapchainHigh, + int swapchainLow, int timeoutHigh, int timeoutLow, int semaphoreHigh, int semaphoreLow, int fenceHigh, int fenceLow) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return (value)font->GetGlyphIndices (true, hxs_utf8 (characters, nullptr)); - #else +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + uint64_t timeout = CombineVulkanHandle (timeoutHigh, timeoutLow); + VkSemaphore semaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (semaphoreHigh, semaphoreLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + if (!semaphore && !fence) { + + lastVKError = "Vulkan image acquisition requires a semaphore or fence"; + return CreateVulkanAcquireValue (VK_ERROR_INITIALIZATION_FAILED, -1); + + } + + PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkAcquireNextImageKHR"); + if (!vkAcquireNextImageKHR || !swapchain) return CreateVulkanAcquireValue (VK_ERROR_INITIALIZATION_FAILED, -1); + + uint32_t imageIndex = 0; + VkResult result = vkAcquireNextImageKHR (device, swapchain, timeout, semaphore, fence, &imageIndex); + if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { + + lastVKError.clear (); + return CreateVulkanAcquireValue (result, (int)imageIndex); + + } + + lastVKError = "vkAcquireNextImageKHR failed"; + return CreateVulkanAcquireValue (result, -1); +#else + lastVKError = "Lime was built without lime-vulkan support"; return alloc_null (); - #endif +#endif } - HL_PRIM hl_varray* HL_NAME(hl_font_get_glyph_indices) (HL_CFFIPointer* fontHandle, hl_vstring* characters) { + HL_PRIM vdynamic* HL_NAME(hl_vk_acquire_next_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int swapchainHigh, int swapchainLow, int timeoutHigh, int timeoutLow, int semaphoreHigh, int semaphoreLow, int fenceHigh, int fenceLow) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return (hl_varray*)font->GetGlyphIndices (false, characters ? (char*)hl_to_utf8 ((const uchar*)characters->bytes) : NULL); - #else +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + uint64_t timeout = CombineVulkanHandle (timeoutHigh, timeoutLow); + VkSemaphore semaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (semaphoreHigh, semaphoreLow); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (fenceHigh, fenceLow); + if (!semaphore && !fence) { + + lastVKError = "Vulkan image acquisition requires a semaphore or fence"; + return HLCreateVulkanAcquireValue (VK_ERROR_INITIALIZATION_FAILED, -1); + + } + + PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkAcquireNextImageKHR"); + if (!vkAcquireNextImageKHR || !swapchain) return HLCreateVulkanAcquireValue (VK_ERROR_INITIALIZATION_FAILED, -1); + + uint32_t imageIndex = 0; + VkResult result = vkAcquireNextImageKHR (device, swapchain, timeout, semaphore, fence, &imageIndex); + if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { + + lastVKError.clear (); + return HLCreateVulkanAcquireValue (result, (int)imageIndex); + + } + + lastVKError = "vkAcquireNextImageKHR failed"; + return HLCreateVulkanAcquireValue (result, -1); +#else + lastVKError = "Lime was built without lime-vulkan support"; return 0; - #endif +#endif } - value lime_font_get_glyph_metrics (value fontHandle, int index) { + int lime_vk_queue_present (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, int queueLow, + int swapchainHigh, int swapchainLow, int imageIndex, int waitSemaphoreHigh, int waitSemaphoreLow) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return (value)font->GetGlyphMetrics (true, index); - #else +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + VkSemaphore waitSemaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (waitSemaphoreHigh, waitSemaphoreLow); + PFN_vkQueuePresentKHR vkQueuePresentKHR = (PFN_vkQueuePresentKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkQueuePresentKHR"); + if (!vkQueuePresentKHR || !queue || !swapchain) return VK_ERROR_INITIALIZATION_FAILED; + + VkPresentInfoKHR presentInfo; + memset (&presentInfo, 0, sizeof (presentInfo)); + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.waitSemaphoreCount = waitSemaphore ? 1 : 0; + presentInfo.pWaitSemaphores = waitSemaphore ? &waitSemaphore : 0; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &swapchain; + uint32_t swapchainImageIndex = (uint32_t)imageIndex; + presentInfo.pImageIndices = &swapchainImageIndex; + + VkResult result = vkQueuePresentKHR (queue, &presentInfo); + if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { + + lastVKError.clear (); + + } else { + + lastVKError = "vkQueuePresentKHR failed"; + + } + + return (int)result; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return -3; +#endif + + } + + + HL_PRIM int HL_NAME(hl_vk_queue_present) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, + int queueLow, int swapchainHigh, int swapchainLow, int imageIndex, int waitSemaphoreHigh, int waitSemaphoreLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + VkSwapchainKHR swapchain = (VkSwapchainKHR)(uintptr_t)CombineVulkanHandle (swapchainHigh, swapchainLow); + VkSemaphore waitSemaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (waitSemaphoreHigh, waitSemaphoreLow); + PFN_vkQueuePresentKHR vkQueuePresentKHR = (PFN_vkQueuePresentKHR)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkQueuePresentKHR"); + if (!vkQueuePresentKHR || !queue || !swapchain) return VK_ERROR_INITIALIZATION_FAILED; + + VkPresentInfoKHR presentInfo; + memset (&presentInfo, 0, sizeof (presentInfo)); + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.waitSemaphoreCount = waitSemaphore ? 1 : 0; + presentInfo.pWaitSemaphores = waitSemaphore ? &waitSemaphore : 0; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &swapchain; + uint32_t swapchainImageIndex = (uint32_t)imageIndex; + presentInfo.pImageIndices = &swapchainImageIndex; + + VkResult result = vkQueuePresentKHR (queue, &presentInfo); + if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { + + lastVKError.clear (); + + } else { + + lastVKError = "vkQueuePresentKHR failed"; + + } + + return (int)result; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return -3; +#endif + + } + + + value lime_vk_create_image_view (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int imageHigh, int imageLow, + int format, int aspectMask, int viewType) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + if (!image || format == VK_FORMAT_UNDEFINED) { + + lastVKError = "Missing Vulkan image or image view format"; + return alloc_null (); + + } + + PFN_vkCreateImageView vkCreateImageView = (PFN_vkCreateImageView)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateImageView"); + if (!vkCreateImageView) return alloc_null (); + + VkImageViewCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.image = image; + createInfo.viewType = (VkImageViewType)viewType; + createInfo.format = (VkFormat)format; + createInfo.subresourceRange.aspectMask = (VkImageAspectFlags)aspectMask; + createInfo.subresourceRange.baseMipLevel = 0; + createInfo.subresourceRange.levelCount = 1; + createInfo.subresourceRange.baseArrayLayer = 0; + createInfo.subresourceRange.layerCount = 1; + + VkImageView imageView = VK_NULL_HANDLE; + VkResult result = vkCreateImageView (device, &createInfo, 0, &imageView); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateImageView failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)imageView); +#else + lastVKError = "Lime was built without lime-vulkan support"; return alloc_null (); - #endif +#endif } - HL_PRIM vdynamic* HL_NAME(hl_font_get_glyph_metrics) (HL_CFFIPointer* fontHandle, int index) { + HL_PRIM vdynamic* HL_NAME(hl_vk_create_image_view) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int imageHigh, int imageLow, int format, int aspectMask, int viewType) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return (vdynamic*)font->GetGlyphMetrics (false, index); - #else +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + if (!image || format == VK_FORMAT_UNDEFINED) { + + lastVKError = "Missing Vulkan image or image view format"; + return 0; + + } + + PFN_vkCreateImageView vkCreateImageView = (PFN_vkCreateImageView)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateImageView"); + if (!vkCreateImageView) return 0; + + VkImageViewCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.image = image; + createInfo.viewType = (VkImageViewType)viewType; + createInfo.format = (VkFormat)format; + createInfo.subresourceRange.aspectMask = (VkImageAspectFlags)aspectMask; + createInfo.subresourceRange.baseMipLevel = 0; + createInfo.subresourceRange.levelCount = 1; + createInfo.subresourceRange.baseArrayLayer = 0; + createInfo.subresourceRange.layerCount = 1; + + VkImageView imageView = VK_NULL_HANDLE; + VkResult result = vkCreateImageView (device, &createInfo, 0, &imageView); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateImageView failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)imageView); +#else + lastVKError = "Lime was built without lime-vulkan support"; return 0; - #endif +#endif } - int lime_font_get_height (value fontHandle) { + void lime_vk_destroy_image_view (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int imageViewHigh, + int imageViewLow) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetHeight (); - #else - return 0; - #endif +#ifdef LIME_VULKAN + if (imageViewHigh == 0 && imageViewLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImageView imageView = (VkImageView)(uintptr_t)CombineVulkanHandle (imageViewHigh, imageViewLow); + PFN_vkDestroyImageView vkDestroyImageView = (PFN_vkDestroyImageView)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyImageView"); + if (vkDestroyImageView) { + + vkDestroyImageView (device, imageView, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif } - HL_PRIM int HL_NAME(hl_font_get_height) (HL_CFFIPointer* fontHandle) { + HL_PRIM void HL_NAME(hl_vk_destroy_image_view) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int imageViewHigh, int imageViewLow) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetHeight (); - #else - return 0; - #endif +#ifdef LIME_VULKAN + if (imageViewHigh == 0 && imageViewLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImageView imageView = (VkImageView)(uintptr_t)CombineVulkanHandle (imageViewHigh, imageViewLow); + PFN_vkDestroyImageView vkDestroyImageView = (PFN_vkDestroyImageView)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyImageView"); + if (vkDestroyImageView) { + + vkDestroyImageView (device, imageView, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif } - int lime_font_get_num_glyphs (value fontHandle) { + value lime_vk_create_image_view_ex (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int imageHigh, int imageLow, + int format, int aspectMask, int viewType, int baseMipLevel, int levelCount, int baseArrayLayer, int layerCount) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetNumGlyphs (); - #else - return 0; - #endif +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + if (!image || format == VK_FORMAT_UNDEFINED) { + + lastVKError = "Missing Vulkan image or image view format"; + return alloc_null (); + + } + + PFN_vkCreateImageView vkCreateImageView = (PFN_vkCreateImageView)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateImageView"); + if (!vkCreateImageView) return alloc_null (); + + VkImageViewCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.image = image; + createInfo.viewType = (VkImageViewType)viewType; + createInfo.format = (VkFormat)format; + createInfo.subresourceRange.aspectMask = (VkImageAspectFlags)aspectMask; + createInfo.subresourceRange.baseMipLevel = (uint32_t)baseMipLevel; + createInfo.subresourceRange.levelCount = (uint32_t)levelCount; + createInfo.subresourceRange.baseArrayLayer = (uint32_t)baseArrayLayer; + createInfo.subresourceRange.layerCount = (uint32_t)layerCount; + + VkImageView imageView = VK_NULL_HANDLE; + VkResult result = vkCreateImageView (device, &createInfo, 0, &imageView); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateImageView failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)imageView); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif } - HL_PRIM int HL_NAME(hl_font_get_num_glyphs) (HL_CFFIPointer* fontHandle) { + HL_PRIM vdynamic* HL_NAME(hl_vk_create_image_view_ex) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int imageHigh, int imageLow, int format, int aspectMask, int viewType, int baseMipLevel, int levelCount, + int baseArrayLayer, int layerCount) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetNumGlyphs (); - #else +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkImage image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + if (!image || format == VK_FORMAT_UNDEFINED) { + + lastVKError = "Missing Vulkan image or image view format"; + return 0; + + } + + PFN_vkCreateImageView vkCreateImageView = (PFN_vkCreateImageView)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateImageView"); + if (!vkCreateImageView) return 0; + + VkImageViewCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.image = image; + createInfo.viewType = (VkImageViewType)viewType; + createInfo.format = (VkFormat)format; + createInfo.subresourceRange.aspectMask = (VkImageAspectFlags)aspectMask; + createInfo.subresourceRange.baseMipLevel = (uint32_t)baseMipLevel; + createInfo.subresourceRange.levelCount = (uint32_t)levelCount; + createInfo.subresourceRange.baseArrayLayer = (uint32_t)baseArrayLayer; + createInfo.subresourceRange.layerCount = (uint32_t)layerCount; + + VkImageView imageView = VK_NULL_HANDLE; + VkResult result = vkCreateImageView (device, &createInfo, 0, &imageView); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateImageView failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)imageView); +#else + lastVKError = "Lime was built without lime-vulkan support"; return 0; - #endif +#endif } - int lime_font_get_underline_position (value fontHandle) { + value lime_vk_create_render_pass (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value state) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetUnderlinePosition (); - #else +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateRenderPass vkCreateRenderPass = (PFN_vkCreateRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateRenderPass"); + if (!vkCreateRenderPass) return alloc_null (); + std::vector packed = GetVulkanIntVector (state); + if (packed.size () < 16) return alloc_null (); + + int colorFormat = packed[0]; + int depthStencilFormat = packed[1]; + int samples = packed[2]; + int colorLoadOp = packed[3]; + int colorStoreOp = packed[4]; + int colorInitialLayout = packed[5]; + int colorFinalLayout = packed[6]; + int depthInitialLayout = packed[7]; + int depthFinalLayout = packed[8]; + int depthLoadOp = packed[9]; + int depthStoreOp = packed[10]; + int resolveFormat = packed[11]; + int resolveLoadOp = packed[12]; + int resolveStoreOp = packed[13]; + int resolveInitialLayout = packed[14]; + int resolveFinalLayout = packed[15]; + + std::vector attachments; + VkAttachmentDescription colorAttachment; + memset (&colorAttachment, 0, sizeof (colorAttachment)); + colorAttachment.format = (VkFormat)colorFormat; + colorAttachment.samples = (VkSampleCountFlagBits)samples; + colorAttachment.loadOp = (VkAttachmentLoadOp)colorLoadOp; + colorAttachment.storeOp = (VkAttachmentStoreOp)colorStoreOp; + colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + colorAttachment.initialLayout = (VkImageLayout)colorInitialLayout; + colorAttachment.finalLayout = (VkImageLayout)colorFinalLayout; + attachments.push_back (colorAttachment); + + VkAttachmentReference colorReference; + memset (&colorReference, 0, sizeof (colorReference)); + colorReference.attachment = 0; + colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depthReference; + memset (&depthReference, 0, sizeof (depthReference)); + bool hasDepth = depthStencilFormat != VK_FORMAT_UNDEFINED; + bool hasResolve = resolveFormat != VK_FORMAT_UNDEFINED; + if (hasDepth) { + + VkAttachmentDescription depthAttachment; + memset (&depthAttachment, 0, sizeof (depthAttachment)); + depthAttachment.format = (VkFormat)depthStencilFormat; + depthAttachment.samples = (VkSampleCountFlagBits)samples; + depthAttachment.loadOp = (VkAttachmentLoadOp)depthLoadOp; + depthAttachment.storeOp = (VkAttachmentStoreOp)depthStoreOp; + depthAttachment.stencilLoadOp = (VkAttachmentLoadOp)depthLoadOp; + depthAttachment.stencilStoreOp = (VkAttachmentStoreOp)depthStoreOp; + depthAttachment.initialLayout = (VkImageLayout)depthInitialLayout; + depthAttachment.finalLayout = (VkImageLayout)depthFinalLayout; + attachments.push_back (depthAttachment); + depthReference.attachment = 1; + depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + } + + VkAttachmentReference resolveReference; + memset (&resolveReference, 0, sizeof (resolveReference)); + if (hasResolve) { + + VkAttachmentDescription resolveAttachment; + memset (&resolveAttachment, 0, sizeof (resolveAttachment)); + resolveAttachment.format = (VkFormat)resolveFormat; + resolveAttachment.samples = VK_SAMPLE_COUNT_1_BIT; + resolveAttachment.loadOp = (VkAttachmentLoadOp)resolveLoadOp; + resolveAttachment.storeOp = (VkAttachmentStoreOp)resolveStoreOp; + resolveAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + resolveAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + resolveAttachment.initialLayout = (VkImageLayout)resolveInitialLayout; + resolveAttachment.finalLayout = (VkImageLayout)resolveFinalLayout; + attachments.push_back (resolveAttachment); + resolveReference.attachment = (uint32_t)(attachments.size () - 1); + resolveReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + } + + VkSubpassDescription subpass; + memset (&subpass, 0, sizeof (subpass)); + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &colorReference; + subpass.pResolveAttachments = hasResolve ? &resolveReference : 0; + subpass.pDepthStencilAttachment = hasDepth ? &depthReference : 0; + + VkSubpassDependency dependency; + memset (&dependency, 0, sizeof (dependency)); + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + + VkRenderPassCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + createInfo.attachmentCount = (uint32_t)attachments.size (); + createInfo.pAttachments = attachments.data (); + createInfo.subpassCount = 1; + createInfo.pSubpasses = &subpass; + createInfo.dependencyCount = 1; + createInfo.pDependencies = &dependency; + + VkRenderPass renderPass = VK_NULL_HANDLE; + VkResult result = vkCreateRenderPass (device, &createInfo, 0, &renderPass); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateRenderPass failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)renderPass); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif + + } + + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_render_pass) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, hl_varray* state) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateRenderPass vkCreateRenderPass = (PFN_vkCreateRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateRenderPass"); + if (!vkCreateRenderPass) return 0; + std::vector packed = GetHLVulkanIntVector (state); + if (packed.size () < 16) return 0; + + int colorFormat = packed[0]; + int depthStencilFormat = packed[1]; + int samples = packed[2]; + int colorLoadOp = packed[3]; + int colorStoreOp = packed[4]; + int colorInitialLayout = packed[5]; + int colorFinalLayout = packed[6]; + int depthInitialLayout = packed[7]; + int depthFinalLayout = packed[8]; + int depthLoadOp = packed[9]; + int depthStoreOp = packed[10]; + int resolveFormat = packed[11]; + int resolveLoadOp = packed[12]; + int resolveStoreOp = packed[13]; + int resolveInitialLayout = packed[14]; + int resolveFinalLayout = packed[15]; + + std::vector attachments; + VkAttachmentDescription colorAttachment; + memset (&colorAttachment, 0, sizeof (colorAttachment)); + colorAttachment.format = (VkFormat)colorFormat; + colorAttachment.samples = (VkSampleCountFlagBits)samples; + colorAttachment.loadOp = (VkAttachmentLoadOp)colorLoadOp; + colorAttachment.storeOp = (VkAttachmentStoreOp)colorStoreOp; + colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + colorAttachment.initialLayout = (VkImageLayout)colorInitialLayout; + colorAttachment.finalLayout = (VkImageLayout)colorFinalLayout; + attachments.push_back (colorAttachment); + + VkAttachmentReference colorReference; + memset (&colorReference, 0, sizeof (colorReference)); + colorReference.attachment = 0; + colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depthReference; + memset (&depthReference, 0, sizeof (depthReference)); + bool hasDepth = depthStencilFormat != VK_FORMAT_UNDEFINED; + bool hasResolve = resolveFormat != VK_FORMAT_UNDEFINED; + if (hasDepth) { + + VkAttachmentDescription depthAttachment; + memset (&depthAttachment, 0, sizeof (depthAttachment)); + depthAttachment.format = (VkFormat)depthStencilFormat; + depthAttachment.samples = (VkSampleCountFlagBits)samples; + depthAttachment.loadOp = (VkAttachmentLoadOp)depthLoadOp; + depthAttachment.storeOp = (VkAttachmentStoreOp)depthStoreOp; + depthAttachment.stencilLoadOp = (VkAttachmentLoadOp)depthLoadOp; + depthAttachment.stencilStoreOp = (VkAttachmentStoreOp)depthStoreOp; + depthAttachment.initialLayout = (VkImageLayout)depthInitialLayout; + depthAttachment.finalLayout = (VkImageLayout)depthFinalLayout; + attachments.push_back (depthAttachment); + depthReference.attachment = 1; + depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + } + + VkAttachmentReference resolveReference; + memset (&resolveReference, 0, sizeof (resolveReference)); + if (hasResolve) { + + VkAttachmentDescription resolveAttachment; + memset (&resolveAttachment, 0, sizeof (resolveAttachment)); + resolveAttachment.format = (VkFormat)resolveFormat; + resolveAttachment.samples = VK_SAMPLE_COUNT_1_BIT; + resolveAttachment.loadOp = (VkAttachmentLoadOp)resolveLoadOp; + resolveAttachment.storeOp = (VkAttachmentStoreOp)resolveStoreOp; + resolveAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + resolveAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + resolveAttachment.initialLayout = (VkImageLayout)resolveInitialLayout; + resolveAttachment.finalLayout = (VkImageLayout)resolveFinalLayout; + attachments.push_back (resolveAttachment); + resolveReference.attachment = (uint32_t)(attachments.size () - 1); + resolveReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + } + + VkSubpassDescription subpass; + memset (&subpass, 0, sizeof (subpass)); + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &colorReference; + subpass.pResolveAttachments = hasResolve ? &resolveReference : 0; + subpass.pDepthStencilAttachment = hasDepth ? &depthReference : 0; + + VkSubpassDependency dependency; + memset (&dependency, 0, sizeof (dependency)); + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + + VkRenderPassCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + createInfo.attachmentCount = (uint32_t)attachments.size (); + createInfo.pAttachments = attachments.data (); + createInfo.subpassCount = 1; + createInfo.pSubpasses = &subpass; + createInfo.dependencyCount = 1; + createInfo.pDependencies = &dependency; + + VkRenderPass renderPass = VK_NULL_HANDLE; + VkResult result = vkCreateRenderPass (device, &createInfo, 0, &renderPass); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateRenderPass failed"; + return 0; + + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)renderPass); +#else + lastVKError = "Lime was built without lime-vulkan support"; return 0; - #endif +#endif + + } + + value lime_vk_get_last_error () { + + return alloc_string (lastVKError.c_str ()); + + } + + + void lime_vk_destroy_render_pass (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int renderPassHigh, + int renderPassLow) { + +#ifdef LIME_VULKAN + if (renderPassHigh == 0 && renderPassLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkRenderPass renderPass = (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow); + PFN_vkDestroyRenderPass vkDestroyRenderPass = (PFN_vkDestroyRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyRenderPass"); + if (vkDestroyRenderPass) { + + vkDestroyRenderPass (device, renderPass, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif } - HL_PRIM int HL_NAME(hl_font_get_underline_position) (HL_CFFIPointer* fontHandle) { + HL_PRIM void HL_NAME(hl_vk_destroy_render_pass) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int renderPassHigh, int renderPassLow) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetUnderlinePosition (); - #else - return 0; - #endif +#ifdef LIME_VULKAN + if (renderPassHigh == 0 && renderPassLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkRenderPass renderPass = (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow); + PFN_vkDestroyRenderPass vkDestroyRenderPass = (PFN_vkDestroyRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyRenderPass"); + if (vkDestroyRenderPass) { + + vkDestroyRenderPass (device, renderPass, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif } - int lime_font_get_underline_thickness (value fontHandle) { + value lime_vk_create_framebuffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int renderPassHigh, + int renderPassLow, value attachments, int width, int height, int layers) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetUnderlineThickness (); - #else - return 0; - #endif +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkRenderPass renderPass = (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow); + std::vector packed = GetVulkanIntVector (attachments); + if (packed.empty () || packed.size () < (size_t)(1 + packed[0] * 2)) { - } + lastVKError = "Invalid Vulkan framebuffer attachment list"; + return alloc_null (); + } - HL_PRIM int HL_NAME(hl_font_get_underline_thickness) (HL_CFFIPointer* fontHandle) { + std::vector imageViews; + imageViews.reserve ((size_t)packed[0]); + for (int i = 0; i < packed[0]; ++i) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetUnderlineThickness (); - #else - return 0; - #endif + imageViews.push_back ((VkImageView)(uintptr_t)CombineVulkanHandle (packed[1 + i * 2], packed[2 + i * 2])); - } + } + PFN_vkCreateFramebuffer vkCreateFramebuffer = (PFN_vkCreateFramebuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateFramebuffer"); + if (!vkCreateFramebuffer || !renderPass) return alloc_null (); + + VkFramebufferCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + createInfo.renderPass = renderPass; + createInfo.attachmentCount = (uint32_t)imageViews.size (); + createInfo.pAttachments = imageViews.data (); + createInfo.width = (uint32_t)width; + createInfo.height = (uint32_t)height; + createInfo.layers = (uint32_t)layers; + + VkFramebuffer framebuffer = VK_NULL_HANDLE; + VkResult result = vkCreateFramebuffer (device, &createInfo, 0, &framebuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateFramebuffer failed"; + return alloc_null (); - int lime_font_get_strikethrough_position (value fontHandle) { + } - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetStrikethroughPosition (); - #else - return 0; - #endif + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)framebuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif } - HL_PRIM int HL_NAME(hl_font_get_strikethrough_position) (HL_CFFIPointer* fontHandle) { + HL_PRIM vdynamic* HL_NAME(hl_vk_create_framebuffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int renderPassHigh, int renderPassLow, hl_varray* attachments, int width, int height, int layers) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetStrikethroughPosition (); - #else - return 0; - #endif +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkRenderPass renderPass = (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow); + std::vector packed = GetHLVulkanIntVector (attachments); + if (packed.empty () || packed.size () < (size_t)(1 + packed[0] * 2)) { - } + lastVKError = "Invalid Vulkan framebuffer attachment list"; + return 0; + } - int lime_font_get_strikethrough_thickness (value fontHandle) { + std::vector imageViews; + imageViews.reserve ((size_t)packed[0]); + for (int i = 0; i < packed[0]; ++i) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetStrikethroughThickness (); - #else - return 0; - #endif + imageViews.push_back ((VkImageView)(uintptr_t)CombineVulkanHandle (packed[1 + i * 2], packed[2 + i * 2])); - } + } + PFN_vkCreateFramebuffer vkCreateFramebuffer = (PFN_vkCreateFramebuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateFramebuffer"); + if (!vkCreateFramebuffer || !renderPass) return 0; + + VkFramebufferCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + createInfo.renderPass = renderPass; + createInfo.attachmentCount = (uint32_t)imageViews.size (); + createInfo.pAttachments = imageViews.data (); + createInfo.width = (uint32_t)width; + createInfo.height = (uint32_t)height; + createInfo.layers = (uint32_t)layers; + + VkFramebuffer framebuffer = VK_NULL_HANDLE; + VkResult result = vkCreateFramebuffer (device, &createInfo, 0, &framebuffer); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateFramebuffer failed"; + return 0; - HL_PRIM int HL_NAME(hl_font_get_strikethrough_thickness) (HL_CFFIPointer* fontHandle) { + } - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetStrikethroughThickness (); - #else + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)framebuffer); +#else + lastVKError = "Lime was built without lime-vulkan support"; return 0; - #endif +#endif } - int lime_font_get_units_per_em (value fontHandle) { + void lime_vk_destroy_framebuffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int framebufferHigh, + int framebufferLow) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return font->GetUnitsPerEM (); - #else - return 0; - #endif +#ifdef LIME_VULKAN + if (framebufferHigh == 0 && framebufferLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFramebuffer framebuffer = (VkFramebuffer)(uintptr_t)CombineVulkanHandle (framebufferHigh, framebufferLow); + PFN_vkDestroyFramebuffer vkDestroyFramebuffer = (PFN_vkDestroyFramebuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyFramebuffer"); + if (vkDestroyFramebuffer) { + + vkDestroyFramebuffer (device, framebuffer, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif } - HL_PRIM int HL_NAME(hl_font_get_units_per_em) (HL_CFFIPointer* fontHandle) { + HL_PRIM void HL_NAME(hl_vk_destroy_framebuffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int framebufferHigh, int framebufferLow) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return font->GetUnitsPerEM (); - #else - return 0; - #endif +#ifdef LIME_VULKAN + if (framebufferHigh == 0 && framebufferLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkFramebuffer framebuffer = (VkFramebuffer)(uintptr_t)CombineVulkanHandle (framebufferHigh, framebufferLow); + PFN_vkDestroyFramebuffer vkDestroyFramebuffer = (PFN_vkDestroyFramebuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyFramebuffer"); + if (vkDestroyFramebuffer) { - } + vkDestroyFramebuffer (device, framebuffer, 0); + lastVKError.clear (); + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif - value lime_font_load_bytes (value data) { + } - #ifdef LIME_FREETYPE - Resource resource; - Bytes bytes; - bytes.Set (data); - resource = Resource (&bytes); + value lime_vk_create_shader_module (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value bytes, int byteOffset, + int byteLength) { - Font *font = new Font (&resource, 0); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + Bytes data (bytes); + if (!data.b || byteOffset < 0 || byteLength <= 0 || byteOffset + byteLength > data.length || (byteLength % 4) != 0) { - if (font) { + lastVKError = "Invalid Vulkan shader module bytes"; + return alloc_null (); - if (font->face) { + } - return CFFIPointer (font, gc_font); + PFN_vkCreateShaderModule vkCreateShaderModule = (PFN_vkCreateShaderModule)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateShaderModule"); + if (!vkCreateShaderModule) return alloc_null (); - } else { + VkShaderModuleCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + createInfo.codeSize = (size_t)byteLength; + createInfo.pCode = (const uint32_t*)(data.b + byteOffset); - delete font; + VkShaderModule shaderModule = VK_NULL_HANDLE; + VkResult result = vkCreateShaderModule (device, &createInfo, 0, &shaderModule); + if (result != VK_SUCCESS) { - } + lastVKError = "vkCreateShaderModule failed"; + return alloc_null (); } - #endif + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)shaderModule); +#else + lastVKError = "Lime was built without lime-vulkan support"; return alloc_null (); +#endif } - HL_PRIM HL_CFFIPointer* HL_NAME(hl_font_load_bytes) (Bytes* data) { - - #ifdef LIME_FREETYPE - Resource resource = Resource (data); + HL_PRIM vdynamic* HL_NAME(hl_vk_create_shader_module) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, Bytes* bytes, int byteOffset, int byteLength) { - Font *font = new Font (&resource, 0); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + if (!bytes || !bytes->b || byteOffset < 0 || byteLength <= 0 || byteOffset + byteLength > bytes->length || (byteLength % 4) != 0) { - if (font) { + lastVKError = "Invalid Vulkan shader module bytes"; + return 0; - if (font->face) { + } - return HLCFFIPointer (font, (hl_finalizer)hl_gc_font); + PFN_vkCreateShaderModule vkCreateShaderModule = (PFN_vkCreateShaderModule)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCreateShaderModule"); + if (!vkCreateShaderModule) return 0; - } else { + VkShaderModuleCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + createInfo.codeSize = (size_t)byteLength; + createInfo.pCode = (const uint32_t*)(bytes->b + byteOffset); - delete font; + VkShaderModule shaderModule = VK_NULL_HANDLE; + VkResult result = vkCreateShaderModule (device, &createInfo, 0, &shaderModule); + if (result != VK_SUCCESS) { - } + lastVKError = "vkCreateShaderModule failed"; + return 0; } - #endif + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)shaderModule); +#else + lastVKError = "Lime was built without lime-vulkan support"; return 0; +#endif } - value lime_font_load_file (value data) { + void lime_vk_destroy_shader_module (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int shaderModuleHigh, + int shaderModuleLow) { - #ifdef LIME_FREETYPE - Resource resource = Resource (val_string (data)); +#ifdef LIME_VULKAN + if (shaderModuleHigh == 0 && shaderModuleLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkShaderModule shaderModule = (VkShaderModule)(uintptr_t)CombineVulkanHandle (shaderModuleHigh, shaderModuleLow); + PFN_vkDestroyShaderModule vkDestroyShaderModule = (PFN_vkDestroyShaderModule)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyShaderModule"); + if (vkDestroyShaderModule) { - Font *font = new Font (&resource, 0); + vkDestroyShaderModule (device, shaderModule, 0); + lastVKError.clear (); - if (font) { + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif - if (font->face) { + } - return CFFIPointer (font, gc_font); - } else { + HL_PRIM void HL_NAME(hl_vk_destroy_shader_module) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int shaderModuleHigh, int shaderModuleLow) { - delete font; +#ifdef LIME_VULKAN + if (shaderModuleHigh == 0 && shaderModuleLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkShaderModule shaderModule = (VkShaderModule)(uintptr_t)CombineVulkanHandle (shaderModuleHigh, shaderModuleLow); + PFN_vkDestroyShaderModule vkDestroyShaderModule = (PFN_vkDestroyShaderModule)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyShaderModule"); + if (vkDestroyShaderModule) { - } + vkDestroyShaderModule (device, shaderModule, 0); + lastVKError.clear (); } - #endif - - return alloc_null (); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif } - HL_PRIM HL_CFFIPointer* HL_NAME(hl_font_load_file) (hl_vstring* data) { - - #ifdef LIME_FREETYPE - Resource resource = Resource (data ? hl_to_utf8 ((const uchar*)data->bytes) : NULL); + value lime_vk_create_sampler (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int filter, int addressMode, + int mipmapMode, bool anisotropyEnable, double maxAnisotropy, int compareOp, double minLod, double maxLod) { - Font *font = new Font (&resource, 0); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateSampler vkCreateSampler = (PFN_vkCreateSampler)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateSampler"); + if (!vkCreateSampler) return alloc_null (); + + VkSamplerCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + createInfo.magFilter = (VkFilter)filter; + createInfo.minFilter = (VkFilter)filter; + createInfo.mipmapMode = (VkSamplerMipmapMode)mipmapMode; + createInfo.addressModeU = (VkSamplerAddressMode)addressMode; + createInfo.addressModeV = (VkSamplerAddressMode)addressMode; + createInfo.addressModeW = (VkSamplerAddressMode)addressMode; + createInfo.anisotropyEnable = anisotropyEnable ? VK_TRUE : VK_FALSE; + createInfo.maxAnisotropy = (float)maxAnisotropy; + createInfo.compareEnable = compareOp >= 0 ? VK_TRUE : VK_FALSE; + createInfo.compareOp = compareOp >= 0 ? (VkCompareOp)compareOp : VK_COMPARE_OP_ALWAYS; + createInfo.minLod = (float)minLod; + createInfo.maxLod = (float)maxLod; + createInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + + VkSampler sampler = VK_NULL_HANDLE; + VkResult result = vkCreateSampler (device, &createInfo, 0, &sampler); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateSampler failed"; + return alloc_null (); - if (font) { + } - if (font->face) { + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)sampler); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif - return HLCFFIPointer (font, (hl_finalizer)hl_gc_font); + } - } else { - delete font; + HL_PRIM vdynamic* HL_NAME(hl_vk_create_sampler) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int filter, int addressMode, int mipmapMode, bool anisotropyEnable, double maxAnisotropy, int compareOp, double minLod, double maxLod) { - } +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreateSampler vkCreateSampler = (PFN_vkCreateSampler)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateSampler"); + if (!vkCreateSampler) return 0; + + VkSamplerCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + createInfo.magFilter = (VkFilter)filter; + createInfo.minFilter = (VkFilter)filter; + createInfo.mipmapMode = (VkSamplerMipmapMode)mipmapMode; + createInfo.addressModeU = (VkSamplerAddressMode)addressMode; + createInfo.addressModeV = (VkSamplerAddressMode)addressMode; + createInfo.addressModeW = (VkSamplerAddressMode)addressMode; + createInfo.anisotropyEnable = anisotropyEnable ? VK_TRUE : VK_FALSE; + createInfo.maxAnisotropy = (float)maxAnisotropy; + createInfo.compareEnable = compareOp >= 0 ? VK_TRUE : VK_FALSE; + createInfo.compareOp = compareOp >= 0 ? (VkCompareOp)compareOp : VK_COMPARE_OP_ALWAYS; + createInfo.minLod = (float)minLod; + createInfo.maxLod = (float)maxLod; + createInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + + VkSampler sampler = VK_NULL_HANDLE; + VkResult result = vkCreateSampler (device, &createInfo, 0, &sampler); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateSampler failed"; + return 0; } - #endif + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)sampler); +#else + lastVKError = "Lime was built without lime-vulkan support"; return 0; +#endif } - value lime_font_load (value data) { - - if (val_is_string (data)) { - - return lime_font_load_file (data); + void lime_vk_destroy_sampler (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int samplerHigh, int samplerLow) { - } else { +#ifdef LIME_VULKAN + if (samplerHigh == 0 && samplerLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSampler sampler = (VkSampler)(uintptr_t)CombineVulkanHandle (samplerHigh, samplerLow); + PFN_vkDestroySampler vkDestroySampler = (PFN_vkDestroySampler)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroySampler"); + if (vkDestroySampler) { - return lime_font_load_bytes (data); + vkDestroySampler (device, sampler, 0); + lastVKError.clear (); } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif } - value lime_font_outline_decompose (value fontHandle, int size) { + HL_PRIM void HL_NAME(hl_vk_destroy_sampler) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int samplerHigh, int samplerLow) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return (value)font->Decompose (true, size); - #else - return alloc_null (); - #endif +#ifdef LIME_VULKAN + if (samplerHigh == 0 && samplerLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkSampler sampler = (VkSampler)(uintptr_t)CombineVulkanHandle (samplerHigh, samplerLow); + PFN_vkDestroySampler vkDestroySampler = (PFN_vkDestroySampler)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroySampler"); + if (vkDestroySampler) { - } + vkDestroySampler (device, sampler, 0); + lastVKError.clear (); + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif - value lime_font_outline_decompose_no_hint (value fontHandle, int size) { + } - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - return (value)font->Decompose (true, size, false); - #else - return alloc_null (); - #endif - } + value lime_vk_create_descriptor_set_layout (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value bindings) { +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + std::vector packed = GetVulkanIntVector (bindings); + if (packed.size () < 2 || packed.size () < (size_t)(2 + packed[1] * 4)) return alloc_null (); + + std::vector nativeBindings; + nativeBindings.reserve ((size_t)packed[1]); + for (int i = 0; i < packed[1]; ++i) { + + int base = 2 + i * 4; + VkDescriptorSetLayoutBinding binding; + memset (&binding, 0, sizeof (binding)); + binding.binding = (uint32_t)packed[base]; + binding.descriptorType = (VkDescriptorType)packed[base + 1]; + binding.descriptorCount = (uint32_t)packed[base + 2]; + binding.stageFlags = (VkShaderStageFlags)packed[base + 3]; + nativeBindings.push_back (binding); - HL_PRIM vdynamic* HL_NAME(hl_font_outline_decompose) (HL_CFFIPointer* fontHandle, int size) { + } - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return (vdynamic*)font->Decompose (false, size); - #else - return 0; - #endif + PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout = + (PFN_vkCreateDescriptorSetLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateDescriptorSetLayout"); + if (!vkCreateDescriptorSetLayout) return alloc_null (); - } + VkDescriptorSetLayoutCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + createInfo.flags = (VkDescriptorSetLayoutCreateFlags)packed[0]; + createInfo.bindingCount = (uint32_t)nativeBindings.size (); + createInfo.pBindings = nativeBindings.empty () ? 0 : nativeBindings.data (); + VkDescriptorSetLayout layout = VK_NULL_HANDLE; + VkResult result = vkCreateDescriptorSetLayout (device, &createInfo, 0, &layout); + if (result != VK_SUCCESS) { - HL_PRIM vdynamic* HL_NAME(hl_font_outline_decompose_no_hint) (HL_CFFIPointer* fontHandle, int size) { + lastVKError = "vkCreateDescriptorSetLayout failed"; + return alloc_null (); - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - return (vdynamic*)font->Decompose (false, size, false); - #else - return 0; - #endif + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)layout); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif } - value lime_font_render_glyph (value fontHandle, int index, value data) { + HL_PRIM vdynamic* HL_NAME(hl_vk_create_descriptor_set_layout) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, hl_varray* bindings) { - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - Bytes bytes (data); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + std::vector packed = GetHLVulkanIntVector (bindings); + if (packed.size () < 2 || packed.size () < (size_t)(2 + packed[1] * 4)) return 0; + + std::vector nativeBindings; + nativeBindings.reserve ((size_t)packed[1]); + for (int i = 0; i < packed[1]; ++i) { + + int base = 2 + i * 4; + VkDescriptorSetLayoutBinding binding; + memset (&binding, 0, sizeof (binding)); + binding.binding = (uint32_t)packed[base]; + binding.descriptorType = (VkDescriptorType)packed[base + 1]; + binding.descriptorCount = (uint32_t)packed[base + 2]; + binding.stageFlags = (VkShaderStageFlags)packed[base + 3]; + nativeBindings.push_back (binding); - if (font->RenderGlyph (index, &bytes)) { + } - return bytes.Value (data); + PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout = + (PFN_vkCreateDescriptorSetLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateDescriptorSetLayout"); + if (!vkCreateDescriptorSetLayout) return 0; + + VkDescriptorSetLayoutCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + createInfo.flags = (VkDescriptorSetLayoutCreateFlags)packed[0]; + createInfo.bindingCount = (uint32_t)nativeBindings.size (); + createInfo.pBindings = nativeBindings.empty () ? 0 : nativeBindings.data (); + + VkDescriptorSetLayout layout = VK_NULL_HANDLE; + VkResult result = vkCreateDescriptorSetLayout (device, &createInfo, 0, &layout); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateDescriptorSetLayout failed"; + return 0; } - #endif - return alloc_null (); + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)layout); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif } - value lime_font_render_glyph_with_flags (value fontHandle, int index, int loadFlags, value data) { - - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - Bytes bytes (data); + void lime_vk_destroy_descriptor_set_layout (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int layoutHigh, + int layoutLow) { - if (font->RenderGlyphWithFlags (index, loadFlags, &bytes)) { +#ifdef LIME_VULKAN + if (layoutHigh == 0 && layoutLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorSetLayout layout = (VkDescriptorSetLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout = + (PFN_vkDestroyDescriptorSetLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyDescriptorSetLayout"); + if (vkDestroyDescriptorSetLayout) { - return bytes.Value (data); + vkDestroyDescriptorSetLayout (device, layout, 0); + lastVKError.clear (); } - #endif - - return alloc_null (); +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif } - HL_PRIM Bytes* HL_NAME(hl_font_render_glyph) (HL_CFFIPointer* fontHandle, int index, Bytes* data) { - - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; + HL_PRIM void HL_NAME(hl_vk_destroy_descriptor_set_layout) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int layoutHigh, int layoutLow) { - if (font->RenderGlyph (index, data)) { +#ifdef LIME_VULKAN + if (layoutHigh == 0 && layoutLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorSetLayout layout = (VkDescriptorSetLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout = + (PFN_vkDestroyDescriptorSetLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyDescriptorSetLayout"); + if (vkDestroyDescriptorSetLayout) { - return data; + vkDestroyDescriptorSetLayout (device, layout, 0); + lastVKError.clear (); } - #endif - - return NULL; +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif } - HL_PRIM Bytes* HL_NAME(hl_font_render_glyph_with_flags) (HL_CFFIPointer* fontHandle, int index, int loadFlags, Bytes* data) { + value lime_vk_create_descriptor_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value poolSizes) { - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + std::vector packed = GetVulkanIntVector (poolSizes); + if (packed.size () < 3 || packed.size () < (size_t)(3 + packed[2] * 2)) return alloc_null (); - if (font->RenderGlyphWithFlags (index, loadFlags, data)) { + std::vector nativeSizes; + nativeSizes.reserve ((size_t)packed[2]); + for (int i = 0; i < packed[2]; ++i) { - return data; + int base = 3 + i * 2; + VkDescriptorPoolSize size; + size.type = (VkDescriptorType)packed[base]; + size.descriptorCount = (uint32_t)packed[base + 1]; + nativeSizes.push_back (size); } - #endif - - return NULL; - - } + PFN_vkCreateDescriptorPool vkCreateDescriptorPool = + (PFN_vkCreateDescriptorPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateDescriptorPool"); + if (!vkCreateDescriptorPool) return alloc_null (); - value lime_font_render_glyphs (value fontHandle, value indices, value data) { - - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - Bytes bytes (data); + VkDescriptorPoolCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + createInfo.flags = (VkDescriptorPoolCreateFlags)packed[0]; + createInfo.maxSets = (uint32_t)packed[1]; + createInfo.poolSizeCount = (uint32_t)nativeSizes.size (); + createInfo.pPoolSizes = nativeSizes.empty () ? 0 : nativeSizes.data (); - if (font->RenderGlyphs (indices, &bytes)) { + VkDescriptorPool pool = VK_NULL_HANDLE; + VkResult result = vkCreateDescriptorPool (device, &createInfo, 0, &pool); + if (result != VK_SUCCESS) { - return bytes.Value (data); + lastVKError = "vkCreateDescriptorPool failed"; + return alloc_null (); } - #endif + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)pool); +#else + lastVKError = "Lime was built without lime-vulkan support"; return alloc_null (); +#endif } - HL_PRIM Bytes* HL_NAME(hl_font_render_glyphs) (HL_CFFIPointer* fontHandle, hl_varray* indices, Bytes* data) { + HL_PRIM vdynamic* HL_NAME(hl_vk_create_descriptor_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, hl_varray* poolSizes) { - // #ifdef LIME_FREETYPE - // Font *font = (Font*)fontHandle->ptr; - // return font->RenderGlyphs (indices, &bytes); - // #else - return NULL; - // #endif +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + std::vector packed = GetHLVulkanIntVector (poolSizes); + if (packed.size () < 3 || packed.size () < (size_t)(3 + packed[2] * 2)) return 0; - } + std::vector nativeSizes; + nativeSizes.reserve ((size_t)packed[2]); + for (int i = 0; i < packed[2]; ++i) { + int base = 3 + i * 2; + VkDescriptorPoolSize size; + size.type = (VkDescriptorType)packed[base]; + size.descriptorCount = (uint32_t)packed[base + 1]; + nativeSizes.push_back (size); - void lime_font_set_size (value fontHandle, int fontSize, int dpi) { + } - #ifdef LIME_FREETYPE - Font *font = (Font*)val_data (fontHandle); - font->SetSize (fontSize, dpi); - #endif + PFN_vkCreateDescriptorPool vkCreateDescriptorPool = + (PFN_vkCreateDescriptorPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateDescriptorPool"); + if (!vkCreateDescriptorPool) return 0; - } + VkDescriptorPoolCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + createInfo.flags = (VkDescriptorPoolCreateFlags)packed[0]; + createInfo.maxSets = (uint32_t)packed[1]; + createInfo.poolSizeCount = (uint32_t)nativeSizes.size (); + createInfo.pPoolSizes = nativeSizes.empty () ? 0 : nativeSizes.data (); + VkDescriptorPool pool = VK_NULL_HANDLE; + VkResult result = vkCreateDescriptorPool (device, &createInfo, 0, &pool); + if (result != VK_SUCCESS) { - HL_PRIM void HL_NAME(hl_font_set_size) (HL_CFFIPointer* fontHandle, int fontSize, int dpi) { + lastVKError = "vkCreateDescriptorPool failed"; + return 0; - #ifdef LIME_FREETYPE - Font *font = (Font*)fontHandle->ptr; - font->SetSize (fontSize, dpi); - #endif + } + + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)pool); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif } + HL_PRIM vbyte* HL_NAME(hl_vk_get_last_error) () { - void lime_gamepad_add_mappings (value mappings) { + return hl_copy_bytes ((const vbyte*)lastVKError.c_str (), (int)lastVKError.size () + 1); - int length = val_array_size (mappings); + } - for (int i = 0; i < length; i++) { - Gamepad::AddMapping (val_string (val_array_i (mappings, i))); + void lime_vk_destroy_descriptor_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int poolHigh, int poolLow) { + +#ifdef LIME_VULKAN + if (poolHigh == 0 && poolLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorPool pool = (VkDescriptorPool)(uintptr_t)CombineVulkanHandle (poolHigh, poolLow); + PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool = + (PFN_vkDestroyDescriptorPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyDescriptorPool"); + if (vkDestroyDescriptorPool) { + + vkDestroyDescriptorPool (device, pool, 0); + lastVKError.clear (); } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif } - HL_PRIM void HL_NAME(hl_gamepad_add_mappings) (hl_varray* mappings) { - - int length = mappings->size; - hl_vstring** mappingsData = hl_aptr (mappings, hl_vstring*); + HL_PRIM void HL_NAME(hl_vk_destroy_descriptor_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int poolHigh, int poolLow) { - for (int i = 0; i < length; i++) { +#ifdef LIME_VULKAN + if (poolHigh == 0 && poolLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorPool pool = (VkDescriptorPool)(uintptr_t)CombineVulkanHandle (poolHigh, poolLow); + PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool = + (PFN_vkDestroyDescriptorPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyDescriptorPool"); + if (vkDestroyDescriptorPool) { - Gamepad::AddMapping (hl_to_utf8 ((const uchar*)((*mappingsData++)->bytes))); + vkDestroyDescriptorPool (device, pool, 0); + lastVKError.clear (); } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif } - void lime_gamepad_event_manager_register (value callback, value eventObject) { + bool lime_vk_reset_descriptor_pool (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int poolHigh, int poolLow, + int flags) { - GamepadEvent::callback = new ValuePointer (callback); - GamepadEvent::eventObject = new ValuePointer (eventObject); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorPool pool = (VkDescriptorPool)(uintptr_t)CombineVulkanHandle (poolHigh, poolLow); + PFN_vkResetDescriptorPool vkResetDescriptorPool = + (PFN_vkResetDescriptorPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkResetDescriptorPool"); + if (!vkResetDescriptorPool || !pool) return false; - } + VkResult result = vkResetDescriptorPool (device, pool, (VkDescriptorPoolResetFlags)flags); + if (result != VK_SUCCESS) { + lastVKError = "vkResetDescriptorPool failed"; + return false; - HL_PRIM void HL_NAME(hl_gamepad_event_manager_register) (vclosure* callback, GamepadEvent* eventObject) { + } - GamepadEvent::callback = new ValuePointer (callback); - GamepadEvent::eventObject = new ValuePointer ((vobj*)eventObject); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - value lime_gamepad_get_device_guid (int id) { - - const char* guid = Gamepad::GetDeviceGUID (id); - - if (guid) { + HL_PRIM bool HL_NAME(hl_vk_reset_descriptor_pool) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int poolHigh, int poolLow, int flags) { - value result = alloc_string (guid); - delete guid; - return result; +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorPool pool = (VkDescriptorPool)(uintptr_t)CombineVulkanHandle (poolHigh, poolLow); + PFN_vkResetDescriptorPool vkResetDescriptorPool = + (PFN_vkResetDescriptorPool)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkResetDescriptorPool"); + if (!vkResetDescriptorPool || !pool) return false; - } else { + VkResult result = vkResetDescriptorPool (device, pool, (VkDescriptorPoolResetFlags)flags); + if (result != VK_SUCCESS) { - return alloc_null (); + lastVKError = "vkResetDescriptorPool failed"; + return false; } + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif + } - HL_PRIM vbyte* HL_NAME(hl_gamepad_get_device_guid) (int id) { + value lime_vk_allocate_descriptor_set (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int poolHigh, + int poolLow, int layoutHigh, int layoutLow) { - const char* guid = Gamepad::GetDeviceGUID (id); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorPool pool = (VkDescriptorPool)(uintptr_t)CombineVulkanHandle (poolHigh, poolLow); + VkDescriptorSetLayout layout = (VkDescriptorSetLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets = + (PFN_vkAllocateDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkAllocateDescriptorSets"); + if (!vkAllocateDescriptorSets || !pool || !layout) return alloc_null (); + + VkDescriptorSetAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + allocateInfo.descriptorPool = pool; + allocateInfo.descriptorSetCount = 1; + allocateInfo.pSetLayouts = &layout; + + VkDescriptorSet descriptorSet = VK_NULL_HANDLE; + VkResult result = vkAllocateDescriptorSets (device, &allocateInfo, &descriptorSet); + if (result != VK_SUCCESS) { + + lastVKError = "vkAllocateDescriptorSets failed"; + return alloc_null (); - if (guid) { + } - return (vbyte*)guid; + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)descriptorSet); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif - } else { + } + + HL_PRIM vdynamic* HL_NAME(hl_vk_allocate_descriptor_set) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int poolHigh, int poolLow, int layoutHigh, int layoutLow) { + +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorPool pool = (VkDescriptorPool)(uintptr_t)CombineVulkanHandle (poolHigh, poolLow); + VkDescriptorSetLayout layout = (VkDescriptorSetLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets = + (PFN_vkAllocateDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkAllocateDescriptorSets"); + if (!vkAllocateDescriptorSets || !pool || !layout) return 0; + + VkDescriptorSetAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + allocateInfo.descriptorPool = pool; + allocateInfo.descriptorSetCount = 1; + allocateInfo.pSetLayouts = &layout; + + VkDescriptorSet descriptorSet = VK_NULL_HANDLE; + VkResult result = vkAllocateDescriptorSets (device, &allocateInfo, &descriptorSet); + if (result != VK_SUCCESS) { + + lastVKError = "vkAllocateDescriptorSets failed"; return 0; } + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)descriptorSet); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + } - value lime_gamepad_get_device_name (int id) { + bool lime_vk_update_descriptor_set_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int setHigh, + int setLow, int binding, int descriptorType, int imageViewHigh, int imageViewLow, int samplerHigh, int samplerLow, int imageLayout) { - const char* name = Gamepad::GetDeviceName (id); - return name ? alloc_string (name) : alloc_null (); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets = + (PFN_vkUpdateDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUpdateDescriptorSets"); + if (!vkUpdateDescriptorSets || !descriptorSet) return false; + + VkDescriptorImageInfo imageInfo; + memset (&imageInfo, 0, sizeof (imageInfo)); + imageInfo.sampler = (VkSampler)(uintptr_t)CombineVulkanHandle (samplerHigh, samplerLow); + imageInfo.imageView = (VkImageView)(uintptr_t)CombineVulkanHandle (imageViewHigh, imageViewLow); + imageInfo.imageLayout = (VkImageLayout)imageLayout; + + VkWriteDescriptorSet write; + memset (&write, 0, sizeof (write)); + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstSet = descriptorSet; + write.dstBinding = (uint32_t)binding; + write.descriptorCount = 1; + write.descriptorType = (VkDescriptorType)descriptorType; + write.pImageInfo = &imageInfo; + vkUpdateDescriptorSets (device, 1, &write, 0, 0); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM vbyte* HL_NAME(hl_gamepad_get_device_name) (int id) { + HL_PRIM bool HL_NAME(hl_vk_update_descriptor_set_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int setHigh, int setLow, int binding, int descriptorType, int imageViewHigh, int imageViewLow, int samplerHigh, + int samplerLow, int imageLayout) { - return (vbyte*)Gamepad::GetDeviceName (id); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets = + (PFN_vkUpdateDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUpdateDescriptorSets"); + if (!vkUpdateDescriptorSets || !descriptorSet) return false; + + VkDescriptorImageInfo imageInfo; + memset (&imageInfo, 0, sizeof (imageInfo)); + imageInfo.sampler = (VkSampler)(uintptr_t)CombineVulkanHandle (samplerHigh, samplerLow); + imageInfo.imageView = (VkImageView)(uintptr_t)CombineVulkanHandle (imageViewHigh, imageViewLow); + imageInfo.imageLayout = (VkImageLayout)imageLayout; + + VkWriteDescriptorSet write; + memset (&write, 0, sizeof (write)); + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstSet = descriptorSet; + write.dstBinding = (uint32_t)binding; + write.descriptorCount = 1; + write.descriptorType = (VkDescriptorType)descriptorType; + write.pImageInfo = &imageInfo; + vkUpdateDescriptorSets (device, 1, &write, 0, 0); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } +#ifdef LIME_VULKAN + value lime_vulkan_renderer_create (value window, HxString applicationName) { - void lime_gamepad_rumble (int id, double lowFrequencyRumble, double highFrequencyRumble, int duration) { - - Gamepad::Rumble (id, lowFrequencyRumble, highFrequencyRumble, duration); + Window* targetWindow = (Window*)val_data (window); + VulkanRenderer* renderer = new VulkanRenderer (targetWindow); - } + if (!renderer->Create (applicationName.c_str () ? hxs_utf8 (applicationName, nullptr) : 0)) { + lastVulkanRendererError = renderer->GetLastError (); + delete renderer; + return alloc_null (); - HL_PRIM void HL_NAME(hl_gamepad_rumble) (int id, double lowFrequencyRumble, double highFrequencyRumble, int duration) { + } - Gamepad::Rumble (id, lowFrequencyRumble, highFrequencyRumble, duration); + lastVulkanRendererError.clear (); + return CFFIPointer (renderer); } - value lime_gzip_compress (value buffer, value bytes) { - - #ifdef LIME_ZLIB - Bytes data (buffer); - Bytes result (bytes); - - Zlib::Compress (GZIP, &data, &result); + bool lime_vk_update_descriptor_set_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int setHigh, + int setLow, int binding, int descriptorType, int bufferHigh, int bufferLow, int offset, int range) { - return result.Value (bytes); - #else - return alloc_null (); - #endif +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets = + (PFN_vkUpdateDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUpdateDescriptorSets"); + if (!vkUpdateDescriptorSets || !descriptorSet) return false; + + VkDescriptorBufferInfo bufferInfo; + memset (&bufferInfo, 0, sizeof (bufferInfo)); + bufferInfo.buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + bufferInfo.offset = (VkDeviceSize)(uint32_t)offset; + bufferInfo.range = range > 0 ? (VkDeviceSize)(uint32_t)range : VK_WHOLE_SIZE; + + VkWriteDescriptorSet write; + memset (&write, 0, sizeof (write)); + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstSet = descriptorSet; + write.dstBinding = (uint32_t)binding; + write.descriptorCount = 1; + write.descriptorType = (VkDescriptorType)descriptorType; + write.pBufferInfo = &bufferInfo; + vkUpdateDescriptorSets (device, 1, &write, 0, 0); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM Bytes* HL_NAME(hl_gzip_compress) (Bytes* buffer, Bytes* bytes) { + HL_PRIM bool HL_NAME(hl_vk_update_descriptor_set_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int setHigh, int setLow, int binding, int descriptorType, int bufferHigh, int bufferLow, int offset, int range) { - #ifdef LIME_ZLIB - Zlib::Compress (GZIP, buffer, bytes); - return bytes; - #else - return 0; - #endif +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets = + (PFN_vkUpdateDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkUpdateDescriptorSets"); + if (!vkUpdateDescriptorSets || !descriptorSet) return false; + + VkDescriptorBufferInfo bufferInfo; + memset (&bufferInfo, 0, sizeof (bufferInfo)); + bufferInfo.buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + bufferInfo.offset = (VkDeviceSize)(uint32_t)offset; + bufferInfo.range = range > 0 ? (VkDeviceSize)(uint32_t)range : VK_WHOLE_SIZE; + + VkWriteDescriptorSet write; + memset (&write, 0, sizeof (write)); + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstSet = descriptorSet; + write.dstBinding = (uint32_t)binding; + write.descriptorCount = 1; + write.descriptorType = (VkDescriptorType)descriptorType; + write.pBufferInfo = &bufferInfo; + vkUpdateDescriptorSets (device, 1, &write, 0, 0); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - value lime_gzip_decompress (value buffer, value bytes) { - - #ifdef LIME_ZLIB - Bytes data (buffer); - Bytes result (bytes); - - Zlib::Decompress (GZIP, &data, &result); + bool lime_vk_update_descriptor_sets (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value writes) { - return result.Value (bytes); - #else - return alloc_null (); - #endif +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + return UpdateManagedVulkanDescriptorSets (targetWindow, instance, device, GetVulkanIntVector (writes)); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM Bytes* HL_NAME(hl_gzip_decompress) (Bytes* buffer, Bytes* bytes) { + HL_PRIM bool HL_NAME(hl_vk_update_descriptor_sets) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, hl_varray* writes) { - #ifdef LIME_ZLIB - Zlib::Decompress (GZIP, buffer, bytes); - return bytes; - #else - return 0; - #endif +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + return UpdateManagedVulkanDescriptorSets (targetWindow, instance, device, GetHLVulkanIntVector (writes)); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - void lime_haptic_vibrate (int period, int duration) { + value lime_vk_create_pipeline_layout (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value setLayouts, + int pushConstantStages, int pushConstantSize) { - #ifdef IPHONE - Haptic::Vibrate (period, duration); - #endif +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + std::vector packed = GetVulkanIntVector (setLayouts); + if (packed.empty () || packed.size () < (size_t)(1 + packed[0] * 2)) return alloc_null (); - } + std::vector layouts; + layouts.reserve ((size_t)packed[0]); + for (int i = 0; i < packed[0]; ++i) { + layouts.push_back ((VkDescriptorSetLayout)(uintptr_t)CombineVulkanHandle (packed[1 + i * 2], packed[2 + i * 2])); - HL_PRIM void HL_NAME(hl_haptic_vibrate) (int period, int duration) { + } - #ifdef IPHONE - Haptic::Vibrate (period, duration); - #endif + VkPushConstantRange pushRange; + memset (&pushRange, 0, sizeof (pushRange)); + pushRange.stageFlags = (VkShaderStageFlags)pushConstantStages; + pushRange.offset = 0; + pushRange.size = (uint32_t)pushConstantSize; + + PFN_vkCreatePipelineLayout vkCreatePipelineLayout = + (PFN_vkCreatePipelineLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreatePipelineLayout"); + if (!vkCreatePipelineLayout) return alloc_null (); + + VkPipelineLayoutCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + createInfo.setLayoutCount = (uint32_t)layouts.size (); + createInfo.pSetLayouts = layouts.empty () ? 0 : layouts.data (); + createInfo.pushConstantRangeCount = pushConstantSize > 0 ? 1 : 0; + createInfo.pPushConstantRanges = pushConstantSize > 0 ? &pushRange : 0; + + VkPipelineLayout layout = VK_NULL_HANDLE; + VkResult result = vkCreatePipelineLayout (device, &createInfo, 0, &layout); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreatePipelineLayout failed"; + return alloc_null (); + + } + + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)layout); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif } - value lime_image_encode (value buffer, int type, int quality, value bytes) { + HL_PRIM vdynamic* HL_NAME(hl_vk_create_pipeline_layout) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, hl_varray* setLayouts, int pushConstantStages, int pushConstantSize) { - ImageBuffer imageBuffer = ImageBuffer (buffer); - Bytes data = Bytes (bytes); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + std::vector packed = GetHLVulkanIntVector (setLayouts); + if (packed.empty () || packed.size () < (size_t)(1 + packed[0] * 2)) return 0; - switch (type) { + std::vector layouts; + layouts.reserve ((size_t)packed[0]); + for (int i = 0; i < packed[0]; ++i) { - case 0: + layouts.push_back ((VkDescriptorSetLayout)(uintptr_t)CombineVulkanHandle (packed[1 + i * 2], packed[2 + i * 2])); - #ifdef LIME_PNG - if (PNG::Encode (&imageBuffer, &data)) { + } - return data.Value (bytes); + VkPushConstantRange pushRange; + memset (&pushRange, 0, sizeof (pushRange)); + pushRange.stageFlags = (VkShaderStageFlags)pushConstantStages; + pushRange.offset = 0; + pushRange.size = (uint32_t)pushConstantSize; + + PFN_vkCreatePipelineLayout vkCreatePipelineLayout = + (PFN_vkCreatePipelineLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreatePipelineLayout"); + if (!vkCreatePipelineLayout) return 0; + + VkPipelineLayoutCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + createInfo.setLayoutCount = (uint32_t)layouts.size (); + createInfo.pSetLayouts = layouts.empty () ? 0 : layouts.data (); + createInfo.pushConstantRangeCount = pushConstantSize > 0 ? 1 : 0; + createInfo.pPushConstantRanges = pushConstantSize > 0 ? &pushRange : 0; + + VkPipelineLayout layout = VK_NULL_HANDLE; + VkResult result = vkCreatePipelineLayout (device, &createInfo, 0, &layout); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreatePipelineLayout failed"; + return 0; - } - #endif - break; + } - case 1: + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)layout); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif + + } - #ifdef LIME_JPEG - if (JPEG::Encode (&imageBuffer, &data, quality)) { + HL_PRIM HL_CFFIPointer* HL_NAME(hl_vulkan_renderer_create) (HL_CFFIPointer* window, hl_vstring* applicationName) { - return data.Value (bytes); + Window* targetWindow = (Window*)window->ptr; + VulkanRenderer* renderer = new VulkanRenderer (targetWindow); + const char* applicationNameUTF8 = applicationName ? (const char*)hl_to_utf8 ((const uchar*)applicationName->bytes) : 0; - } - #endif - break; + if (!renderer->Create (applicationNameUTF8)) { - default: break; + lastVulkanRendererError = renderer->GetLastError (); + delete renderer; + return 0; } - return alloc_null (); + lastVulkanRendererError.clear (); + return HLCFFIPointer (renderer); } - HL_PRIM Bytes* HL_NAME(hl_image_encode) (ImageBuffer* buffer, int type, int quality, Bytes* bytes) { - - switch (type) { - - case 0: + void lime_vk_destroy_pipeline_layout (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int layoutHigh, + int layoutLow) { - #ifdef LIME_PNG - if (PNG::Encode (buffer, bytes)) { +#ifdef LIME_VULKAN + if (layoutHigh == 0 && layoutLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout = + (PFN_vkDestroyPipelineLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyPipelineLayout"); + if (vkDestroyPipelineLayout) { - return bytes; + vkDestroyPipelineLayout (device, layout, 0); + lastVKError.clear (); - } - #endif - break; + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif - case 1: + } - #ifdef LIME_JPEG - if (JPEG::Encode (buffer, bytes, quality)) { - return bytes; + HL_PRIM void HL_NAME(hl_vk_destroy_pipeline_layout) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int layoutHigh, int layoutLow) { - } - #endif - break; +#ifdef LIME_VULKAN + if (layoutHigh == 0 && layoutLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout = + (PFN_vkDestroyPipelineLayout)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyPipelineLayout"); + if (vkDestroyPipelineLayout) { - default: break; + vkDestroyPipelineLayout (device, layout, 0); + lastVKError.clear (); } - - return 0; +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif } - value lime_image_load_bytes (value data, value buffer) { + value lime_vk_create_pipeline_cache (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value bytes, int byteOffset, + int byteLength) { - Resource resource; - Bytes bytes; +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreatePipelineCache vkCreatePipelineCache = + (PFN_vkCreatePipelineCache)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreatePipelineCache"); + if (!vkCreatePipelineCache) return alloc_null (); - ImageBuffer imageBuffer = ImageBuffer (buffer); + VkPipelineCacheCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; + Bytes initialData (bytes); + if (initialData.b && byteLength > 0) { - bytes.Set (data); - resource = Resource (&bytes); + if (byteOffset < 0 || byteOffset + byteLength > initialData.length) { - #ifdef LIME_PNG - if (PNG::Decode (&resource, &imageBuffer)) { + lastVKError = "Invalid Vulkan pipeline cache data range"; + return alloc_null (); - return imageBuffer.Value (buffer); + } + + createInfo.initialDataSize = (size_t)byteLength; + createInfo.pInitialData = initialData.b + byteOffset; } - #endif - #ifdef LIME_JPEG - if (JPEG::Decode (&resource, &imageBuffer)) { + VkPipelineCache cache = VK_NULL_HANDLE; + VkResult result = vkCreatePipelineCache (device, &createInfo, 0, &cache); + if (result != VK_SUCCESS) { - return imageBuffer.Value (buffer); + lastVKError = "vkCreatePipelineCache failed"; + return alloc_null (); } - #endif + lastVKError.clear (); + return CreateVulkanHandleValue ((uint64_t)(uintptr_t)cache); +#else + lastVKError = "Lime was built without lime-vulkan support"; return alloc_null (); +#endif } - HL_PRIM ImageBuffer* HL_NAME(hl_image_load_bytes) (Bytes* data, ImageBuffer* buffer) { + HL_PRIM vdynamic* HL_NAME(hl_vk_create_pipeline_cache) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, Bytes* bytes, int byteOffset, int byteLength) { - Resource resource = Resource (data); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCreatePipelineCache vkCreatePipelineCache = + (PFN_vkCreatePipelineCache)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreatePipelineCache"); + if (!vkCreatePipelineCache) return 0; - #ifdef LIME_PNG - if (PNG::Decode (&resource, buffer)) { + VkPipelineCacheCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; + if (bytes && bytes->b && byteLength > 0) { - return buffer; + if (byteOffset < 0 || byteOffset + byteLength > bytes->length) { + + lastVKError = "Invalid Vulkan pipeline cache data range"; + return 0; + + } + + createInfo.initialDataSize = (size_t)byteLength; + createInfo.pInitialData = bytes->b + byteOffset; } - #endif - #ifdef LIME_JPEG - if (JPEG::Decode (&resource, buffer)) { + VkPipelineCache cache = VK_NULL_HANDLE; + VkResult result = vkCreatePipelineCache (device, &createInfo, 0, &cache); + if (result != VK_SUCCESS) { - return buffer; + lastVKError = "vkCreatePipelineCache failed"; + return 0; } - #endif + lastVKError.clear (); + return HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)cache); +#else + lastVKError = "Lime was built without lime-vulkan support"; return 0; +#endif } - value lime_image_load_file (value data, value buffer) { + bool lime_vk_get_pipeline_cache_data (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int cacheHigh, + int cacheLow, value bytes) { - Resource resource = Resource (val_string (data)); - ImageBuffer imageBuffer = ImageBuffer (buffer); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipelineCache cache = (VkPipelineCache)(uintptr_t)CombineVulkanHandle (cacheHigh, cacheLow); + PFN_vkGetPipelineCacheData vkGetPipelineCacheData = + (PFN_vkGetPipelineCacheData)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkGetPipelineCacheData"); + if (!vkGetPipelineCacheData || !cache) return false; - #ifdef LIME_PNG - if (PNG::Decode (&resource, &imageBuffer)) { + size_t size = 0; + VkResult result = vkGetPipelineCacheData (device, cache, &size, 0); + if (result != VK_SUCCESS) { - return imageBuffer.Value (buffer); + lastVKError = "vkGetPipelineCacheData failed"; + return false; } - #endif - #ifdef LIME_JPEG - if (JPEG::Decode (&resource, &imageBuffer)) { + Bytes data (bytes); + data.Resize ((int)size); + if (size > 0 && !data.b) return false; - return imageBuffer.Value (buffer); + result = vkGetPipelineCacheData (device, cache, &size, data.b); + if (result != VK_SUCCESS) { + + lastVKError = "vkGetPipelineCacheData failed"; + return false; } - #endif - return alloc_null (); + data.Value (bytes); + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM ImageBuffer* HL_NAME(hl_image_load_file) (hl_vstring* data, ImageBuffer* buffer) { + HL_PRIM bool HL_NAME(hl_vk_get_pipeline_cache_data) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int cacheHigh, int cacheLow, Bytes* bytes) { - Resource resource = Resource (data); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipelineCache cache = (VkPipelineCache)(uintptr_t)CombineVulkanHandle (cacheHigh, cacheLow); + PFN_vkGetPipelineCacheData vkGetPipelineCacheData = + (PFN_vkGetPipelineCacheData)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkGetPipelineCacheData"); + if (!vkGetPipelineCacheData || !cache || !bytes) return false; - #ifdef LIME_PNG - if (PNG::Decode (&resource, buffer)) { + size_t size = 0; + VkResult result = vkGetPipelineCacheData (device, cache, &size, 0); + if (result != VK_SUCCESS) { - return buffer; + lastVKError = "vkGetPipelineCacheData failed"; + return false; } - #endif - #ifdef LIME_JPEG - if (JPEG::Decode (&resource, buffer)) { + bytes->Resize ((int)size); + if (size > 0 && !bytes->b) return false; - return buffer; + result = vkGetPipelineCacheData (device, cache, &size, bytes->b); + if (result != VK_SUCCESS) { + + lastVKError = "vkGetPipelineCacheData failed"; + return false; } - #endif - return 0; + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - value lime_image_load (value data, value buffer) { - - if (val_is_string (data)) { - - return lime_image_load_file (data, buffer); + void lime_vk_destroy_pipeline_cache (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int cacheHigh, + int cacheLow) { - } else { +#ifdef LIME_VULKAN + if (cacheHigh == 0 && cacheLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipelineCache cache = (VkPipelineCache)(uintptr_t)CombineVulkanHandle (cacheHigh, cacheLow); + PFN_vkDestroyPipelineCache vkDestroyPipelineCache = + (PFN_vkDestroyPipelineCache)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyPipelineCache"); + if (vkDestroyPipelineCache) { - return lime_image_load_bytes (data, buffer); + vkDestroyPipelineCache (device, cache, 0); + lastVKError.clear (); } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif } - void lime_image_data_util_color_transform (value image, value rect, value colorMatrix) { + HL_PRIM void HL_NAME(hl_vk_destroy_pipeline_cache) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int cacheHigh, int cacheLow) { - Image _image = Image (image); - Rectangle _rect = Rectangle (rect); - ColorMatrix _colorMatrix = ColorMatrix (colorMatrix); - ImageDataUtil::ColorTransform (&_image, &_rect, &_colorMatrix); +#ifdef LIME_VULKAN + if (cacheHigh == 0 && cacheLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipelineCache cache = (VkPipelineCache)(uintptr_t)CombineVulkanHandle (cacheHigh, cacheLow); + PFN_vkDestroyPipelineCache vkDestroyPipelineCache = + (PFN_vkDestroyPipelineCache)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkDestroyPipelineCache"); + if (vkDestroyPipelineCache) { - } + vkDestroyPipelineCache (device, cache, 0); + lastVKError.clear (); + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif - HL_PRIM void HL_NAME(hl_image_data_util_color_transform) (Image* image, Rectangle* rect, ArrayBufferView* colorMatrix) { + } - ColorMatrix _colorMatrix = ColorMatrix (colorMatrix); - ImageDataUtil::ColorTransform (image, rect, &_colorMatrix); + void lime_vulkan_renderer_destroy (value handle) { + + if (val_is_null (handle)) return; + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + delete renderer; } - void lime_image_data_util_copy_channel (value image, value sourceImage, value sourceRect, value destPoint, int srcChannel, int destChannel) { +#ifdef LIME_VULKAN + static VkPipeline CreateManagedVulkanGraphicsPipeline (Window* targetWindow, VkInstance instance, VkDevice device, VkRenderPass renderPass, + VkPipelineLayout layout, VkShaderModule vertexShader, VkShaderModule fragmentShader, const std::vector& state) { - Image _image = Image (image); - Image _sourceImage = Image (sourceImage); - Rectangle _sourceRect = Rectangle (sourceRect); - Vector2 _destPoint = Vector2 (destPoint); - ImageDataUtil::CopyChannel (&_image, &_sourceImage, &_sourceRect, &_destPoint, srcChannel, destChannel); + if (state.size () < 41 || !renderPass || !layout || !vertexShader || !fragmentShader) { - } + lastVKError = "Invalid Vulkan graphics pipeline state"; + return VK_NULL_HANDLE; + } - HL_PRIM void HL_NAME(hl_image_data_util_copy_channel) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int srcChannel, int destChannel) { + int cursor = 0; + VkPipelineCache cache = (VkPipelineCache)(uintptr_t)CombineVulkanHandle (state[cursor], state[cursor + 1]); + cursor += 2; + int topology = state[cursor++]; + bool primitiveRestart = state[cursor++] != 0; + int polygonMode = state[cursor++]; + int cullMode = state[cursor++]; + int frontFace = state[cursor++]; + bool depthTest = state[cursor++] != 0; + bool depthWrite = state[cursor++] != 0; + int depthCompareOp = state[cursor++]; + bool blend = state[cursor++] != 0; + int srcColorBlendFactor = state[cursor++]; + int dstColorBlendFactor = state[cursor++]; + int colorBlendOp = state[cursor++]; + int srcAlphaBlendFactor = state[cursor++]; + int dstAlphaBlendFactor = state[cursor++]; + int alphaBlendOp = state[cursor++]; + int dynamicStateFlags = state[cursor++]; + int colorWriteMask = state[cursor++]; + bool stencilTest = state[cursor++] != 0; + int frontFailOp = state[cursor++]; + int frontPassOp = state[cursor++]; + int frontDepthFailOp = state[cursor++]; + int frontCompareOp = state[cursor++]; + int frontCompareMask = state[cursor++]; + int frontWriteMask = state[cursor++]; + int frontReference = state[cursor++]; + int backFailOp = state[cursor++]; + int backPassOp = state[cursor++]; + int backDepthFailOp = state[cursor++]; + int backCompareOp = state[cursor++]; + int backCompareMask = state[cursor++]; + int backWriteMask = state[cursor++]; + int backReference = state[cursor++]; + int rasterizationSamples = state[cursor++]; + bool sampleShading = state[cursor++] != 0; + int minSampleShading = state[cursor++]; + int sampleMask = state[cursor++]; + bool alphaToCoverage = state[cursor++] != 0; + bool alphaToOne = state[cursor++] != 0; + int bindingCount = state[cursor++]; + + if ((int)state.size () < cursor + bindingCount * 3 + 1) { + + lastVKError = "Invalid Vulkan vertex binding state"; + return VK_NULL_HANDLE; - ImageDataUtil::CopyChannel (image, sourceImage, sourceRect, destPoint, srcChannel, destChannel); + } - } + std::vector bindings; + bindings.reserve ((size_t)bindingCount); + for (int i = 0; i < bindingCount; ++i) { + VkVertexInputBindingDescription binding; + binding.binding = (uint32_t)state[cursor++]; + binding.stride = (uint32_t)state[cursor++]; + binding.inputRate = (VkVertexInputRate)state[cursor++]; + bindings.push_back (binding); - void lime_image_data_util_copy_pixels (value image, value sourceImage, value sourceRect, value destPoint, value alphaImage, value alphaPoint, bool mergeAlpha) { + } - Image _image = Image (image); - Image _sourceImage = Image (sourceImage); - Rectangle _sourceRect = Rectangle (sourceRect); - Vector2 _destPoint = Vector2 (destPoint); + int attributeCount = state[cursor++]; + if ((int)state.size () < cursor + attributeCount * 4) { - if (val_is_null (alphaImage)) { + lastVKError = "Invalid Vulkan vertex attribute state"; + return VK_NULL_HANDLE; - ImageDataUtil::CopyPixels (&_image, &_sourceImage, &_sourceRect, &_destPoint, 0, 0, mergeAlpha); + } - } else { + std::vector attributes; + attributes.reserve ((size_t)attributeCount); + for (int i = 0; i < attributeCount; ++i) { - Image _alphaImage = Image (alphaImage); - Vector2 _alphaPoint = Vector2 (alphaPoint); + VkVertexInputAttributeDescription attribute; + attribute.location = (uint32_t)state[cursor++]; + attribute.binding = (uint32_t)state[cursor++]; + attribute.format = (VkFormat)state[cursor++]; + attribute.offset = (uint32_t)state[cursor++]; + attributes.push_back (attribute); - ImageDataUtil::CopyPixels (&_image, &_sourceImage, &_sourceRect, &_destPoint, &_alphaImage, &_alphaPoint, mergeAlpha); + } + + PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines = + (PFN_vkCreateGraphicsPipelines)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCreateGraphicsPipelines"); + if (!vkCreateGraphicsPipelines) return VK_NULL_HANDLE; + + VkPipelineShaderStageCreateInfo stages[2]; + memset (stages, 0, sizeof (stages)); + stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + stages[0].module = vertexShader; + stages[0].pName = "main"; + stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + stages[1].module = fragmentShader; + stages[1].pName = "main"; + + VkPipelineVertexInputStateCreateInfo vertexInput; + memset (&vertexInput, 0, sizeof (vertexInput)); + vertexInput.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertexInput.vertexBindingDescriptionCount = (uint32_t)bindings.size (); + vertexInput.pVertexBindingDescriptions = bindings.empty () ? 0 : bindings.data (); + vertexInput.vertexAttributeDescriptionCount = (uint32_t)attributes.size (); + vertexInput.pVertexAttributeDescriptions = attributes.empty () ? 0 : attributes.data (); + + VkPipelineInputAssemblyStateCreateInfo inputAssembly; + memset (&inputAssembly, 0, sizeof (inputAssembly)); + inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + inputAssembly.topology = (VkPrimitiveTopology)topology; + inputAssembly.primitiveRestartEnable = primitiveRestart ? VK_TRUE : VK_FALSE; + + VkViewport viewport; + memset (&viewport, 0, sizeof (viewport)); + viewport.width = 1.0f; + viewport.height = 1.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + memset (&scissor, 0, sizeof (scissor)); + scissor.extent.width = 1; + scissor.extent.height = 1; + + VkPipelineViewportStateCreateInfo viewportState; + memset (&viewportState, 0, sizeof (viewportState)); + viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewportState.viewportCount = 1; + viewportState.pViewports = &viewport; + viewportState.scissorCount = 1; + viewportState.pScissors = &scissor; + + VkPipelineRasterizationStateCreateInfo rasterization; + memset (&rasterization, 0, sizeof (rasterization)); + rasterization.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterization.polygonMode = (VkPolygonMode)polygonMode; + rasterization.cullMode = (VkCullModeFlags)cullMode; + rasterization.frontFace = (VkFrontFace)frontFace; + rasterization.lineWidth = 1.0f; + + VkPipelineMultisampleStateCreateInfo multisample; + memset (&multisample, 0, sizeof (multisample)); + multisample.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisample.rasterizationSamples = (VkSampleCountFlagBits)rasterizationSamples; + multisample.sampleShadingEnable = sampleShading ? VK_TRUE : VK_FALSE; + multisample.minSampleShading = (float)minSampleShading / 1000000.0f; + VkSampleMask sampleMaskValue = (VkSampleMask)sampleMask; + multisample.pSampleMask = sampleMask != 0 ? &sampleMaskValue : 0; + multisample.alphaToCoverageEnable = alphaToCoverage ? VK_TRUE : VK_FALSE; + multisample.alphaToOneEnable = alphaToOne ? VK_TRUE : VK_FALSE; + + VkPipelineDepthStencilStateCreateInfo depthStencil; + memset (&depthStencil, 0, sizeof (depthStencil)); + depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depthStencil.depthTestEnable = depthTest ? VK_TRUE : VK_FALSE; + depthStencil.depthWriteEnable = depthWrite ? VK_TRUE : VK_FALSE; + depthStencil.depthCompareOp = (VkCompareOp)depthCompareOp; + depthStencil.stencilTestEnable = stencilTest ? VK_TRUE : VK_FALSE; + depthStencil.front.failOp = (VkStencilOp)frontFailOp; + depthStencil.front.passOp = (VkStencilOp)frontPassOp; + depthStencil.front.depthFailOp = (VkStencilOp)frontDepthFailOp; + depthStencil.front.compareOp = (VkCompareOp)frontCompareOp; + depthStencil.front.compareMask = (uint32_t)frontCompareMask; + depthStencil.front.writeMask = (uint32_t)frontWriteMask; + depthStencil.front.reference = (uint32_t)frontReference; + depthStencil.back.failOp = (VkStencilOp)backFailOp; + depthStencil.back.passOp = (VkStencilOp)backPassOp; + depthStencil.back.depthFailOp = (VkStencilOp)backDepthFailOp; + depthStencil.back.compareOp = (VkCompareOp)backCompareOp; + depthStencil.back.compareMask = (uint32_t)backCompareMask; + depthStencil.back.writeMask = (uint32_t)backWriteMask; + depthStencil.back.reference = (uint32_t)backReference; + + VkPipelineColorBlendAttachmentState colorAttachment; + memset (&colorAttachment, 0, sizeof (colorAttachment)); + colorAttachment.colorWriteMask = (VkColorComponentFlags)colorWriteMask; + colorAttachment.blendEnable = blend ? VK_TRUE : VK_FALSE; + colorAttachment.srcColorBlendFactor = (VkBlendFactor)srcColorBlendFactor; + colorAttachment.dstColorBlendFactor = (VkBlendFactor)dstColorBlendFactor; + colorAttachment.colorBlendOp = (VkBlendOp)colorBlendOp; + colorAttachment.srcAlphaBlendFactor = (VkBlendFactor)srcAlphaBlendFactor; + colorAttachment.dstAlphaBlendFactor = (VkBlendFactor)dstAlphaBlendFactor; + colorAttachment.alphaBlendOp = (VkBlendOp)alphaBlendOp; + + VkPipelineColorBlendStateCreateInfo colorBlend; + memset (&colorBlend, 0, sizeof (colorBlend)); + colorBlend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + colorBlend.attachmentCount = 1; + colorBlend.pAttachments = &colorAttachment; + + std::vector dynamicStates; + if (dynamicStateFlags & 0x1) dynamicStates.push_back (VK_DYNAMIC_STATE_VIEWPORT); + if (dynamicStateFlags & 0x2) dynamicStates.push_back (VK_DYNAMIC_STATE_SCISSOR); + VkPipelineDynamicStateCreateInfo dynamicState; + memset (&dynamicState, 0, sizeof (dynamicState)); + dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamicState.dynamicStateCount = (uint32_t)dynamicStates.size (); + dynamicState.pDynamicStates = dynamicStates.empty () ? 0 : dynamicStates.data (); + + VkGraphicsPipelineCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + createInfo.stageCount = 2; + createInfo.pStages = stages; + createInfo.pVertexInputState = &vertexInput; + createInfo.pInputAssemblyState = &inputAssembly; + createInfo.pViewportState = &viewportState; + createInfo.pRasterizationState = &rasterization; + createInfo.pMultisampleState = &multisample; + createInfo.pDepthStencilState = &depthStencil; + createInfo.pColorBlendState = &colorBlend; + createInfo.pDynamicState = dynamicStates.empty () ? 0 : &dynamicState; + createInfo.layout = layout; + createInfo.renderPass = renderPass; + createInfo.subpass = 0; + + VkPipeline pipeline = VK_NULL_HANDLE; + VkResult result = vkCreateGraphicsPipelines (device, cache, 1, &createInfo, 0, &pipeline); + if (result != VK_SUCCESS) { + + lastVKError = "vkCreateGraphicsPipelines failed"; + return VK_NULL_HANDLE; } + lastVKError.clear (); + return pipeline; + } +#endif - HL_PRIM void HL_NAME(hl_image_data_util_copy_pixels) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, Image* alphaImage, Vector2* alphaPoint, bool mergeAlpha) { - if (!alphaImage) { + value lime_vk_create_graphics_pipeline (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int renderPassHigh, + int renderPassLow, int layoutHigh, int layoutLow, int vertexShaderHigh, int vertexShaderLow, int fragmentShaderHigh, int fragmentShaderLow, + value state) { - ImageDataUtil::CopyPixels (image, sourceImage, sourceRect, destPoint, NULL, NULL, mergeAlpha); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipeline pipeline = CreateManagedVulkanGraphicsPipeline (targetWindow, instance, device, + (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow), + (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow), + (VkShaderModule)(uintptr_t)CombineVulkanHandle (vertexShaderHigh, vertexShaderLow), + (VkShaderModule)(uintptr_t)CombineVulkanHandle (fragmentShaderHigh, fragmentShaderLow), + GetVulkanIntVector (state)); + return pipeline ? CreateVulkanHandleValue ((uint64_t)(uintptr_t)pipeline) : alloc_null (); +#else + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); +#endif - } else { + } - if (!alphaPoint) { - Vector2 _alphaPoint = Vector2 (0, 0); + HL_PRIM vdynamic* HL_NAME(hl_vk_create_graphics_pipeline) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int renderPassHigh, int renderPassLow, int layoutHigh, int layoutLow, int vertexShaderHigh, int vertexShaderLow, + int fragmentShaderHigh, int fragmentShaderLow, hl_varray* state) { - ImageDataUtil::CopyPixels (image, sourceImage, sourceRect, destPoint, alphaImage, &_alphaPoint, mergeAlpha); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipeline pipeline = CreateManagedVulkanGraphicsPipeline (targetWindow, instance, device, + (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow), + (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow), + (VkShaderModule)(uintptr_t)CombineVulkanHandle (vertexShaderHigh, vertexShaderLow), + (VkShaderModule)(uintptr_t)CombineVulkanHandle (fragmentShaderHigh, fragmentShaderLow), + GetHLVulkanIntVector (state)); + return pipeline ? HLCreateVulkanHandleValue ((uint64_t)(uintptr_t)pipeline) : 0; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return 0; +#endif - } else { + } - ImageDataUtil::CopyPixels (image, sourceImage, sourceRect, destPoint, alphaImage, alphaPoint, mergeAlpha); - } + void lime_vk_destroy_pipeline (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int pipelineHigh, int pipelineLow) { + +#ifdef LIME_VULKAN + if (pipelineHigh == 0 && pipelineLow == 0) return; + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipeline pipeline = (VkPipeline)(uintptr_t)CombineVulkanHandle (pipelineHigh, pipelineLow); + PFN_vkDestroyPipeline vkDestroyPipeline = (PFN_vkDestroyPipeline)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyPipeline"); + if (vkDestroyPipeline) { + + vkDestroyPipeline (device, pipeline, 0); + lastVKError.clear (); } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif } - void lime_image_data_util_fill_rect (value image, value rect, int rg, int ba) { + HL_PRIM void HL_NAME(hl_vk_destroy_pipeline) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int pipelineHigh, int pipelineLow) { - Image _image = Image (image); - Rectangle _rect = Rectangle (rect); - int32_t color = (rg << 16) | ba; - ImageDataUtil::FillRect (&_image, &_rect, color); +#ifdef LIME_VULKAN + if (pipelineHigh == 0 && pipelineLow == 0) return; + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkPipeline pipeline = (VkPipeline)(uintptr_t)CombineVulkanHandle (pipelineHigh, pipelineLow); + PFN_vkDestroyPipeline vkDestroyPipeline = (PFN_vkDestroyPipeline)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkDestroyPipeline"); + if (vkDestroyPipeline) { - } + vkDestroyPipeline (device, pipeline, 0); + lastVKError.clear (); + + } +#else + lastVKError = "Lime was built without lime-vulkan support"; +#endif + } - HL_PRIM void HL_NAME(hl_image_data_util_fill_rect) (Image* image, Rectangle* rect, int rg, int ba) { + HL_PRIM void HL_NAME(hl_vulkan_renderer_destroy) (HL_CFFIPointer* handle) { - int32_t color = (rg << 16) | ba; - ImageDataUtil::FillRect (image, rect, color); + if (!handle || !handle->ptr) return; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + handle->ptr = 0; + delete renderer; } - void lime_image_data_util_flood_fill (value image, int x, int y, int rg, int ba) { + bool lime_vk_queue_submit_synced (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, + int queueLow, int commandBufferHigh, int commandBufferLow, value state) { - Image _image = Image (image); - int32_t color = (rg << 16) | ba; - ImageDataUtil::FloodFill (&_image, x, y, color); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + if (packed.size () < 7) return false; + + VkSemaphore waitSemaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (packed[0], packed[1]); + VkPipelineStageFlags waitStage = (VkPipelineStageFlags)packed[2]; + VkSemaphore signalSemaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (packed[3], packed[4]); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (packed[5], packed[6]); + PFN_vkQueueSubmit vkQueueSubmit = (PFN_vkQueueSubmit)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkQueueSubmit"); + if (!vkQueueSubmit || !queue || !commandBuffer) return false; + + VkSubmitInfo submitInfo; + memset (&submitInfo, 0, sizeof (submitInfo)); + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.waitSemaphoreCount = waitSemaphore ? 1 : 0; + submitInfo.pWaitSemaphores = waitSemaphore ? &waitSemaphore : 0; + submitInfo.pWaitDstStageMask = waitSemaphore ? &waitStage : 0; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + submitInfo.signalSemaphoreCount = signalSemaphore ? 1 : 0; + submitInfo.pSignalSemaphores = signalSemaphore ? &signalSemaphore : 0; + + VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); + if (result != VK_SUCCESS) { + + char error[64]; + ::snprintf (error, sizeof (error), "vkQueueSubmit failed: %d", (int)result); + lastVKError = error; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM void HL_NAME(hl_image_data_util_flood_fill) (Image* image, int x, int y, int rg, int ba) { + HL_PRIM bool HL_NAME(hl_vk_queue_submit_synced) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int queueHigh, int queueLow, int commandBufferHigh, int commandBufferLow, hl_varray* state) { - int32_t color = (rg << 16) | ba; - ImageDataUtil::FloodFill (image, x, y, color); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + VkQueue queue = (VkQueue)(uintptr_t)CombineVulkanHandle (queueHigh, queueLow); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + if (packed.size () < 7) return false; + + VkSemaphore waitSemaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (packed[0], packed[1]); + VkPipelineStageFlags waitStage = (VkPipelineStageFlags)packed[2]; + VkSemaphore signalSemaphore = (VkSemaphore)(uintptr_t)CombineVulkanHandle (packed[3], packed[4]); + VkFence fence = (VkFence)(uintptr_t)CombineVulkanHandle (packed[5], packed[6]); + PFN_vkQueueSubmit vkQueueSubmit = (PFN_vkQueueSubmit)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkQueueSubmit"); + if (!vkQueueSubmit || !queue || !commandBuffer) return false; + + VkSubmitInfo submitInfo; + memset (&submitInfo, 0, sizeof (submitInfo)); + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.waitSemaphoreCount = waitSemaphore ? 1 : 0; + submitInfo.pWaitSemaphores = waitSemaphore ? &waitSemaphore : 0; + submitInfo.pWaitDstStageMask = waitSemaphore ? &waitStage : 0; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + submitInfo.signalSemaphoreCount = signalSemaphore ? 1 : 0; + submitInfo.pSignalSemaphores = signalSemaphore ? &signalSemaphore : 0; + + VkResult result = vkQueueSubmit (queue, 1, &submitInfo, fence); + if (result != VK_SUCCESS) { + + char error[64]; + ::snprintf (error, sizeof (error), "vkQueueSubmit failed: %d", (int)result); + lastVKError = error; + return false; + + } + + lastVKError.clear (); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - void lime_image_data_util_get_pixels (value image, value rect, int format, value bytes) { + bool lime_vk_cmd_begin_render_pass (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int renderPassHigh, int renderPassLow, int framebufferHigh, int framebufferLow, value state, value clear) { - Image _image = Image (image); - Rectangle _rect = Rectangle (rect); - PixelFormat _format = (PixelFormat)format; - Bytes pixels = Bytes (bytes); - ImageDataUtil::GetPixels (&_image, &_rect, _format, &pixels); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass = (PFN_vkCmdBeginRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdBeginRenderPass"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + std::vector clearValues = GetVulkanDoubleVector (clear); + if (!vkCmdBeginRenderPass || !commandBuffer || packed.size () < 5 || clearValues.size () < 5) return false; + uint32_t clearValueCount = packed.size () > 5 ? (uint32_t)packed[5] : 2; + if (clearValueCount < 1) clearValueCount = 1; + if (clearValueCount > 2) clearValueCount = 2; + + VkClearValue clears[2]; + memset (clears, 0, sizeof (clears)); + clears[0].color.float32[0] = (float)clearValues[0]; + clears[0].color.float32[1] = (float)clearValues[1]; + clears[0].color.float32[2] = (float)clearValues[2]; + clears[0].color.float32[3] = (float)clearValues[3]; + clears[1].depthStencil.depth = (float)clearValues[4]; + clears[1].depthStencil.stencil = (uint32_t)packed[4]; + + VkRenderPassBeginInfo beginInfo; + memset (&beginInfo, 0, sizeof (beginInfo)); + beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + beginInfo.renderPass = (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow); + beginInfo.framebuffer = (VkFramebuffer)(uintptr_t)CombineVulkanHandle (framebufferHigh, framebufferLow); + beginInfo.renderArea.offset.x = packed[0]; + beginInfo.renderArea.offset.y = packed[1]; + beginInfo.renderArea.extent.width = (uint32_t)packed[2]; + beginInfo.renderArea.extent.height = (uint32_t)packed[3]; + beginInfo.clearValueCount = clearValueCount; + beginInfo.pClearValues = clears; + + vkCmdBeginRenderPass (commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM void HL_NAME(hl_image_data_util_get_pixels) (Image* image, Rectangle* rect, PixelFormat format, Bytes* bytes) { + HL_PRIM bool HL_NAME(hl_vk_cmd_begin_render_pass) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int renderPassHigh, int renderPassLow, int framebufferHigh, int framebufferLow, + hl_varray* state, hl_varray* clear) { - ImageDataUtil::GetPixels (image, rect, format, bytes); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass = (PFN_vkCmdBeginRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdBeginRenderPass"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + std::vector clearValues = GetHLVulkanDoubleVector (clear); + if (!vkCmdBeginRenderPass || !commandBuffer || packed.size () < 5 || clearValues.size () < 5) return false; + uint32_t clearValueCount = packed.size () > 5 ? (uint32_t)packed[5] : 2; + if (clearValueCount < 1) clearValueCount = 1; + if (clearValueCount > 2) clearValueCount = 2; + + VkClearValue clears[2]; + memset (clears, 0, sizeof (clears)); + clears[0].color.float32[0] = (float)clearValues[0]; + clears[0].color.float32[1] = (float)clearValues[1]; + clears[0].color.float32[2] = (float)clearValues[2]; + clears[0].color.float32[3] = (float)clearValues[3]; + clears[1].depthStencil.depth = (float)clearValues[4]; + clears[1].depthStencil.stencil = (uint32_t)packed[4]; + + VkRenderPassBeginInfo beginInfo; + memset (&beginInfo, 0, sizeof (beginInfo)); + beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + beginInfo.renderPass = (VkRenderPass)(uintptr_t)CombineVulkanHandle (renderPassHigh, renderPassLow); + beginInfo.framebuffer = (VkFramebuffer)(uintptr_t)CombineVulkanHandle (framebufferHigh, framebufferLow); + beginInfo.renderArea.offset.x = packed[0]; + beginInfo.renderArea.offset.y = packed[1]; + beginInfo.renderArea.extent.width = (uint32_t)packed[2]; + beginInfo.renderArea.extent.height = (uint32_t)packed[3]; + beginInfo.clearValueCount = clearValueCount; + beginInfo.pClearValues = clears; + + vkCmdBeginRenderPass (commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - void lime_image_data_util_merge (value image, value sourceImage, value sourceRect, value destPoint, int redMultiplier, int greenMultiplier, int blueMultiplier, int alphaMultiplier) { + bool lime_vk_cmd_end_render_pass (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow) { - Image _image = Image (image); - Image _sourceImage = Image (sourceImage); - Rectangle _sourceRect = Rectangle (sourceRect); - Vector2 _destPoint = Vector2 (destPoint); - ImageDataUtil::Merge (&_image, &_sourceImage, &_sourceRect, &_destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdEndRenderPass vkCmdEndRenderPass = (PFN_vkCmdEndRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdEndRenderPass"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdEndRenderPass || !commandBuffer) return false; + vkCmdEndRenderPass (commandBuffer); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM void HL_NAME(hl_image_data_util_merge) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int redMultiplier, int greenMultiplier, int blueMultiplier, int alphaMultiplier) { + HL_PRIM bool HL_NAME(hl_vk_cmd_end_render_pass) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow) { - ImageDataUtil::Merge (image, sourceImage, sourceRect, destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdEndRenderPass vkCmdEndRenderPass = (PFN_vkCmdEndRenderPass)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdEndRenderPass"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdEndRenderPass || !commandBuffer) return false; + vkCmdEndRenderPass (commandBuffer); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - void lime_image_data_util_multiply_alpha (value image) { + bool lime_vk_cmd_bind_pipeline (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int pipelineHigh, int pipelineLow, int bindPoint) { - Image _image = Image (image); - ImageDataUtil::MultiplyAlpha (&_image); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindPipeline vkCmdBindPipeline = (PFN_vkCmdBindPipeline)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdBindPipeline"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipeline pipeline = (VkPipeline)(uintptr_t)CombineVulkanHandle (pipelineHigh, pipelineLow); + if (!vkCmdBindPipeline || !commandBuffer || !pipeline) return false; + vkCmdBindPipeline (commandBuffer, (VkPipelineBindPoint)bindPoint, pipeline); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM void HL_NAME(hl_image_data_util_multiply_alpha) (Image* image) { + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_pipeline) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int pipelineHigh, int pipelineLow, int bindPoint) { - ImageDataUtil::MultiplyAlpha (image); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindPipeline vkCmdBindPipeline = (PFN_vkCmdBindPipeline)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdBindPipeline"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipeline pipeline = (VkPipeline)(uintptr_t)CombineVulkanHandle (pipelineHigh, pipelineLow); + if (!vkCmdBindPipeline || !commandBuffer || !pipeline) return false; + vkCmdBindPipeline (commandBuffer, (VkPipelineBindPoint)bindPoint, pipeline); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - void lime_image_data_util_resize (value image, value buffer, int width, int height) { + bool lime_vk_cmd_bind_descriptor_set (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, int bindPoint, int firstSet) { - Image _image = Image (image); - ImageBuffer _buffer = ImageBuffer (buffer); - ImageDataUtil::Resize (&_image, &_buffer, width, height); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = + (PFN_vkCmdBindDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindDescriptorSets"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + if (!vkCmdBindDescriptorSets || !commandBuffer || !layout || !descriptorSet) return false; + vkCmdBindDescriptorSets (commandBuffer, (VkPipelineBindPoint)bindPoint, layout, (uint32_t)firstSet, 1, &descriptorSet, 0, 0); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM void HL_NAME(hl_image_data_util_resize) (Image* image, ImageBuffer* buffer, int width, int height) { + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_descriptor_set) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, int bindPoint, + int firstSet) { - ImageDataUtil::Resize (image, buffer, width, height); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = + (PFN_vkCmdBindDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindDescriptorSets"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + if (!vkCmdBindDescriptorSets || !commandBuffer || !layout || !descriptorSet) return false; + vkCmdBindDescriptorSets (commandBuffer, (VkPipelineBindPoint)bindPoint, layout, (uint32_t)firstSet, 1, &descriptorSet, 0, 0); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } + bool lime_vk_cmd_bind_descriptor_set_ex (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, value state) { - void lime_image_data_util_set_format (value image, int format) { - - Image _image = Image (image); - PixelFormat _format = (PixelFormat)format; - ImageDataUtil::SetFormat (&_image, _format); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = + (PFN_vkCmdBindDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindDescriptorSets"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + std::vector packed = GetVulkanIntVector (state); + if (!vkCmdBindDescriptorSets || !commandBuffer || !layout || !descriptorSet || packed.size () < 3) return false; + + int dynamicOffsetCount = packed[2]; + if ((int)packed.size () < 3 + dynamicOffsetCount) return false; + std::vector dynamicOffsets; + dynamicOffsets.reserve ((size_t)dynamicOffsetCount); + for (int i = 0; i < dynamicOffsetCount; ++i) dynamicOffsets.push_back ((uint32_t)packed[3 + i]); + + vkCmdBindDescriptorSets (commandBuffer, (VkPipelineBindPoint)packed[0], layout, (uint32_t)packed[1], 1, &descriptorSet, + (uint32_t)dynamicOffsets.size (), dynamicOffsets.empty () ? 0 : dynamicOffsets.data ()); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM void HL_NAME(hl_image_data_util_set_format) (Image* image, PixelFormat format) { + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_descriptor_set_ex) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, hl_varray* state) { - ImageDataUtil::SetFormat (image, format); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = + (PFN_vkCmdBindDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindDescriptorSets"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + std::vector packed = GetHLVulkanIntVector (state); + if (!vkCmdBindDescriptorSets || !commandBuffer || !layout || !descriptorSet || packed.size () < 3) return false; + + int dynamicOffsetCount = packed[2]; + if ((int)packed.size () < 3 + dynamicOffsetCount) return false; + std::vector dynamicOffsets; + dynamicOffsets.reserve ((size_t)dynamicOffsetCount); + for (int i = 0; i < dynamicOffsetCount; ++i) dynamicOffsets.push_back ((uint32_t)packed[3 + i]); + + vkCmdBindDescriptorSets (commandBuffer, (VkPipelineBindPoint)packed[0], layout, (uint32_t)packed[1], 1, &descriptorSet, + (uint32_t)dynamicOffsets.size (), dynamicOffsets.empty () ? 0 : dynamicOffsets.data ()); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - void lime_image_data_util_set_pixels (value image, value rect, value bytes, int offset, int format, int endian) { + bool lime_vk_cmd_bind_descriptor_set_dynamic_offset (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, int dynamicOffset, int firstSet, + int bindPoint) { - Image _image = Image (image); - Rectangle _rect = Rectangle (rect); - Bytes _bytes (bytes); - PixelFormat _format = (PixelFormat)format; - Endian _endian = (Endian)endian; - ImageDataUtil::SetPixels (&_image, &_rect, &_bytes, offset, _format, _endian); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = + (PFN_vkCmdBindDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindDescriptorSets"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + uint32_t offset = (uint32_t)dynamicOffset; + if (!vkCmdBindDescriptorSets || !commandBuffer || !layout || !descriptorSet) return false; + vkCmdBindDescriptorSets (commandBuffer, (VkPipelineBindPoint)bindPoint, layout, (uint32_t)firstSet, 1, &descriptorSet, 1, &offset); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM void HL_NAME(hl_image_data_util_set_pixels) (Image* image, Rectangle* rect, Bytes* bytes, int offset, PixelFormat format, Endian endian) { + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_descriptor_set_dynamic_offset) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, + int deviceHigh, int deviceLow, int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, + int dynamicOffset, int firstSet, int bindPoint) { - ImageDataUtil::SetPixels (image, rect, bytes, offset, format, endian); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = + (PFN_vkCmdBindDescriptorSets)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindDescriptorSets"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + VkDescriptorSet descriptorSet = (VkDescriptorSet)(uintptr_t)CombineVulkanHandle (setHigh, setLow); + uint32_t offset = (uint32_t)dynamicOffset; + if (!vkCmdBindDescriptorSets || !commandBuffer || !layout || !descriptorSet) return false; + vkCmdBindDescriptorSets (commandBuffer, (VkPipelineBindPoint)bindPoint, layout, (uint32_t)firstSet, 1, &descriptorSet, 1, &offset); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - int lime_image_data_util_threshold (value image, value sourceImage, value sourceRect, value destPoint, int operation, int thresholdRG, int thresholdBA, int colorRG, int colorBA, int maskRG, int maskBA, bool copySource) { + value lime_vulkan_renderer_get_info (value handle) { - Image _image = Image (image); - Image _sourceImage = Image (sourceImage); - Rectangle _sourceRect = Rectangle (sourceRect); - Vector2 _destPoint = Vector2 (destPoint); - int32_t threshold = (thresholdRG << 16) | thresholdBA; - int32_t color = (colorRG << 16) | colorBA; - int32_t mask = (maskRG << 16) | maskBA; - return ImageDataUtil::Threshold (&_image, &_sourceImage, &_sourceRect, &_destPoint, operation, threshold, color, mask, copySource); + if (val_is_null (handle)) return alloc_string (""); + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + return alloc_string (renderer->GetInfo ().c_str ()); } - HL_PRIM int HL_NAME(hl_image_data_util_threshold) (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int operation, int thresholdRG, int thresholdBA, int colorRG, int colorBA, int maskRG, int maskBA, bool copySource) { + bool lime_vk_cmd_bind_vertex_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int bufferHigh, int bufferLow, int binding, int offsetHigh, int offsetLow) { - int32_t threshold = (thresholdRG << 16) | thresholdBA; - int32_t color = (colorRG << 16) | colorBA; - int32_t mask = (maskRG << 16) | maskBA; - return ImageDataUtil::Threshold (image, sourceImage, sourceRect, destPoint, operation, threshold, color, mask, copySource); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers = + (PFN_vkCmdBindVertexBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindVertexBuffers"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + VkDeviceSize offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + if (!vkCmdBindVertexBuffers || !commandBuffer || !buffer) return false; + vkCmdBindVertexBuffers (commandBuffer, (uint32_t)binding, 1, &buffer, &offset); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - void lime_image_data_util_unmultiply_alpha (value image) { + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_vertex_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int binding, int offsetHigh, int offsetLow) { - Image _image = Image (image); - ImageDataUtil::UnmultiplyAlpha (&_image); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers = + (PFN_vkCmdBindVertexBuffers)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindVertexBuffers"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + VkDeviceSize offset = (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow); + if (!vkCmdBindVertexBuffers || !commandBuffer || !buffer) return false; + vkCmdBindVertexBuffers (commandBuffer, (uint32_t)binding, 1, &buffer, &offset); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM void HL_NAME(hl_image_data_util_unmultiply_alpha) (Image* image) { + bool lime_vk_cmd_bind_index_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int indexType) { - ImageDataUtil::UnmultiplyAlpha (image); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer = + (PFN_vkCmdBindIndexBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindIndexBuffer"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + if (!vkCmdBindIndexBuffer || !commandBuffer || !buffer) return false; + vkCmdBindIndexBuffer (commandBuffer, buffer, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow), (VkIndexType)indexType); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - double lime_jni_getenv () { + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_index_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int indexType) { - #ifdef ANDROID - return (uintptr_t)JNI::GetEnv (); - #else - return 0; - #endif +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer = + (PFN_vkCmdBindIndexBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBindIndexBuffer"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + if (!vkCmdBindIndexBuffer || !commandBuffer || !buffer) return false; + vkCmdBindIndexBuffer (commandBuffer, buffer, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow), (VkIndexType)indexType); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM double HL_NAME(hl_jni_getenv) () { + bool lime_vk_cmd_set_viewport (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, double x, double y, double width, double height, double minDepth, double maxDepth) { - #ifdef ANDROID - return (uintptr_t)JNI::GetEnv (); - #else - return 0; - #endif +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdSetViewport vkCmdSetViewport = (PFN_vkCmdSetViewport)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdSetViewport"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdSetViewport || !commandBuffer) return false; + VkViewport viewport; + viewport.x = (float)x; + viewport.y = (float)y; + viewport.width = (float)width; + viewport.height = (float)height; + viewport.minDepth = (float)minDepth; + viewport.maxDepth = (float)maxDepth; + vkCmdSetViewport (commandBuffer, 0, 1, &viewport); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - void lime_joystick_event_manager_register (value callback, value eventObject) { + HL_PRIM bool HL_NAME(hl_vk_cmd_set_viewport) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, double x, double y, double width, double height, double minDepth, double maxDepth) { - JoystickEvent::callback = new ValuePointer (callback); - JoystickEvent::eventObject = new ValuePointer (eventObject); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdSetViewport vkCmdSetViewport = (PFN_vkCmdSetViewport)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdSetViewport"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdSetViewport || !commandBuffer) return false; + VkViewport viewport; + viewport.x = (float)x; + viewport.y = (float)y; + viewport.width = (float)width; + viewport.height = (float)height; + viewport.minDepth = (float)minDepth; + viewport.maxDepth = (float)maxDepth; + vkCmdSetViewport (commandBuffer, 0, 1, &viewport); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } + HL_PRIM vbyte* HL_NAME(hl_vulkan_renderer_get_info) (HL_CFFIPointer* handle) { - HL_PRIM void HL_NAME(hl_joystick_event_manager_register) (vclosure* callback, JoystickEvent* eventObject) { - - JoystickEvent::callback = new ValuePointer (callback); - JoystickEvent::eventObject = new ValuePointer ((vobj*)eventObject); + if (!handle || !handle->ptr) return 0; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + return hl_copy_bytes ((const vbyte*)renderer->GetInfo ().c_str (), (int)renderer->GetInfo ().size () + 1); } - value lime_joystick_get_device_guid (int id) { + bool lime_vk_cmd_set_scissor (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int x, int y, int width, int height) { - const char* guid = Joystick::GetDeviceGUID (id); - return guid ? alloc_string (guid) : alloc_null (); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdSetScissor vkCmdSetScissor = (PFN_vkCmdSetScissor)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdSetScissor"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdSetScissor || !commandBuffer) return false; + VkRect2D scissor; + scissor.offset.x = x; + scissor.offset.y = y; + scissor.extent.width = (uint32_t)width; + scissor.extent.height = (uint32_t)height; + vkCmdSetScissor (commandBuffer, 0, 1, &scissor); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM vbyte* HL_NAME(hl_joystick_get_device_guid) (int id) { + HL_PRIM bool HL_NAME(hl_vk_cmd_set_scissor) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int x, int y, int width, int height) { - return (vbyte*)Joystick::GetDeviceGUID (id); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdSetScissor vkCmdSetScissor = (PFN_vkCmdSetScissor)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdSetScissor"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdSetScissor || !commandBuffer) return false; + VkRect2D scissor; + scissor.offset.x = x; + scissor.offset.y = y; + scissor.extent.width = (uint32_t)width; + scissor.extent.height = (uint32_t)height; + vkCmdSetScissor (commandBuffer, 0, 1, &scissor); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - value lime_joystick_get_device_name (int id) { + bool lime_vk_cmd_draw (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int vertexCount, int instanceCount, int firstVertex, int firstInstance) { - const char* name = Joystick::GetDeviceName (id); - return name ? alloc_string (name) : alloc_null (); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdDraw vkCmdDraw = (PFN_vkCmdDraw)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdDraw"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdDraw || !commandBuffer) return false; + vkCmdDraw (commandBuffer, (uint32_t)vertexCount, (uint32_t)instanceCount, (uint32_t)firstVertex, (uint32_t)firstInstance); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM vbyte* HL_NAME(hl_joystick_get_device_name) (int id) { + HL_PRIM bool HL_NAME(hl_vk_cmd_draw) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int vertexCount, int instanceCount, int firstVertex, int firstInstance) { - return (vbyte*)Joystick::GetDeviceName (id); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdDraw vkCmdDraw = (PFN_vkCmdDraw)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdDraw"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdDraw || !commandBuffer) return false; + vkCmdDraw (commandBuffer, (uint32_t)vertexCount, (uint32_t)instanceCount, (uint32_t)firstVertex, (uint32_t)firstInstance); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - int lime_joystick_get_num_axes (int id) { + bool lime_vk_cmd_draw_indexed (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int indexCount, int instanceCount, int firstIndex, int vertexOffset, int firstInstance) { - return Joystick::GetNumAxes (id); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdDrawIndexed vkCmdDrawIndexed = (PFN_vkCmdDrawIndexed)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdDrawIndexed"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdDrawIndexed || !commandBuffer) return false; + vkCmdDrawIndexed (commandBuffer, (uint32_t)indexCount, (uint32_t)instanceCount, (uint32_t)firstIndex, vertexOffset, (uint32_t)firstInstance); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM int HL_NAME(hl_joystick_get_num_axes) (int id) { + HL_PRIM bool HL_NAME(hl_vk_cmd_draw_indexed) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int indexCount, int instanceCount, int firstIndex, int vertexOffset, int firstInstance) { - return Joystick::GetNumAxes (id); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdDrawIndexed vkCmdDrawIndexed = (PFN_vkCmdDrawIndexed)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdDrawIndexed"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + if (!vkCmdDrawIndexed || !commandBuffer) return false; + vkCmdDrawIndexed (commandBuffer, (uint32_t)indexCount, (uint32_t)instanceCount, (uint32_t)firstIndex, vertexOffset, (uint32_t)firstInstance); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - int lime_joystick_get_num_buttons (int id) { + bool lime_vk_cmd_draw_indirect (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, int stride) { - return Joystick::GetNumButtons (id); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdDrawIndirect vkCmdDrawIndirect = (PFN_vkCmdDrawIndirect)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdDrawIndirect"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + if (!vkCmdDrawIndirect || !commandBuffer || !buffer) return false; + vkCmdDrawIndirect (commandBuffer, buffer, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow), (uint32_t)drawCount, + (uint32_t)stride); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM int HL_NAME(hl_joystick_get_num_buttons) (int id) { + HL_PRIM bool HL_NAME(hl_vk_cmd_draw_indirect) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, int stride) { - return Joystick::GetNumButtons (id); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdDrawIndirect vkCmdDrawIndirect = (PFN_vkCmdDrawIndirect)GetManagedVulkanDeviceProc (targetWindow, instance, device, + "vkCmdDrawIndirect"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + if (!vkCmdDrawIndirect || !commandBuffer || !buffer) return false; + vkCmdDrawIndirect (commandBuffer, buffer, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow), (uint32_t)drawCount, + (uint32_t)stride); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - int lime_joystick_get_num_hats (int id) { + bool lime_vk_cmd_draw_indexed_indirect (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, int stride) { - return Joystick::GetNumHats (id); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect = + (PFN_vkCmdDrawIndexedIndirect)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdDrawIndexedIndirect"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + if (!vkCmdDrawIndexedIndirect || !commandBuffer || !buffer) return false; + vkCmdDrawIndexedIndirect (commandBuffer, buffer, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow), (uint32_t)drawCount, + (uint32_t)stride); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM int HL_NAME(hl_joystick_get_num_hats) (int id) { + HL_PRIM bool HL_NAME(hl_vk_cmd_draw_indexed_indirect) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, + int stride) { - return Joystick::GetNumHats (id); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect = + (PFN_vkCmdDrawIndexedIndirect)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdDrawIndexedIndirect"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkBuffer buffer = (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow); + if (!vkCmdDrawIndexedIndirect || !commandBuffer || !buffer) return false; + vkCmdDrawIndexedIndirect (commandBuffer, buffer, (VkDeviceSize)CombineVulkanHandle (offsetHigh, offsetLow), (uint32_t)drawCount, + (uint32_t)stride); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } + value lime_vulkan_renderer_get_last_error () { - value lime_jpeg_decode_bytes (value data, bool decodeData, value buffer) { - - ImageBuffer imageBuffer (buffer); - - Bytes bytes (data); - Resource resource = Resource (&bytes); + return alloc_string (lastVulkanRendererError.c_str ()); - #ifdef LIME_JPEG - if (JPEG::Decode (&resource, &imageBuffer, decodeData)) { + } - return imageBuffer.Value (buffer); - } - #endif + bool lime_vk_cmd_copy_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, value state) { - return alloc_null (); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdCopyBuffer vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyBuffer"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + if (!vkCmdCopyBuffer || !commandBuffer || packed.size () < 6) return false; + + VkBufferCopy region; + region.size = (VkDeviceSize)CombineVulkanHandle (packed[0], packed[1]); + region.srcOffset = (VkDeviceSize)CombineVulkanHandle (packed[2], packed[3]); + region.dstOffset = (VkDeviceSize)CombineVulkanHandle (packed[4], packed[5]); + vkCmdCopyBuffer (commandBuffer, (VkBuffer)(uintptr_t)CombineVulkanHandle (sourceHigh, sourceLow), + (VkBuffer)(uintptr_t)CombineVulkanHandle (destinationHigh, destinationLow), 1, ®ion); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM ImageBuffer* HL_NAME(hl_jpeg_decode_bytes) (Bytes* data, bool decodeData, ImageBuffer* buffer) { - - Resource resource = Resource (data); + HL_PRIM bool HL_NAME(hl_vk_cmd_copy_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, hl_varray* state) { - #ifdef LIME_JPEG - if (JPEG::Decode (&resource, buffer, decodeData)) { +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdCopyBuffer vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyBuffer"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + if (!vkCmdCopyBuffer || !commandBuffer || packed.size () < 6) return false; + + VkBufferCopy region; + region.size = (VkDeviceSize)CombineVulkanHandle (packed[0], packed[1]); + region.srcOffset = (VkDeviceSize)CombineVulkanHandle (packed[2], packed[3]); + region.dstOffset = (VkDeviceSize)CombineVulkanHandle (packed[4], packed[5]); + vkCmdCopyBuffer (commandBuffer, (VkBuffer)(uintptr_t)CombineVulkanHandle (sourceHigh, sourceLow), + (VkBuffer)(uintptr_t)CombineVulkanHandle (destinationHigh, destinationLow), 1, ®ion); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif - return buffer; + } - } - #endif + bool lime_vk_cmd_copy_buffer_to_image_region (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, value state) { - return 0; +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage = + (PFN_vkCmdCopyBufferToImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyBufferToImage"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + if (!vkCmdCopyBufferToImage || !commandBuffer || packed.size () < 15) return false; + + VkBufferImageCopy region; + memset (®ion, 0, sizeof (region)); + region.bufferOffset = (VkDeviceSize)CombineVulkanHandle (packed[4], packed[5]); + region.bufferRowLength = (uint32_t)packed[6]; + region.bufferImageHeight = (uint32_t)packed[7]; + region.imageSubresource.aspectMask = (VkImageAspectFlags)packed[14]; + region.imageSubresource.mipLevel = (uint32_t)packed[11]; + region.imageSubresource.baseArrayLayer = (uint32_t)packed[12]; + region.imageSubresource.layerCount = (uint32_t)packed[13]; + region.imageOffset.x = packed[8]; + region.imageOffset.y = packed[9]; + region.imageOffset.z = packed[10]; + region.imageExtent.width = (uint32_t)packed[0]; + region.imageExtent.height = (uint32_t)packed[1]; + region.imageExtent.depth = (uint32_t)packed[2]; + vkCmdCopyBufferToImage (commandBuffer, (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow), + (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)packed[3], 1, ®ion); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - value lime_jpeg_decode_file (HxString path, bool decodeData, value buffer) { + HL_PRIM bool HL_NAME(hl_vk_cmd_copy_buffer_to_image_region) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, hl_varray* state) { - ImageBuffer imageBuffer (buffer); - Resource resource = Resource (hxs_utf8 (path, nullptr)); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage = + (PFN_vkCmdCopyBufferToImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyBufferToImage"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + if (!vkCmdCopyBufferToImage || !commandBuffer || packed.size () < 15) return false; + + VkBufferImageCopy region; + memset (®ion, 0, sizeof (region)); + region.bufferOffset = (VkDeviceSize)CombineVulkanHandle (packed[4], packed[5]); + region.bufferRowLength = (uint32_t)packed[6]; + region.bufferImageHeight = (uint32_t)packed[7]; + region.imageSubresource.aspectMask = (VkImageAspectFlags)packed[14]; + region.imageSubresource.mipLevel = (uint32_t)packed[11]; + region.imageSubresource.baseArrayLayer = (uint32_t)packed[12]; + region.imageSubresource.layerCount = (uint32_t)packed[13]; + region.imageOffset.x = packed[8]; + region.imageOffset.y = packed[9]; + region.imageOffset.z = packed[10]; + region.imageExtent.width = (uint32_t)packed[0]; + region.imageExtent.height = (uint32_t)packed[1]; + region.imageExtent.depth = (uint32_t)packed[2]; + vkCmdCopyBufferToImage (commandBuffer, (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow), + (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)packed[3], 1, ®ion); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif - #ifdef LIME_JPEG - if (JPEG::Decode (&resource, &imageBuffer, decodeData)) { + } - return imageBuffer.Value (buffer); - } - #endif + bool lime_vk_cmd_copy_image_to_buffer_region (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, int bufferHigh, int bufferLow, value state) { - return alloc_null (); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer = + (PFN_vkCmdCopyImageToBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyImageToBuffer"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + if (!vkCmdCopyImageToBuffer || !commandBuffer || packed.size () < 15) return false; + + VkBufferImageCopy region; + memset (®ion, 0, sizeof (region)); + region.bufferOffset = (VkDeviceSize)CombineVulkanHandle (packed[4], packed[5]); + region.bufferRowLength = (uint32_t)packed[6]; + region.bufferImageHeight = (uint32_t)packed[7]; + region.imageSubresource.aspectMask = (VkImageAspectFlags)packed[14]; + region.imageSubresource.mipLevel = (uint32_t)packed[11]; + region.imageSubresource.baseArrayLayer = (uint32_t)packed[12]; + region.imageSubresource.layerCount = (uint32_t)packed[13]; + region.imageOffset.x = packed[8]; + region.imageOffset.y = packed[9]; + region.imageOffset.z = packed[10]; + region.imageExtent.width = (uint32_t)packed[0]; + region.imageExtent.height = (uint32_t)packed[1]; + region.imageExtent.depth = (uint32_t)packed[2]; + vkCmdCopyImageToBuffer (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)packed[3], + (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow), 1, ®ion); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM ImageBuffer* HL_NAME(hl_jpeg_decode_file) (hl_vstring* path, bool decodeData, ImageBuffer* buffer) { - - Resource resource = Resource (path); + HL_PRIM bool HL_NAME(hl_vk_cmd_copy_image_to_buffer_region) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, int bufferHigh, int bufferLow, hl_varray* state) { - #ifdef LIME_JPEG - if (JPEG::Decode (&resource, buffer, decodeData)) { +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer = + (PFN_vkCmdCopyImageToBuffer)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdCopyImageToBuffer"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + if (!vkCmdCopyImageToBuffer || !commandBuffer || packed.size () < 15) return false; + + VkBufferImageCopy region; + memset (®ion, 0, sizeof (region)); + region.bufferOffset = (VkDeviceSize)CombineVulkanHandle (packed[4], packed[5]); + region.bufferRowLength = (uint32_t)packed[6]; + region.bufferImageHeight = (uint32_t)packed[7]; + region.imageSubresource.aspectMask = (VkImageAspectFlags)packed[14]; + region.imageSubresource.mipLevel = (uint32_t)packed[11]; + region.imageSubresource.baseArrayLayer = (uint32_t)packed[12]; + region.imageSubresource.layerCount = (uint32_t)packed[13]; + region.imageOffset.x = packed[8]; + region.imageOffset.y = packed[9]; + region.imageOffset.z = packed[10]; + region.imageExtent.width = (uint32_t)packed[0]; + region.imageExtent.height = (uint32_t)packed[1]; + region.imageExtent.depth = (uint32_t)packed[2]; + vkCmdCopyImageToBuffer (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)packed[3], + (VkBuffer)(uintptr_t)CombineVulkanHandle (bufferHigh, bufferLow), 1, ®ion); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif - return buffer; + } - } - #endif + HL_PRIM vbyte* HL_NAME(hl_vulkan_renderer_get_last_error) () { - return 0; + return hl_copy_bytes ((const vbyte*)lastVulkanRendererError.c_str (), (int)lastVulkanRendererError.size () + 1); } - int lime_key_code_from_scan_code (int scanCode) { + bool lime_vk_cmd_pipeline_barrier_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, value state) { - return KeyCode::FromScanCode (scanCode); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier = + (PFN_vkCmdPipelineBarrier)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdPipelineBarrier"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + if (!vkCmdPipelineBarrier || !commandBuffer || packed.size () < 11) return false; + + VkImageMemoryBarrier barrier; + memset (&barrier, 0, sizeof (barrier)); + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.oldLayout = (VkImageLayout)packed[0]; + barrier.newLayout = (VkImageLayout)packed[1]; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + barrier.srcAccessMask = (VkAccessFlags)packed[4]; + barrier.dstAccessMask = (VkAccessFlags)packed[5]; + barrier.subresourceRange.aspectMask = (VkImageAspectFlags)packed[6]; + barrier.subresourceRange.baseMipLevel = (uint32_t)packed[7]; + barrier.subresourceRange.levelCount = (uint32_t)packed[8]; + barrier.subresourceRange.baseArrayLayer = (uint32_t)packed[9]; + barrier.subresourceRange.layerCount = (uint32_t)packed[10]; + + vkCmdPipelineBarrier (commandBuffer, (VkPipelineStageFlags)packed[2], (VkPipelineStageFlags)packed[3], 0, 0, 0, 0, 0, 1, &barrier); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM int HL_NAME(hl_key_code_from_scan_code) (int scanCode) { + HL_PRIM bool HL_NAME(hl_vk_cmd_pipeline_barrier_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, hl_varray* state) { - return KeyCode::FromScanCode (scanCode); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier = + (PFN_vkCmdPipelineBarrier)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdPipelineBarrier"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + if (!vkCmdPipelineBarrier || !commandBuffer || packed.size () < 11) return false; + + VkImageMemoryBarrier barrier; + memset (&barrier, 0, sizeof (barrier)); + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.oldLayout = (VkImageLayout)packed[0]; + barrier.newLayout = (VkImageLayout)packed[1]; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow); + barrier.srcAccessMask = (VkAccessFlags)packed[4]; + barrier.dstAccessMask = (VkAccessFlags)packed[5]; + barrier.subresourceRange.aspectMask = (VkImageAspectFlags)packed[6]; + barrier.subresourceRange.baseMipLevel = (uint32_t)packed[7]; + barrier.subresourceRange.levelCount = (uint32_t)packed[8]; + barrier.subresourceRange.baseArrayLayer = (uint32_t)packed[9]; + barrier.subresourceRange.layerCount = (uint32_t)packed[10]; + + vkCmdPipelineBarrier (commandBuffer, (VkPipelineStageFlags)packed[2], (VkPipelineStageFlags)packed[3], 0, 0, 0, 0, 0, 1, &barrier); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - int lime_key_code_to_scan_code (int keyCode) { + bool lime_vk_cmd_clear_color_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int imageHigh, int imageLow, int layout, int aspectMask, value clear) { - return KeyCode::ToScanCode (keyCode); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdClearColorImage vkCmdClearColorImage = + (PFN_vkCmdClearColorImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdClearColorImage"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector clearValues = GetVulkanDoubleVector (clear); + if (!vkCmdClearColorImage || !commandBuffer || clearValues.size () < 4) return false; + + VkClearColorValue color; + color.float32[0] = (float)clearValues[0]; + color.float32[1] = (float)clearValues[1]; + color.float32[2] = (float)clearValues[2]; + color.float32[3] = (float)clearValues[3]; + VkImageSubresourceRange range; + memset (&range, 0, sizeof (range)); + range.aspectMask = (VkImageAspectFlags)aspectMask; + range.levelCount = 1; + range.layerCount = 1; + vkCmdClearColorImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)layout, &color, 1, &range); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM int HL_NAME(hl_key_code_to_scan_code) (int keyCode) { + HL_PRIM bool HL_NAME(hl_vk_cmd_clear_color_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, int layout, int aspectMask, hl_varray* clear) { - return KeyCode::ToScanCode (keyCode); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdClearColorImage vkCmdClearColorImage = + (PFN_vkCmdClearColorImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdClearColorImage"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector clearValues = GetHLVulkanDoubleVector (clear); + if (!vkCmdClearColorImage || !commandBuffer || clearValues.size () < 4) return false; + + VkClearColorValue color; + color.float32[0] = (float)clearValues[0]; + color.float32[1] = (float)clearValues[1]; + color.float32[2] = (float)clearValues[2]; + color.float32[3] = (float)clearValues[3]; + VkImageSubresourceRange range; + memset (&range, 0, sizeof (range)); + range.aspectMask = (VkImageAspectFlags)aspectMask; + range.levelCount = 1; + range.layerCount = 1; + vkCmdClearColorImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)layout, &color, 1, &range); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - void lime_key_event_manager_register (value callback, value eventObject) { + bool lime_vk_cmd_clear_depth_stencil_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, value state, value clear) { - KeyEvent::callback = new ValuePointer (callback); - KeyEvent::eventObject = new ValuePointer (eventObject); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdClearDepthStencilImage vkCmdClearDepthStencilImage = + (PFN_vkCmdClearDepthStencilImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdClearDepthStencilImage"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + std::vector clearValues = GetVulkanDoubleVector (clear); + if (!vkCmdClearDepthStencilImage || !commandBuffer || packed.size () < 7 || clearValues.size () < 1) return false; + + VkClearDepthStencilValue depthStencil; + depthStencil.depth = (float)clearValues[0]; + depthStencil.stencil = (uint32_t)packed[1]; + VkImageSubresourceRange range; + memset (&range, 0, sizeof (range)); + range.aspectMask = (VkImageAspectFlags)packed[2]; + range.baseMipLevel = (uint32_t)packed[3]; + range.levelCount = (uint32_t)packed[4]; + range.baseArrayLayer = (uint32_t)packed[5]; + range.layerCount = (uint32_t)packed[6]; + vkCmdClearDepthStencilImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)packed[0], + &depthStencil, 1, &range); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM void HL_NAME(hl_key_event_manager_register) (vclosure* callback, KeyEvent* eventObject) { + HL_PRIM bool HL_NAME(hl_vk_cmd_clear_depth_stencil_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, hl_varray* state, hl_varray* clear) { - KeyEvent::callback = new ValuePointer (callback); - KeyEvent::eventObject = new ValuePointer ((vobj*)eventObject); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdClearDepthStencilImage vkCmdClearDepthStencilImage = + (PFN_vkCmdClearDepthStencilImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdClearDepthStencilImage"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + std::vector clearValues = GetHLVulkanDoubleVector (clear); + if (!vkCmdClearDepthStencilImage || !commandBuffer || packed.size () < 7 || clearValues.size () < 1) return false; + + VkClearDepthStencilValue depthStencil; + depthStencil.depth = (float)clearValues[0]; + depthStencil.stencil = (uint32_t)packed[1]; + VkImageSubresourceRange range; + memset (&range, 0, sizeof (range)); + range.aspectMask = (VkImageAspectFlags)packed[2]; + range.baseMipLevel = (uint32_t)packed[3]; + range.levelCount = (uint32_t)packed[4]; + range.baseArrayLayer = (uint32_t)packed[5]; + range.layerCount = (uint32_t)packed[6]; + vkCmdClearDepthStencilImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (imageHigh, imageLow), (VkImageLayout)packed[0], + &depthStencil, 1, &range); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - value lime_locale_get_system_locale () { - - std::string* locale = Locale::GetSystemLocale (); + bool lime_vk_cmd_clear_attachments (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, value state, value clear) { - if (!locale) { +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdClearAttachments vkCmdClearAttachments = + (PFN_vkCmdClearAttachments)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdClearAttachments"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + std::vector clearValues = GetVulkanDoubleVector (clear); + if (!vkCmdClearAttachments || !commandBuffer || packed.size () < 8 || clearValues.size () < 5) return false; + + VkClearAttachment attachments[2]; + memset (attachments, 0, sizeof (attachments)); + uint32_t attachmentCount = 0; + + if (packed[0] != 0) { + + attachments[attachmentCount].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + attachments[attachmentCount].colorAttachment = 0; + attachments[attachmentCount].clearValue.color.float32[0] = (float)clearValues[0]; + attachments[attachmentCount].clearValue.color.float32[1] = (float)clearValues[1]; + attachments[attachmentCount].clearValue.color.float32[2] = (float)clearValues[2]; + attachments[attachmentCount].clearValue.color.float32[3] = (float)clearValues[3]; + attachmentCount++; - return alloc_null (); + } - } else { + if (packed[1] != 0 || packed[2] != 0) { - value result = alloc_string (locale->c_str ()); - delete locale; - return result; + attachments[attachmentCount].aspectMask = 0; + if (packed[1] != 0) attachments[attachmentCount].aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; + if (packed[2] != 0) attachments[attachmentCount].aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + attachments[attachmentCount].clearValue.depthStencil.depth = (float)clearValues[4]; + attachments[attachmentCount].clearValue.depthStencil.stencil = (uint32_t)packed[7]; + attachmentCount++; } - } - + if (attachmentCount == 0) return true; + + VkClearRect rect; + memset (&rect, 0, sizeof (rect)); + rect.rect.offset.x = packed[3]; + rect.rect.offset.y = packed[4]; + rect.rect.extent.width = (uint32_t)packed[5]; + rect.rect.extent.height = (uint32_t)packed[6]; + rect.baseArrayLayer = 0; + rect.layerCount = 1; + vkCmdClearAttachments (commandBuffer, attachmentCount, attachments, 1, &rect); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif - HL_PRIM vbyte* HL_NAME(hl_locale_get_system_locale) () { + } - std::string* locale = Locale::GetSystemLocale (); - if (!locale) { + HL_PRIM bool HL_NAME(hl_vk_cmd_clear_attachments) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, hl_varray* state, hl_varray* clear) { - return 0; +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdClearAttachments vkCmdClearAttachments = + (PFN_vkCmdClearAttachments)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdClearAttachments"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + std::vector clearValues = GetHLVulkanDoubleVector (clear); + if (!vkCmdClearAttachments || !commandBuffer || packed.size () < 8 || clearValues.size () < 5) return false; + + VkClearAttachment attachments[2]; + memset (attachments, 0, sizeof (attachments)); + uint32_t attachmentCount = 0; + + if (packed[0] != 0) { + + attachments[attachmentCount].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + attachments[attachmentCount].colorAttachment = 0; + attachments[attachmentCount].clearValue.color.float32[0] = (float)clearValues[0]; + attachments[attachmentCount].clearValue.color.float32[1] = (float)clearValues[1]; + attachments[attachmentCount].clearValue.color.float32[2] = (float)clearValues[2]; + attachments[attachmentCount].clearValue.color.float32[3] = (float)clearValues[3]; + attachmentCount++; - } else { + } - int size = locale->size (); - char* _locale = (char*)malloc (size + 1); - strncpy (_locale, locale->c_str (), size); - _locale[size] = '\0'; - delete locale; + if (packed[1] != 0 || packed[2] != 0) { - return (vbyte*)_locale; + attachments[attachmentCount].aspectMask = 0; + if (packed[1] != 0) attachments[attachmentCount].aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; + if (packed[2] != 0) attachments[attachmentCount].aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + attachments[attachmentCount].clearValue.depthStencil.depth = (float)clearValues[4]; + attachments[attachmentCount].clearValue.depthStencil.stencil = (uint32_t)packed[7]; + attachmentCount++; } - } - + if (attachmentCount == 0) return true; + + VkClearRect rect; + memset (&rect, 0, sizeof (rect)); + rect.rect.offset.x = packed[3]; + rect.rect.offset.y = packed[4]; + rect.rect.extent.width = (uint32_t)packed[5]; + rect.rect.extent.height = (uint32_t)packed[6]; + rect.baseArrayLayer = 0; + rect.layerCount = 1; + vkCmdClearAttachments (commandBuffer, attachmentCount, attachments, 1, &rect); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif - value lime_lzma_compress (value buffer, value bytes) { + } - #ifdef LIME_LZMA - Bytes data (buffer); - Bytes result (bytes); - LZMA::Compress (&data, &result); + bool lime_vk_cmd_blit_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, value state) { - return result.Value (bytes); - #else - return alloc_null (); - #endif +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBlitImage vkCmdBlitImage = (PFN_vkCmdBlitImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBlitImage"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetVulkanIntVector (state); + if (!vkCmdBlitImage || !commandBuffer || packed.size () < 21) return false; + + VkImageBlit blit; + memset (&blit, 0, sizeof (blit)); + blit.srcOffsets[0].x = packed[0]; + blit.srcOffsets[0].y = packed[1]; + blit.srcOffsets[0].z = packed[2]; + blit.srcOffsets[1].x = packed[3]; + blit.srcOffsets[1].y = packed[4]; + blit.srcOffsets[1].z = packed[5]; + blit.dstOffsets[0].x = packed[6]; + blit.dstOffsets[0].y = packed[7]; + blit.dstOffsets[0].z = packed[8]; + blit.dstOffsets[1].x = packed[9]; + blit.dstOffsets[1].y = packed[10]; + blit.dstOffsets[1].z = packed[11]; + int sourceLayout = packed[12]; + int destinationLayout = packed[13]; + int filter = packed[14]; + blit.srcSubresource.mipLevel = (uint32_t)packed[15]; + blit.dstSubresource.mipLevel = (uint32_t)packed[16]; + blit.srcSubresource.baseArrayLayer = (uint32_t)packed[17]; + blit.dstSubresource.baseArrayLayer = (uint32_t)packed[18]; + blit.srcSubresource.layerCount = (uint32_t)packed[19]; + blit.dstSubresource.layerCount = (uint32_t)packed[19]; + blit.srcSubresource.aspectMask = (VkImageAspectFlags)packed[20]; + blit.dstSubresource.aspectMask = (VkImageAspectFlags)packed[20]; + vkCmdBlitImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (sourceHigh, sourceLow), (VkImageLayout)sourceLayout, + (VkImage)(uintptr_t)CombineVulkanHandle (destinationHigh, destinationLow), (VkImageLayout)destinationLayout, 1, &blit, + (VkFilter)filter); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM Bytes* HL_NAME(hl_lzma_compress) (Bytes* buffer, Bytes* bytes) { + HL_PRIM bool HL_NAME(hl_vk_cmd_blit_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, hl_varray* state) { - #ifdef LIME_LZMA - LZMA::Compress (buffer, bytes); - return bytes; - #else - return 0; - #endif +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdBlitImage vkCmdBlitImage = (PFN_vkCmdBlitImage)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdBlitImage"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + std::vector packed = GetHLVulkanIntVector (state); + if (!vkCmdBlitImage || !commandBuffer || packed.size () < 21) return false; + + VkImageBlit blit; + memset (&blit, 0, sizeof (blit)); + blit.srcOffsets[0].x = packed[0]; + blit.srcOffsets[0].y = packed[1]; + blit.srcOffsets[0].z = packed[2]; + blit.srcOffsets[1].x = packed[3]; + blit.srcOffsets[1].y = packed[4]; + blit.srcOffsets[1].z = packed[5]; + blit.dstOffsets[0].x = packed[6]; + blit.dstOffsets[0].y = packed[7]; + blit.dstOffsets[0].z = packed[8]; + blit.dstOffsets[1].x = packed[9]; + blit.dstOffsets[1].y = packed[10]; + blit.dstOffsets[1].z = packed[11]; + int sourceLayout = packed[12]; + int destinationLayout = packed[13]; + int filter = packed[14]; + blit.srcSubresource.mipLevel = (uint32_t)packed[15]; + blit.dstSubresource.mipLevel = (uint32_t)packed[16]; + blit.srcSubresource.baseArrayLayer = (uint32_t)packed[17]; + blit.dstSubresource.baseArrayLayer = (uint32_t)packed[18]; + blit.srcSubresource.layerCount = (uint32_t)packed[19]; + blit.dstSubresource.layerCount = (uint32_t)packed[19]; + blit.srcSubresource.aspectMask = (VkImageAspectFlags)packed[20]; + blit.dstSubresource.aspectMask = (VkImageAspectFlags)packed[20]; + vkCmdBlitImage (commandBuffer, (VkImage)(uintptr_t)CombineVulkanHandle (sourceHigh, sourceLow), (VkImageLayout)sourceLayout, + (VkImage)(uintptr_t)CombineVulkanHandle (destinationHigh, destinationLow), (VkImageLayout)destinationLayout, 1, &blit, + (VkFilter)filter); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - value lime_lzma_decompress (value buffer, value bytes) { - - #ifdef LIME_LZMA - Bytes data (buffer); - Bytes result (bytes); + bool lime_vk_cmd_push_constants (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int layoutHigh, int layoutLow, value state, value bytes) { - LZMA::Decompress (&data, &result); +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)val_data (window); + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdPushConstants vkCmdPushConstants = + (PFN_vkCmdPushConstants)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdPushConstants"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + std::vector packed = GetVulkanIntVector (state); + Bytes data (bytes); + if (!vkCmdPushConstants || !commandBuffer || !layout || !data.b || packed.size () < 4) return false; + if (packed[2] < 0 || packed[3] < 0 || packed[2] + packed[3] > data.length) return false; - return result.Value (bytes); - #else - return alloc_null (); - #endif + vkCmdPushConstants (commandBuffer, layout, (VkShaderStageFlags)packed[0], (uint32_t)packed[1], (uint32_t)packed[3], data.b + packed[2]); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - HL_PRIM Bytes* HL_NAME(hl_lzma_decompress) (Bytes* buffer, Bytes* bytes) { + HL_PRIM bool HL_NAME(hl_vk_cmd_push_constants) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, hl_varray* state, Bytes* bytes) { - #ifdef LIME_LZMA - LZMA::Decompress (buffer, bytes); - return bytes; - #else - return 0; - #endif +#ifdef LIME_VULKAN + Window* targetWindow = (Window*)window->ptr; + VkInstance instance = (VkInstance)(uintptr_t)CombineVulkanHandle (instanceHigh, instanceLow); + VkDevice device = (VkDevice)(uintptr_t)CombineVulkanHandle (deviceHigh, deviceLow); + PFN_vkCmdPushConstants vkCmdPushConstants = + (PFN_vkCmdPushConstants)GetManagedVulkanDeviceProc (targetWindow, instance, device, "vkCmdPushConstants"); + VkCommandBuffer commandBuffer = (VkCommandBuffer)(uintptr_t)CombineVulkanHandle (commandBufferHigh, commandBufferLow); + VkPipelineLayout layout = (VkPipelineLayout)(uintptr_t)CombineVulkanHandle (layoutHigh, layoutLow); + std::vector packed = GetHLVulkanIntVector (state); + if (!vkCmdPushConstants || !commandBuffer || !layout || !bytes || !bytes->b || packed.size () < 4) return false; + if (packed[2] < 0 || packed[3] < 0 || packed[2] + packed[3] > bytes->length) return false; + + vkCmdPushConstants (commandBuffer, layout, (VkShaderStageFlags)packed[0], (uint32_t)packed[1], (uint32_t)packed[3], bytes->b + packed[2]); + return true; +#else + lastVKError = "Lime was built without lime-vulkan support"; + return false; +#endif } - void lime_mouse_event_manager_register (value callback, value eventObject) { + bool lime_vulkan_renderer_set_overlay (value handle, value bytes, int width, int height, int x, int y) { - MouseEvent::callback = new ValuePointer (callback); - MouseEvent::eventObject = new ValuePointer (eventObject); + if (val_is_null (handle)) return false; + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + Bytes data (bytes); + bool result = renderer->SetOverlay (data.b, width, height, x, y); + lastVulkanRendererError = renderer->GetLastError (); + return result; } - HL_PRIM void HL_NAME(hl_mouse_event_manager_register) (vclosure* callback, MouseEvent* eventObject) { + HL_PRIM bool HL_NAME(hl_vulkan_renderer_set_overlay) (HL_CFFIPointer* handle, Bytes* bytes, int width, int height, int x, int y) { - MouseEvent::callback = new ValuePointer (callback); - MouseEvent::eventObject = new ValuePointer ((vobj*)eventObject); + if (!handle || !handle->ptr) return false; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + bool result = renderer->SetOverlay (bytes ? bytes->b : 0, width, height, x, y); + lastVulkanRendererError = renderer->GetLastError (); + return result; } - void lime_neko_execute (HxString module) { + bool lime_vulkan_renderer_clear_overlay (value handle) { - #ifdef LIME_NEKO - NekoVM::Execute (module.c_str ()); - #endif + if (val_is_null (handle)) return false; + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + bool result = renderer->ClearOverlay (); + lastVulkanRendererError = renderer->GetLastError (); + return result; } - void lime_orientation_event_manager_register (value callback, value eventObject) { + HL_PRIM bool HL_NAME(hl_vulkan_renderer_clear_overlay) (HL_CFFIPointer* handle) { - OrientationEvent::callback = new ValuePointer (callback); - OrientationEvent::eventObject = new ValuePointer (eventObject); - System::EnableDeviceOrientationChange(true); + if (!handle || !handle->ptr) return false; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + bool result = renderer->ClearOverlay (); + lastVulkanRendererError = renderer->GetLastError (); + return result; } - HL_PRIM void HL_NAME(hl_orientation_event_manager_register) (vclosure* callback, OrientationEvent* eventObject) { + bool lime_vulkan_renderer_render (value handle, double red, double green, double blue, double alpha) { - OrientationEvent::callback = new ValuePointer (callback); - OrientationEvent::eventObject = new ValuePointer ((vobj*)eventObject); + if (val_is_null (handle)) return false; + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + bool result = renderer->Render (red, green, blue, alpha); + lastVulkanRendererError = renderer->GetLastError (); + return result; } - value lime_png_decode_bytes (value data, bool decodeData, value buffer) { + HL_PRIM bool HL_NAME(hl_vulkan_renderer_render) (HL_CFFIPointer* handle, double red, double green, double blue, double alpha) { - ImageBuffer imageBuffer (buffer); - Bytes bytes (data); - Resource resource = Resource (&bytes); + if (!handle || !handle->ptr) return false; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + bool result = renderer->Render (red, green, blue, alpha); + lastVulkanRendererError = renderer->GetLastError (); + return result; - #ifdef LIME_PNG - if (PNG::Decode (&resource, &imageBuffer, decodeData)) { + } - return imageBuffer.Value (buffer); - } - #endif + bool lime_vulkan_renderer_resize (value handle) { - return alloc_null (); + if (val_is_null (handle)) return false; + VulkanRenderer* renderer = (VulkanRenderer*)val_data (handle); + bool result = renderer->Resize (); + lastVulkanRendererError = renderer->GetLastError (); + return result; } - HL_PRIM ImageBuffer* HL_NAME(hl_png_decode_bytes) (Bytes* data, bool decodeData, ImageBuffer* buffer) { - - Resource resource = Resource (data); - - #ifdef LIME_PNG - if (PNG::Decode (&resource, buffer, decodeData)) { + HL_PRIM bool HL_NAME(hl_vulkan_renderer_resize) (HL_CFFIPointer* handle) { - return buffer; + if (!handle || !handle->ptr) return false; + VulkanRenderer* renderer = (VulkanRenderer*)handle->ptr; + bool result = renderer->Resize (); + lastVulkanRendererError = renderer->GetLastError (); + return result; - } - #endif + } +#else + static inline bool LimeVulkanUnavailableBool () { - return 0; + lastVKError = "Lime was built without lime-vulkan support"; + return false; } - value lime_png_decode_file (HxString path, bool decodeData, value buffer) { + static inline value LimeVulkanUnavailableValue () { - ImageBuffer imageBuffer (buffer); - Resource resource = Resource (hxs_utf8 (path, nullptr)); + lastVKError = "Lime was built without lime-vulkan support"; + return alloc_null (); - #ifdef LIME_PNG - if (PNG::Decode (&resource, &imageBuffer, decodeData)) { + } - return imageBuffer.Value (buffer); - } - #endif + static inline vdynamic* HLLimeVulkanUnavailableValue () { - return alloc_null (); + lastVKError = "Lime was built without lime-vulkan support"; + return 0; } - HL_PRIM ImageBuffer* HL_NAME(hl_png_decode_file) (hl_vstring* path, bool decodeData, ImageBuffer* buffer) { + static inline void LimeVulkanUnavailableVoid () { - Resource resource = Resource (path); + lastVKError = "Lime was built without lime-vulkan support"; - #ifdef LIME_PNG - if (PNG::Decode (&resource, buffer, decodeData)) { + } - return buffer; - } - #endif + bool lime_vk_update_descriptor_set_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int setHigh, + int setLow, int binding, int descriptorType, int bufferHigh, int bufferLow, int offset, int range) { - return 0; + return LimeVulkanUnavailableBool (); } - void lime_render_event_manager_register (value callback, value eventObject) { + HL_PRIM bool HL_NAME(hl_vk_update_descriptor_set_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int setHigh, int setLow, int binding, int descriptorType, int bufferHigh, int bufferLow, int offset, int range) { - RenderEvent::callback = new ValuePointer (callback); - RenderEvent::eventObject = new ValuePointer (eventObject); + return LimeVulkanUnavailableBool (); } - HL_PRIM void HL_NAME(hl_render_event_manager_register) (vclosure* callback, RenderEvent* eventObject) { + bool lime_vk_update_descriptor_sets (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value writes) { - RenderEvent::callback = new ValuePointer (callback); - RenderEvent::eventObject = new ValuePointer ((vobj*)eventObject); + return LimeVulkanUnavailableBool (); } - void lime_sensor_event_manager_register (value callback, value eventObject) { + HL_PRIM bool HL_NAME(hl_vk_update_descriptor_sets) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, hl_varray* writes) { - SensorEvent::callback = new ValuePointer (callback); - SensorEvent::eventObject = new ValuePointer (eventObject); + return LimeVulkanUnavailableBool (); } - HL_PRIM void HL_NAME(hl_sensor_event_manager_register) (vclosure* callback, SensorEvent* eventObject) { + value lime_vk_create_pipeline_layout (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value setLayouts, + int pushConstantStages, int pushConstantSize) { - SensorEvent::callback = new ValuePointer (callback); - SensorEvent::eventObject = new ValuePointer ((vobj*)eventObject); + return LimeVulkanUnavailableValue (); } - bool lime_system_get_allow_screen_timeout () { + HL_PRIM vdynamic* HL_NAME(hl_vk_create_pipeline_layout) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, hl_varray* setLayouts, int pushConstantStages, int pushConstantSize) { - return System::GetAllowScreenTimeout (); + return HLLimeVulkanUnavailableValue (); } - HL_PRIM bool HL_NAME(hl_system_get_allow_screen_timeout) () { + void lime_vk_destroy_pipeline_layout (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int layoutHigh, + int layoutLow) { - return System::GetAllowScreenTimeout (); + LimeVulkanUnavailableVoid (); } - value lime_system_get_device_model () { - - std::wstring* model = System::GetDeviceModel (); + HL_PRIM void HL_NAME(hl_vk_destroy_pipeline_layout) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int layoutHigh, int layoutLow) { - if (model) { + LimeVulkanUnavailableVoid (); - value result = alloc_wstring (model->c_str ()); - delete model; - return result; + } - } else { - return alloc_null (); + value lime_vk_create_pipeline_cache (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, value bytes, int byteOffset, + int byteLength) { - } + return LimeVulkanUnavailableValue (); } - HL_PRIM vbyte* HL_NAME(hl_system_get_device_model) () { - - #ifndef EMSCRIPTEN - - std::wstring* model = System::GetDeviceModel (); + HL_PRIM vdynamic* HL_NAME(hl_vk_create_pipeline_cache) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, Bytes* bytes, int byteOffset, int byteLength) { - if (model) { + return HLLimeVulkanUnavailableValue (); - vbyte* const result = hl_wstring_to_utf8_bytes (*model); - delete model; - return result; + } - } - #endif + void lime_vk_destroy_pipeline_cache (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int cacheHigh, + int cacheLow) { - return 0; + LimeVulkanUnavailableVoid (); } - value lime_system_get_device_vendor () { - - std::wstring* vendor = System::GetDeviceVendor (); + HL_PRIM void HL_NAME(hl_vk_destroy_pipeline_cache) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int cacheHigh, int cacheLow) { - if (vendor) { + LimeVulkanUnavailableVoid (); - value result = alloc_wstring (vendor->c_str ()); - delete vendor; - return result; + } - } else { - return alloc_null (); + bool lime_vk_get_pipeline_cache_data (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int cacheHigh, + int cacheLow, value bytes) { - } + return LimeVulkanUnavailableBool (); } - HL_PRIM vbyte* HL_NAME(hl_system_get_device_vendor) () { + HL_PRIM bool HL_NAME(hl_vk_get_pipeline_cache_data) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int cacheHigh, int cacheLow, Bytes* bytes) { - #ifndef EMSCRIPTEN + return LimeVulkanUnavailableBool (); - std::wstring* vendor = System::GetDeviceVendor (); + } - if (vendor) { - vbyte* const result = hl_wstring_to_utf8_bytes (*vendor); - delete vendor; - return result; + value lime_vk_create_graphics_pipeline (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int renderPassHigh, + int renderPassLow, int layoutHigh, int layoutLow, int vertexShaderHigh, int vertexShaderLow, int fragmentShaderHigh, int fragmentShaderLow, + value state) { - } + return LimeVulkanUnavailableValue (); - #endif + } - return 0; + + HL_PRIM vdynamic* HL_NAME(hl_vk_create_graphics_pipeline) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int renderPassHigh, int renderPassLow, int layoutHigh, int layoutLow, int vertexShaderHigh, int vertexShaderLow, + int fragmentShaderHigh, int fragmentShaderLow, hl_varray* state) { + + return HLLimeVulkanUnavailableValue (); } - value lime_system_get_directory (int type, HxString company, HxString title) { - - std::wstring* path = System::GetDirectory ((SystemDirectory)type, hxs_utf8 (company, nullptr), hxs_utf8 (title, nullptr)); + void lime_vk_destroy_pipeline (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int pipelineHigh, + int pipelineLow) { - if (path) { + LimeVulkanUnavailableVoid (); - value result = alloc_wstring (path->c_str ()); - delete path; - return result; + } - } else { - return alloc_null (); + HL_PRIM void HL_NAME(hl_vk_destroy_pipeline) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int pipelineHigh, int pipelineLow) { - } + LimeVulkanUnavailableVoid (); } - HL_PRIM vbyte* HL_NAME(hl_system_get_directory) (int type, hl_vstring* company, hl_vstring* title) { + bool lime_vk_queue_submit_synced (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int queueHigh, + int queueLow, int commandBufferHigh, int commandBufferLow, value state) { - #ifndef EMSCRIPTEN + return LimeVulkanUnavailableBool (); - std::wstring* path = System::GetDirectory ((SystemDirectory)type, company ? (char*)hl_to_utf8 ((const uchar*)company->bytes) : NULL, title ? (char*)hl_to_utf8 ((const uchar*)title->bytes) : NULL); + } - if (path) { - vbyte* const result = hl_wstring_to_utf8_bytes (*path); - delete path; - return result; + HL_PRIM bool HL_NAME(hl_vk_queue_submit_synced) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int queueHigh, int queueLow, int commandBufferHigh, int commandBufferLow, hl_varray* state) { - } + return LimeVulkanUnavailableBool (); - #endif + } - return 0; + + bool lime_vk_cmd_begin_render_pass (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int renderPassHigh, int renderPassLow, int framebufferHigh, int framebufferLow, value state, value clear) { + + return LimeVulkanUnavailableBool (); } - value lime_system_get_display (int id) { + HL_PRIM bool HL_NAME(hl_vk_cmd_begin_render_pass) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int renderPassHigh, int renderPassLow, int framebufferHigh, int framebufferLow, + hl_varray* state, hl_varray* clear) { - return (value)System::GetDisplay (true, id); + return LimeVulkanUnavailableBool (); } - HL_PRIM vdynamic* HL_NAME(hl_system_get_display) (int id) { + bool lime_vk_cmd_end_render_pass (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow) { - return (vdynamic*)System::GetDisplay (false, id); + return LimeVulkanUnavailableBool (); } - bool lime_system_get_ios_tablet () { + HL_PRIM bool HL_NAME(hl_vk_cmd_end_render_pass) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow) { - #ifdef IPHONE - return System::GetIOSTablet (); - #else - return false; - #endif + return LimeVulkanUnavailableBool (); } - HL_PRIM bool HL_NAME(hl_system_get_ios_tablet) () { + bool lime_vk_cmd_bind_pipeline (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int pipelineHigh, int pipelineLow, int bindPoint) { - #ifdef IPHONE - return System::GetIOSTablet (); - #else - return false; - #endif + return LimeVulkanUnavailableBool (); } - int lime_system_get_num_displays () { + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_pipeline) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int pipelineHigh, int pipelineLow, int bindPoint) { - return System::GetNumDisplays (); + return LimeVulkanUnavailableBool (); } - HL_PRIM int HL_NAME(hl_system_get_num_displays) () { + bool lime_vk_cmd_bind_descriptor_set (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, int bindPoint, int firstSet) { - return System::GetNumDisplays (); + return LimeVulkanUnavailableBool (); } - int lime_system_get_device_orientation () { + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_descriptor_set) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, int bindPoint, + int firstSet) { - return System::GetDeviceOrientation(); + return LimeVulkanUnavailableBool (); } - HL_PRIM int HL_NAME(hl_system_get_device_orientation) () { + bool lime_vk_cmd_bind_descriptor_set_ex (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, value state) { - return System::GetDeviceOrientation(); + return LimeVulkanUnavailableBool (); } - value lime_system_get_platform_label () { - - std::wstring* label = System::GetPlatformLabel (); + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_descriptor_set_ex) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, hl_varray* state) { - if (label) { + return LimeVulkanUnavailableBool (); - value result = alloc_wstring (label->c_str ()); - delete label; - return result; + } - } else { - return alloc_null (); + bool lime_vk_cmd_bind_descriptor_set_dynamic_offset (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, int dynamicOffset, int firstSet, + int bindPoint) { - } + return LimeVulkanUnavailableBool (); } - HL_PRIM vbyte* HL_NAME(hl_system_get_platform_label) () { + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_descriptor_set_dynamic_offset) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, + int deviceHigh, int deviceLow, int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, int setHigh, int setLow, + int dynamicOffset, int firstSet, int bindPoint) { - #ifndef EMSCRIPTEN + return LimeVulkanUnavailableBool (); - std::wstring* label = System::GetPlatformLabel (); + } - if (label) { - vbyte* const result = hl_wstring_to_utf8_bytes (*label); - delete label; - return result; + bool lime_vk_cmd_bind_vertex_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int bufferHigh, int bufferLow, int binding, int offsetHigh, int offsetLow) { - } + return LimeVulkanUnavailableBool (); - #endif + } - return 0; - } + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_vertex_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int binding, int offsetHigh, int offsetLow) { + return LimeVulkanUnavailableBool (); - value lime_system_get_platform_name () { + } - std::wstring* name = System::GetPlatformName (); - if (name) { + bool lime_vk_cmd_bind_index_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int indexType) { - value result = alloc_wstring (name->c_str ()); - delete name; - return result; + return LimeVulkanUnavailableBool (); - } else { + } - return 0; - } + HL_PRIM bool HL_NAME(hl_vk_cmd_bind_index_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int indexType) { + + return LimeVulkanUnavailableBool (); } - HL_PRIM vbyte* HL_NAME(hl_system_get_platform_name) () { + bool lime_vk_cmd_set_viewport (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, double x, double y, double width, double height, double minDepth, double maxDepth) { - #ifndef EMSCRIPTEN + return LimeVulkanUnavailableBool (); - std::wstring* name = System::GetPlatformName (); + } - if (name) { - vbyte* const result = hl_wstring_to_utf8_bytes (*name); - delete name; - return result; + HL_PRIM bool HL_NAME(hl_vk_cmd_set_viewport) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, double x, double y, double width, double height, double minDepth, double maxDepth) { - } + return LimeVulkanUnavailableBool (); - #endif + } - return 0; - } + bool lime_vk_cmd_set_scissor (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int x, int y, int width, int height) { + return LimeVulkanUnavailableBool (); - value lime_system_get_platform_version () { + } - std::wstring* version = System::GetPlatformVersion (); - if (version) { + HL_PRIM bool HL_NAME(hl_vk_cmd_set_scissor) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int x, int y, int width, int height) { - value result = alloc_wstring (version->c_str ()); - delete version; - return result; + return LimeVulkanUnavailableBool (); - } else { + } - return alloc_null (); - } + bool lime_vk_cmd_draw (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int vertexCount, int instanceCount, int firstVertex, int firstInstance) { - } + return LimeVulkanUnavailableBool (); + } - HL_PRIM vbyte* HL_NAME(hl_system_get_platform_version) () { - #ifndef EMSCRIPTEN + HL_PRIM bool HL_NAME(hl_vk_cmd_draw) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int vertexCount, int instanceCount, int firstVertex, int firstInstance) { - std::wstring* version = System::GetPlatformVersion (); + return LimeVulkanUnavailableBool (); - if (version) { + } - vbyte* const result = hl_wstring_to_utf8_bytes (*version); - delete version; - return result; - } - #endif + bool lime_vk_cmd_draw_indexed (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int indexCount, int instanceCount, int firstIndex, int vertexOffset, int firstInstance) { - return 0; + return LimeVulkanUnavailableBool (); } - double lime_system_get_timer () { + HL_PRIM bool HL_NAME(hl_vk_cmd_draw_indexed) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int indexCount, int instanceCount, int firstIndex, int vertexOffset, int firstInstance) { - return System::GetTimer (); + return LimeVulkanUnavailableBool (); } - HL_PRIM double HL_NAME(hl_system_get_timer) () { + bool lime_vk_cmd_draw_indirect (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, int stride) { - return System::GetTimer (); + return LimeVulkanUnavailableBool (); } - int lime_system_get_windows_console_mode (int handleType) { + HL_PRIM bool HL_NAME(hl_vk_cmd_draw_indirect) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, int stride) { - #if defined (HX_WINDOWS) && !defined (HX_WINRT) - return System::GetWindowsConsoleMode (handleType); - #else - return 0; - #endif + return LimeVulkanUnavailableBool (); } - HL_PRIM int HL_NAME(hl_system_get_windows_console_mode) (int handleType) { + bool lime_vk_cmd_draw_indexed_indirect (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, int stride) { - #if defined (HX_WINDOWS) && !defined (HX_WINRT) - return System::GetWindowsConsoleMode (handleType); - #else - return 0; - #endif + return LimeVulkanUnavailableBool (); } - void lime_system_open_file (HxString path) { + HL_PRIM bool HL_NAME(hl_vk_cmd_draw_indexed_indirect) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int offsetHigh, int offsetLow, int drawCount, + int stride) { - #ifdef IPHONE - System::OpenFile (path.c_str ()); - #endif + return LimeVulkanUnavailableBool (); } - HL_PRIM void HL_NAME(hl_system_open_file) (vbyte* path) { + bool lime_vk_cmd_copy_buffer (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, value state) { - #ifdef IPHONE - System::OpenFile ((char*)path); - #endif + return LimeVulkanUnavailableBool (); } - void lime_system_open_url (HxString url, HxString target) { + HL_PRIM bool HL_NAME(hl_vk_cmd_copy_buffer) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, hl_varray* state) { - #ifdef IPHONE - System::OpenURL (url.c_str (), target.c_str ()); - #endif + return LimeVulkanUnavailableBool (); } + bool lime_vk_cmd_copy_buffer_to_image_region (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, value state) { - HL_PRIM void HL_NAME(hl_system_open_url) (vbyte* url, vbyte* target) { - - #ifdef IPHONE - System::OpenURL ((char*)url, (char*)target); - #endif + return LimeVulkanUnavailableBool (); } - bool lime_system_set_allow_screen_timeout (bool allow) { + HL_PRIM bool HL_NAME(hl_vk_cmd_copy_buffer_to_image_region) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int bufferHigh, int bufferLow, int imageHigh, int imageLow, hl_varray* state) { - return System::SetAllowScreenTimeout (allow); + return LimeVulkanUnavailableBool (); } - HL_PRIM bool HL_NAME(hl_system_set_allow_screen_timeout) (bool allow) { + bool lime_vk_cmd_copy_image_to_buffer_region (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, int bufferHigh, int bufferLow, value state) { - return System::SetAllowScreenTimeout (allow); + return LimeVulkanUnavailableBool (); } - bool lime_system_set_windows_console_mode (int handleType, int mode) { + HL_PRIM bool HL_NAME(hl_vk_cmd_copy_image_to_buffer_region) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, int bufferHigh, int bufferLow, hl_varray* state) { - #if defined (HX_WINDOWS) && !defined (HX_WINRT) - return System::SetWindowsConsoleMode (handleType, mode); - #else - return false; - #endif + return LimeVulkanUnavailableBool (); } - HL_PRIM bool HL_NAME(hl_system_set_windows_console_mode) (int handleType, int mode) { + bool lime_vk_cmd_pipeline_barrier_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, value state) { - #if defined (HX_WINDOWS) && !defined (HX_WINRT) - return System::SetWindowsConsoleMode (handleType, mode); - #else - return false; - #endif + return LimeVulkanUnavailableBool (); } - void lime_text_event_manager_register (value callback, value eventObject) { + HL_PRIM bool HL_NAME(hl_vk_cmd_pipeline_barrier_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, hl_varray* state) { - TextEvent::callback = new ValuePointer (callback); - TextEvent::eventObject = new ValuePointer (eventObject); + return LimeVulkanUnavailableBool (); } - HL_PRIM void HL_NAME(hl_text_event_manager_register) (vclosure* callback, TextEvent* eventObject) { + bool lime_vk_cmd_clear_color_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int imageHigh, int imageLow, int layout, int aspectMask, value clear) { - TextEvent::callback = new ValuePointer (callback); - TextEvent::eventObject = new ValuePointer ((vobj*)eventObject); + return LimeVulkanUnavailableBool (); } - void lime_touch_event_manager_register (value callback, value eventObject) { + HL_PRIM bool HL_NAME(hl_vk_cmd_clear_color_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, int layout, int aspectMask, hl_varray* clear) { - TouchEvent::callback = new ValuePointer (callback); - TouchEvent::eventObject = new ValuePointer (eventObject); + return LimeVulkanUnavailableBool (); } - HL_PRIM void HL_NAME(hl_touch_event_manager_register) (vclosure* callback, TouchEvent* eventObject) { + bool lime_vk_cmd_clear_depth_stencil_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, value state, value clear) { - TouchEvent::callback = new ValuePointer (callback); - TouchEvent::eventObject = new ValuePointer ((vobj*)eventObject); + return LimeVulkanUnavailableBool (); } - void lime_window_alert (value window, HxString message, HxString title) { + HL_PRIM bool HL_NAME(hl_vk_cmd_clear_depth_stencil_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, int imageHigh, int imageLow, hl_varray* state, hl_varray* clear) { - Window* targetWindow = (Window*)val_data (window); - targetWindow->Alert (hxs_utf8 (message, nullptr), hxs_utf8 (title, nullptr)); + return LimeVulkanUnavailableBool (); } - HL_PRIM void HL_NAME(hl_window_alert) (HL_CFFIPointer* window, hl_vstring* message, hl_vstring* title) { + bool lime_vk_cmd_clear_attachments (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, value state, value clear) { - Window* targetWindow = (Window*)window->ptr; - const char *cmessage = message ? hl_to_utf8(message->bytes) : nullptr; - const char *ctitle = title ? hl_to_utf8(title->bytes) : nullptr; - targetWindow->Alert (cmessage, ctitle); + return LimeVulkanUnavailableBool (); } - void lime_window_close (value window) { + HL_PRIM bool HL_NAME(hl_vk_cmd_clear_attachments) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, + int deviceLow, int commandBufferHigh, int commandBufferLow, hl_varray* state, hl_varray* clear) { - Window* targetWindow = (Window*)val_data (window); - targetWindow->Close (); + return LimeVulkanUnavailableBool (); } - HL_PRIM void HL_NAME(hl_window_close) (HL_CFFIPointer* window) { + bool lime_vk_cmd_blit_image (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, value state) { - Window* targetWindow = (Window*)window->ptr; - targetWindow->Close (); + return LimeVulkanUnavailableBool (); } - void lime_window_context_flip (value window) { + HL_PRIM bool HL_NAME(hl_vk_cmd_blit_image) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int sourceHigh, int sourceLow, int destinationHigh, int destinationLow, hl_varray* state) { - ((Window*)val_data (window))->ContextFlip (); + return LimeVulkanUnavailableBool (); } - HL_PRIM void HL_NAME(hl_window_context_flip) (HL_CFFIPointer* window) { + bool lime_vk_cmd_push_constants (value window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, int commandBufferHigh, + int commandBufferLow, int layoutHigh, int layoutLow, value state, value bytes) { - ((Window*)window->ptr)->ContextFlip (); + return LimeVulkanUnavailableBool (); } - value lime_window_context_lock (value window) { + HL_PRIM bool HL_NAME(hl_vk_cmd_push_constants) (HL_CFFIPointer* window, int instanceHigh, int instanceLow, int deviceHigh, int deviceLow, + int commandBufferHigh, int commandBufferLow, int layoutHigh, int layoutLow, hl_varray* state, Bytes* bytes) { - return (value)((Window*)val_data (window))->ContextLock (true); + return LimeVulkanUnavailableBool (); } - HL_PRIM vdynamic* HL_NAME(hl_window_context_lock) (HL_CFFIPointer* window) { + value lime_vulkan_renderer_create (value window, HxString applicationName) { - return (vdynamic*)((Window*)window->ptr)->ContextLock (false); + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return alloc_null (); } - void lime_window_context_make_current (value window) { + HL_PRIM HL_CFFIPointer* HL_NAME(hl_vulkan_renderer_create) (HL_CFFIPointer* window, hl_vstring* applicationName) { - ((Window*)val_data (window))->ContextMakeCurrent (); + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return 0; } - HL_PRIM void HL_NAME(hl_window_context_make_current) (HL_CFFIPointer* window) { + void lime_vulkan_renderer_destroy (value handle) {} - ((Window*)window->ptr)->ContextMakeCurrent (); - } + HL_PRIM void HL_NAME(hl_vulkan_renderer_destroy) (HL_CFFIPointer* handle) {} - void lime_window_context_unlock (value window) { + value lime_vulkan_renderer_get_info (value handle) { - ((Window*)val_data (window))->ContextUnlock (); + return alloc_string (""); } - HL_PRIM void HL_NAME(hl_window_context_unlock) (HL_CFFIPointer* window) { + HL_PRIM vbyte* HL_NAME(hl_vulkan_renderer_get_info) (HL_CFFIPointer* handle) { - ((Window*)window->ptr)->ContextUnlock (); + return hl_copy_bytes ((const vbyte*)"", 1); } - value lime_window_create (value application, int width, int height, int flags, HxString title) { + value lime_vulkan_renderer_get_last_error () { - Window* window = CreateWindow ((Application*)val_data (application), width, height, flags, hxs_utf8 (title, nullptr)); - return CFFIPointer (window, gc_window); + return alloc_string (lastVulkanRendererError.c_str ()); } - HL_PRIM HL_CFFIPointer* HL_NAME(hl_window_create) (HL_CFFIPointer* application, int width, int height, int flags, hl_vstring* title) { + HL_PRIM vbyte* HL_NAME(hl_vulkan_renderer_get_last_error) () { - Window* window = CreateWindow ((Application*)application->ptr, width, height, flags, (const char*)hl_to_utf8 ((const uchar*)title->bytes)); - return HLCFFIPointer (window, (hl_finalizer)hl_gc_window); + return hl_copy_bytes ((const vbyte*)lastVulkanRendererError.c_str (), (int)lastVulkanRendererError.size () + 1); } - void lime_window_event_manager_register (value callback, value eventObject) { + bool lime_vulkan_renderer_set_overlay (value handle, value bytes, int width, int height, int x, int y) { - WindowEvent::callback = new ValuePointer (callback); - WindowEvent::eventObject = new ValuePointer (eventObject); + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; } - HL_PRIM void HL_NAME(hl_window_event_manager_register) (vclosure* callback, WindowEvent* eventObject) { + HL_PRIM bool HL_NAME(hl_vulkan_renderer_set_overlay) (HL_CFFIPointer* handle, Bytes* bytes, int width, int height, int x, int y) { - WindowEvent::callback = new ValuePointer (callback); - WindowEvent::eventObject = new ValuePointer ((vobj*)eventObject); + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; } - void lime_window_focus (value window) { + bool lime_vulkan_renderer_clear_overlay (value handle) { - Window* targetWindow = (Window*)val_data (window); - targetWindow->Focus (); + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; } - HL_PRIM void HL_NAME(hl_window_focus) (HL_CFFIPointer* window) { + HL_PRIM bool HL_NAME(hl_vulkan_renderer_clear_overlay) (HL_CFFIPointer* handle) { - Window* targetWindow = (Window*)window->ptr; - targetWindow->Focus (); + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; } - double lime_window_get_context (value window) { + bool lime_vulkan_renderer_render (value handle, double red, double green, double blue, double alpha) { - Window* targetWindow = (Window*)val_data (window); - return (uintptr_t)targetWindow->GetContext (); + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; } - HL_PRIM double HL_NAME(hl_window_get_context) (HL_CFFIPointer* window) { + HL_PRIM bool HL_NAME(hl_vulkan_renderer_render) (HL_CFFIPointer* handle, double red, double green, double blue, double alpha) { - Window* targetWindow = (Window*)window->ptr; - return (uintptr_t)targetWindow->GetContext (); + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; } - value lime_window_get_context_type (value window) { + bool lime_vulkan_renderer_resize (value handle) { - Window* targetWindow = (Window*)val_data (window); - const char* type = targetWindow->GetContextType (); - return type ? alloc_string (type) : alloc_null (); + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; } - HL_PRIM vbyte* HL_NAME(hl_window_get_context_type) (HL_CFFIPointer* window) { + HL_PRIM bool HL_NAME(hl_vulkan_renderer_resize) (HL_CFFIPointer* handle) { - Window* targetWindow = (Window*)window->ptr; - return (vbyte*)targetWindow->GetContextType (); + lastVulkanRendererError = "Lime was built without lime-vulkan support"; + return false; } +#endif int lime_window_get_display (value window) { @@ -4297,6 +13455,7 @@ namespace lime { DEFINE_PRIME1v (lime_window_focus); DEFINE_PRIME1 (lime_window_get_context); DEFINE_PRIME1 (lime_window_get_context_type); + DEFINE_PRIME3 (lime_window_create_vulkan_surface); DEFINE_PRIME1 (lime_window_get_display); DEFINE_PRIME1 (lime_window_get_display_mode); DEFINE_PRIME1 (lime_window_get_height); @@ -4304,6 +13463,114 @@ namespace lime { DEFINE_PRIME1 (lime_window_get_mouse_lock); DEFINE_PRIME1 (lime_window_get_scale); DEFINE_PRIME1 (lime_window_get_text_input_enabled); + DEFINE_PRIME1 (lime_window_get_vulkan_drawable_size); + DEFINE_PRIME1 (lime_window_get_vulkan_instance_extensions); + DEFINE_PRIME1 (lime_window_get_vulkan_instance_proc_addr); + DEFINE_PRIME2 (lime_vk_create_instance); + DEFINE_PRIME3v (lime_vk_destroy_instance); + DEFINE_PRIME5v (lime_vk_destroy_surface); + DEFINE_PRIME5 (lime_vk_get_physical_devices); + DEFINE_PRIME7 (lime_vk_create_device); + DEFINE_PRIME5v (lime_vk_destroy_device); + DEFINE_PRIME5 (lime_vk_device_wait_idle); + DEFINE_PRIME7 (lime_vk_queue_wait_idle); + DEFINE_PRIME7 (lime_vk_create_command_pool); + DEFINE_PRIME7v (lime_vk_destroy_command_pool); + DEFINE_PRIME8 (lime_vk_reset_command_pool); + DEFINE_PRIME8 (lime_vk_allocate_command_buffer); + DEFINE_PRIME9v (lime_vk_free_command_buffer); + DEFINE_PRIME8 (lime_vk_begin_command_buffer); + DEFINE_PRIME7 (lime_vk_end_command_buffer); + DEFINE_PRIME8 (lime_vk_reset_command_buffer); + DEFINE_PRIME5 (lime_vk_create_semaphore); + DEFINE_PRIME7v (lime_vk_destroy_semaphore); + DEFINE_PRIME6 (lime_vk_create_fence); + DEFINE_PRIME7v (lime_vk_destroy_fence); + DEFINE_PRIME9 (lime_vk_wait_for_fence); + DEFINE_PRIME7 (lime_vk_reset_fence); + DEFINE_PRIME11 (lime_vk_queue_submit); + DEFINE_PRIME11 (lime_vk_allocate_memory); + DEFINE_PRIME7v (lime_vk_free_memory); + DEFINE_PRIME12 (lime_vk_upload_memory); + DEFINE_PRIME12 (lime_vk_download_memory); + DEFINE_PRIME12 (lime_vk_map_memory); + DEFINE_PRIME7v (lime_vk_unmap_memory); + DEFINE_PRIME12 (lime_vk_write_mapped_memory); + DEFINE_PRIME11 (lime_vk_flush_mapped_memory); + DEFINE_PRIME11 (lime_vk_invalidate_mapped_memory); + DEFINE_PRIME8 (lime_vk_create_buffer); + DEFINE_PRIME7v (lime_vk_destroy_buffer); + DEFINE_PRIME7 (lime_vk_get_buffer_memory_requirements); + DEFINE_PRIME11 (lime_vk_bind_buffer_memory); + DEFINE_PRIME15 (lime_vk_create_image); + DEFINE_PRIME7v (lime_vk_destroy_image); + DEFINE_PRIME7 (lime_vk_get_image_memory_requirements); + DEFINE_PRIME11 (lime_vk_bind_image_memory); + DEFINE_PRIME15 (lime_vk_create_swapchain); + DEFINE_PRIME7v (lime_vk_destroy_swapchain); + DEFINE_PRIME7 (lime_vk_get_swapchain_images); + DEFINE_PRIME13 (lime_vk_acquire_next_image); + DEFINE_PRIME12 (lime_vk_queue_present); + DEFINE_PRIME10 (lime_vk_create_image_view); + DEFINE_PRIME7v (lime_vk_destroy_image_view); + DEFINE_PRIME14 (lime_vk_create_image_view_ex); + DEFINE_PRIME6 (lime_vk_create_render_pass); + DEFINE_PRIME7v (lime_vk_destroy_render_pass); + DEFINE_PRIME11 (lime_vk_create_framebuffer); + DEFINE_PRIME7v (lime_vk_destroy_framebuffer); + DEFINE_PRIME8 (lime_vk_create_shader_module); + DEFINE_PRIME7v (lime_vk_destroy_shader_module); + DEFINE_PRIME13 (lime_vk_create_sampler); + DEFINE_PRIME7v (lime_vk_destroy_sampler); + DEFINE_PRIME6 (lime_vk_create_descriptor_set_layout); + DEFINE_PRIME7v (lime_vk_destroy_descriptor_set_layout); + DEFINE_PRIME6 (lime_vk_create_descriptor_pool); + DEFINE_PRIME7v (lime_vk_destroy_descriptor_pool); + DEFINE_PRIME8 (lime_vk_reset_descriptor_pool); + DEFINE_PRIME9 (lime_vk_allocate_descriptor_set); + DEFINE_PRIME14 (lime_vk_update_descriptor_set_image); + DEFINE_PRIME13 (lime_vk_update_descriptor_set_buffer); + DEFINE_PRIME6 (lime_vk_update_descriptor_sets); + DEFINE_PRIME8 (lime_vk_create_pipeline_layout); + DEFINE_PRIME7v (lime_vk_destroy_pipeline_layout); + DEFINE_PRIME8 (lime_vk_create_pipeline_cache); + DEFINE_PRIME7v (lime_vk_destroy_pipeline_cache); + DEFINE_PRIME8 (lime_vk_get_pipeline_cache_data); + DEFINE_PRIME14 (lime_vk_create_graphics_pipeline); + DEFINE_PRIME7v (lime_vk_destroy_pipeline); + DEFINE_PRIME10 (lime_vk_queue_submit_synced); + DEFINE_PRIME13 (lime_vk_cmd_begin_render_pass); + DEFINE_PRIME7 (lime_vk_cmd_end_render_pass); + DEFINE_PRIME10 (lime_vk_cmd_bind_pipeline); + DEFINE_PRIME13 (lime_vk_cmd_bind_descriptor_set); + DEFINE_PRIME12 (lime_vk_cmd_bind_descriptor_set_ex); + DEFINE_PRIME14 (lime_vk_cmd_bind_descriptor_set_dynamic_offset); + DEFINE_PRIME12 (lime_vk_cmd_bind_vertex_buffer); + DEFINE_PRIME12 (lime_vk_cmd_bind_index_buffer); + DEFINE_PRIME13 (lime_vk_cmd_set_viewport); + DEFINE_PRIME11 (lime_vk_cmd_set_scissor); + DEFINE_PRIME11 (lime_vk_cmd_draw); + DEFINE_PRIME12 (lime_vk_cmd_draw_indexed); + DEFINE_PRIME13 (lime_vk_cmd_draw_indirect); + DEFINE_PRIME13 (lime_vk_cmd_draw_indexed_indirect); + DEFINE_PRIME12 (lime_vk_cmd_copy_buffer); + DEFINE_PRIME12 (lime_vk_cmd_copy_buffer_to_image_region); + DEFINE_PRIME12 (lime_vk_cmd_copy_image_to_buffer_region); + DEFINE_PRIME10 (lime_vk_cmd_pipeline_barrier_image); + DEFINE_PRIME12 (lime_vk_cmd_clear_color_image); + DEFINE_PRIME11 (lime_vk_cmd_clear_depth_stencil_image); + DEFINE_PRIME9 (lime_vk_cmd_clear_attachments); + DEFINE_PRIME12 (lime_vk_cmd_blit_image); + DEFINE_PRIME11 (lime_vk_cmd_push_constants); + DEFINE_PRIME0 (lime_vk_get_last_error); + DEFINE_PRIME2 (lime_vulkan_renderer_create); + DEFINE_PRIME1v (lime_vulkan_renderer_destroy); + DEFINE_PRIME1 (lime_vulkan_renderer_get_info); + DEFINE_PRIME0 (lime_vulkan_renderer_get_last_error); + DEFINE_PRIME6 (lime_vulkan_renderer_set_overlay); + DEFINE_PRIME1 (lime_vulkan_renderer_clear_overlay); + DEFINE_PRIME5 (lime_vulkan_renderer_render); + DEFINE_PRIME1 (lime_vulkan_renderer_resize); DEFINE_PRIME1 (lime_window_get_width); DEFINE_PRIME1 (lime_window_get_x); DEFINE_PRIME1 (lime_window_get_y); @@ -4341,9 +13608,9 @@ namespace lime { #define _TCLIPBOARD_EVENT _OBJ (_I32) #define _TDISPLAYMODE _OBJ (_I32 _I32 _I32 _I32) #define _TDROP_EVENT _OBJ (_BYTES _I32) - #define _TGAMEPAD_EVENT _OBJ (_I32 _I32 _I32 _I32 _F64) + #define _TGAMEPAD_EVENT _OBJ (_I32 _I32 _I32 _I32 _F64 _I32) #define _TJOYSTICK_EVENT _OBJ (_I32 _I32 _I32 _I32 _F64 _F64) - #define _TKEY_EVENT _OBJ (_F64 _I32 _I32 _I32) + #define _TKEY_EVENT _OBJ (_F64 _I32 _I32 _I32 _I32) #define _TMOUSE_EVENT _OBJ (_I32 _F64 _F64 _I32 _I32 _F64 _F64 _I32) #define _TORIENTATION_EVENT _OBJ (_I32 _I32 _I32) #define _TRECTANGLE _OBJ (_F64 _F64 _F64 _F64) @@ -4357,7 +13624,7 @@ namespace lime { #define _TARRAYBUFFER _TBYTES #define _TARRAYBUFFERVIEW _OBJ (_I32 _TARRAYBUFFER _I32 _I32 _I32 _I32) - #define _TAUDIOBUFFER _OBJ (_I32 _I32 _TARRAYBUFFERVIEW _I32 _DYN _DYN _DYN _DYN _BOOL _DYN _TBYTES _BOOL _I32 _STRING _TBYTES _STRING _TVORBISFILE) + #define _TAUDIOBUFFER _OBJ (_I32 _I32 _TARRAYBUFFERVIEW _I32 _DYN _DYN _I32 _DYN _DYN _BOOL _DYN _TBYTES _BOOL _I32 _STRING _TBYTES _STRING _TVORBISFILE) #define _TIMAGEBUFFER _OBJ (_I32 _TARRAYBUFFERVIEW _I32 _I32 _BOOL _BOOL _I32 _DYN _DYN _DYN _DYN _DYN _DYN) #define _TIMAGE _OBJ (_TIMAGEBUFFER _BOOL _I32 _I32 _I32 _TRECTANGLE _ENUM _I32 _I32 _F64 _F64) @@ -4496,6 +13763,7 @@ namespace lime { DEFINE_HL_PRIM (_VOID, hl_window_focus, _TCFFIPOINTER); DEFINE_HL_PRIM (_F64, hl_window_get_context, _TCFFIPOINTER); DEFINE_HL_PRIM (_BYTES, hl_window_get_context_type, _TCFFIPOINTER); + DEFINE_HL_PRIM (_DYN, hl_window_create_vulkan_surface, _TCFFIPOINTER _I32 _I32); DEFINE_HL_PRIM (_I32, hl_window_get_display, _TCFFIPOINTER); DEFINE_HL_PRIM (_VOID, hl_window_get_display_mode, _TCFFIPOINTER _TDISPLAYMODE); DEFINE_HL_PRIM (_I32, hl_window_get_height, _TCFFIPOINTER); @@ -4503,6 +13771,114 @@ namespace lime { DEFINE_HL_PRIM (_BOOL, hl_window_get_mouse_lock, _TCFFIPOINTER); DEFINE_HL_PRIM (_F64, hl_window_get_scale, _TCFFIPOINTER); DEFINE_HL_PRIM (_BOOL, hl_window_get_text_input_enabled, _TCFFIPOINTER); + DEFINE_HL_PRIM (_DYN, hl_window_get_vulkan_drawable_size, _TCFFIPOINTER); + DEFINE_HL_PRIM (_ARR, hl_window_get_vulkan_instance_extensions, _TCFFIPOINTER); + DEFINE_HL_PRIM (_DYN, hl_window_get_vulkan_instance_proc_addr, _TCFFIPOINTER); + DEFINE_HL_PRIM (_DYN, hl_vk_create_instance, _TCFFIPOINTER _STRING); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_instance, _TCFFIPOINTER _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_surface, _TCFFIPOINTER _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_ARR, hl_vk_get_physical_devices, _TCFFIPOINTER _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_device, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_device, _TCFFIPOINTER _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_device_wait_idle, _TCFFIPOINTER _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_queue_wait_idle, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_command_pool, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_command_pool, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_reset_command_pool, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_allocate_command_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_free_command_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_begin_command_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_end_command_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_reset_command_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_semaphore, _TCFFIPOINTER _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_semaphore, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_fence, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_fence, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_wait_for_fence, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_reset_fence, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_queue_submit, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_allocate_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_free_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_upload_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _TBYTES _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_download_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _TBYTES _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_map_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_unmap_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_write_mapped_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _TBYTES _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_flush_mapped_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_invalidate_mapped_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_get_buffer_memory_requirements, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_bind_buffer_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_get_image_memory_requirements, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_bind_image_memory, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_swapchain, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_swapchain, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_ARR, hl_vk_get_swapchain_images, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_acquire_next_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_I32, hl_vk_queue_present, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_image_view, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_image_view, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_image_view_ex, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_render_pass, _TCFFIPOINTER _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_render_pass, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_framebuffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _ARR _I32 _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_framebuffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_shader_module, _TCFFIPOINTER _I32 _I32 _I32 _I32 _TBYTES _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_shader_module, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_sampler, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _BOOL _F64 _I32 _F64 _F64); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_sampler, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_descriptor_set_layout, _TCFFIPOINTER _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_descriptor_set_layout, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_descriptor_pool, _TCFFIPOINTER _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_descriptor_pool, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_reset_descriptor_pool, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_allocate_descriptor_set, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_update_descriptor_set_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_update_descriptor_set_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_update_descriptor_sets, _TCFFIPOINTER _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_DYN, hl_vk_create_pipeline_layout, _TCFFIPOINTER _I32 _I32 _I32 _I32 _ARR _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_pipeline_layout, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_DYN, hl_vk_create_pipeline_cache, _TCFFIPOINTER _I32 _I32 _I32 _I32 _TBYTES _I32 _I32); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_pipeline_cache, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_get_pipeline_cache_data, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _TBYTES); + DEFINE_HL_PRIM (_DYN, hl_vk_create_graphics_pipeline, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_VOID, hl_vk_destroy_pipeline, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_queue_submit_synced, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_begin_render_pass, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_end_render_pass, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_bind_pipeline, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_bind_descriptor_set, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_bind_descriptor_set_ex, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_bind_descriptor_set_dynamic_offset, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_bind_vertex_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_bind_index_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_set_viewport, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _F64 _F64 _F64 _F64 _F64 _F64); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_set_scissor, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_draw, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_draw_indexed, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_draw_indirect, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_draw_indexed_indirect, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_copy_buffer, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_copy_buffer_to_image_region, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_copy_image_to_buffer_region, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_pipeline_barrier_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_clear_color_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_clear_depth_stencil_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_clear_attachments, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _ARR _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_blit_image, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR); + DEFINE_HL_PRIM (_BOOL, hl_vk_cmd_push_constants, _TCFFIPOINTER _I32 _I32 _I32 _I32 _I32 _I32 _I32 _I32 _ARR _TBYTES); + DEFINE_HL_PRIM (_BYTES, hl_vk_get_last_error, _NO_ARG); + DEFINE_HL_PRIM (_TCFFIPOINTER, hl_vulkan_renderer_create, _TCFFIPOINTER _STRING); + DEFINE_HL_PRIM (_VOID, hl_vulkan_renderer_destroy, _TCFFIPOINTER); + DEFINE_HL_PRIM (_BYTES, hl_vulkan_renderer_get_info, _TCFFIPOINTER); + DEFINE_HL_PRIM (_BYTES, hl_vulkan_renderer_get_last_error, _NO_ARG); + DEFINE_HL_PRIM (_BOOL, hl_vulkan_renderer_set_overlay, _TCFFIPOINTER _TBYTES _I32 _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_vulkan_renderer_clear_overlay, _TCFFIPOINTER); + DEFINE_HL_PRIM (_BOOL, hl_vulkan_renderer_render, _TCFFIPOINTER _F64 _F64 _F64 _F64); + DEFINE_HL_PRIM (_BOOL, hl_vulkan_renderer_resize, _TCFFIPOINTER); DEFINE_HL_PRIM (_I32, hl_window_get_width, _TCFFIPOINTER); DEFINE_HL_PRIM (_I32, hl_window_get_x, _TCFFIPOINTER); DEFINE_HL_PRIM (_I32, hl_window_get_y, _TCFFIPOINTER); diff --git a/project/src/backend/sdl/SDLApplication.cpp b/project/src/backend/sdl/SDLApplication.cpp index 821648774e..5b089f52b2 100644 --- a/project/src/backend/sdl/SDLApplication.cpp +++ b/project/src/backend/sdl/SDLApplication.cpp @@ -826,6 +826,7 @@ namespace lime gamepadEvent.type = GAMEPAD_AXIS_MOVE; gamepadEvent.axis = event->caxis.axis; gamepadEvent.id = event->caxis.which; + gamepadEvent.timestamp = event->common.timestamp; if (event->caxis.value > -analogAxisDeadZone && event->caxis.value < analogAxisDeadZone) { @@ -852,6 +853,7 @@ namespace lime gamepadEvent.type = GAMEPAD_BUTTON_DOWN; gamepadEvent.button = event->cbutton.button; gamepadEvent.id = event->cbutton.which; + gamepadEvent.timestamp = event->common.timestamp; GamepadEvent::Dispatch(&gamepadEvent); break; @@ -861,6 +863,7 @@ namespace lime gamepadEvent.type = GAMEPAD_BUTTON_UP; gamepadEvent.button = event->cbutton.button; gamepadEvent.id = event->cbutton.which; + gamepadEvent.timestamp = event->common.timestamp; GamepadEvent::Dispatch(&gamepadEvent); break; @@ -872,6 +875,7 @@ namespace lime gamepadEvent.type = GAMEPAD_CONNECT; gamepadEvent.id = SDLGamepad::GetInstanceID(event->cdevice.which); + gamepadEvent.timestamp = event->common.timestamp; GamepadEvent::Dispatch(&gamepadEvent); } @@ -883,6 +887,7 @@ namespace lime gamepadEvent.type = GAMEPAD_DISCONNECT; gamepadEvent.id = event->cdevice.which; + gamepadEvent.timestamp = event->common.timestamp; GamepadEvent::Dispatch(&gamepadEvent); SDLGamepad::Disconnect(event->cdevice.which); @@ -1002,6 +1007,7 @@ namespace lime keyEvent.keyCode = event->key.keysym.sym; keyEvent.modifier = event->key.keysym.mod; + keyEvent.timestamp = event->common.timestamp; keyEvent.windowID = event->key.windowID; if (keyEvent.type == KEY_DOWN) diff --git a/project/src/backend/sdl/SDLWindow.cpp b/project/src/backend/sdl/SDLWindow.cpp index 07cd39693b..d38ce8ae4a 100644 --- a/project/src/backend/sdl/SDLWindow.cpp +++ b/project/src/backend/sdl/SDLWindow.cpp @@ -189,6 +189,43 @@ namespace lime { RemovePropW (hwnd, LIME_SDL_LAST_RESIZE_TICK_PROP); } + + static bool EnableTransparentWindow (SDL_Window* sdlWindow) { + + if (!sdlWindow) return false; + + SDL_SysWMinfo wminfo; + SDL_VERSION (&wminfo.version); + if (SDL_GetWindowWMInfo (sdlWindow, &wminfo) != 1) return false; + + HWND hwnd = wminfo.info.win.window; + if (!hwnd) return false; + + typedef struct { + int leftWidth; + int rightWidth; + int topHeight; + int bottomHeight; + } DwmMargins; + typedef HRESULT (WINAPI *DwmExtendFrameIntoClientAreaFunc) (HWND hwnd, const DwmMargins* margins); + + HMODULE dwmapi = LoadLibraryW (L"dwmapi.dll"); + if (!dwmapi) return false; + + DwmExtendFrameIntoClientAreaFunc extendFrame = (DwmExtendFrameIntoClientAreaFunc)GetProcAddress (dwmapi, "DwmExtendFrameIntoClientArea"); + bool enabled = false; + + if (extendFrame) { + + DwmMargins margins = { -1, -1, -1, -1 }; + enabled = SUCCEEDED (extendFrame (hwnd, &margins)); + + } + + FreeLibrary (dwmapi); + return enabled; + + } #endif @@ -199,6 +236,7 @@ namespace lime { sdlTexture = 0; sdlRenderer = 0; context = 0; + useVulkan = (flags & WINDOW_FLAG_VULKAN) != 0; contextWidth = 0; contextHeight = 0; @@ -240,9 +278,25 @@ namespace lime { SDL_SetHint (SDL_HINT_TOUCH_MOUSE_EVENTS, "1"); #endif + if (flags & WINDOW_FLAG_TRANSPARENT) { + + #ifdef SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY + SDL_SetHint (SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY, "1"); + #endif + + } + if (flags & WINDOW_FLAG_HARDWARE) { - sdlWindowFlags |= SDL_WINDOW_OPENGL; + if (useVulkan) { + + sdlWindowFlags |= SDL_WINDOW_VULKAN; + + } else { + + sdlWindowFlags |= SDL_WINDOW_OPENGL; + + } if (flags & WINDOW_FLAG_ALLOW_HIGHDPI) { @@ -250,61 +304,65 @@ namespace lime { } - #if defined (HX_WINDOWS) && defined (NATIVE_TOOLKIT_SDL_ANGLE) - SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2); - SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 0); - SDL_SetHint (SDL_HINT_VIDEO_WIN_D3DCOMPILER, "d3dcompiler_47.dll"); - #endif + if (!useVulkan) { - #if defined (RASPBERRYPI) - SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2); - SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 0); - SDL_SetHint (SDL_HINT_RENDER_DRIVER, "opengles2"); - #endif + #if defined (HX_WINDOWS) && defined (NATIVE_TOOLKIT_SDL_ANGLE) + SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 0); + SDL_SetHint (SDL_HINT_VIDEO_WIN_D3DCOMPILER, "d3dcompiler_47.dll"); + #endif - #if defined (IPHONE) || defined (APPLETV) - SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 3); - #endif + #if defined (RASPBERRYPI) + SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 0); + SDL_SetHint (SDL_HINT_RENDER_DRIVER, "opengles2"); + #endif - if (flags & WINDOW_FLAG_DEPTH_BUFFER) { + #if defined (IPHONE) || defined (APPLETV) + SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 3); + #endif - SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 32 - (flags & WINDOW_FLAG_STENCIL_BUFFER) ? 8 : 0); + if (flags & WINDOW_FLAG_DEPTH_BUFFER) { - } + SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 32 - (flags & WINDOW_FLAG_STENCIL_BUFFER) ? 8 : 0); - if (flags & WINDOW_FLAG_STENCIL_BUFFER) { + } - SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8); + if (flags & WINDOW_FLAG_STENCIL_BUFFER) { - } + SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8); - if (flags & WINDOW_FLAG_HW_AA_HIRES) { + } - SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, true); - SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, 4); + if (flags & WINDOW_FLAG_HW_AA_HIRES) { - } else if (flags & WINDOW_FLAG_HW_AA) { + SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, true); + SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, 4); - SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, true); - SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, 2); + } else if (flags & WINDOW_FLAG_HW_AA) { - } + SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, true); + SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, 2); - if (flags & WINDOW_FLAG_COLOR_DEPTH_32_BIT) { + } - SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8); + if (flags & (WINDOW_FLAG_COLOR_DEPTH_32_BIT | WINDOW_FLAG_TRANSPARENT)) { - } else { + SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8); + + } else { - SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5); - SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 6); - SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5); + SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5); + SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 6); + SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5); + + } } @@ -313,7 +371,7 @@ namespace lime { sdlWindow = SDL_CreateWindow (title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, sdlWindowFlags); #if defined (IPHONE) || defined (APPLETV) - if (sdlWindow && !SDL_GL_CreateContext (sdlWindow)) { + if (!useVulkan && sdlWindow && !SDL_GL_CreateContext (sdlWindow)) { SDL_DestroyWindow (sdlWindow); SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2); @@ -332,6 +390,12 @@ namespace lime { #if defined (HX_WINDOWS) && !defined (HX_WINRT) InstallResizeEventHook (sdlWindow); + + if ((flags & WINDOW_FLAG_TRANSPARENT) && !useVulkan) { + + EnableTransparentWindow (sdlWindow); + + } #endif #if defined (HX_WINDOWS) && !defined (HX_WINRT) @@ -362,7 +426,7 @@ namespace lime { int sdlRendererFlags = 0; - if (flags & WINDOW_FLAG_HARDWARE) { + if ((flags & WINDOW_FLAG_HARDWARE) && !useVulkan) { sdlRendererFlags |= SDL_RENDERER_ACCELERATED; @@ -430,7 +494,7 @@ namespace lime { } - if (!context) { + if (!context && !useVulkan) { sdlRendererFlags &= ~SDL_RENDERER_ACCELERATED; sdlRendererFlags &= ~SDL_RENDERER_PRESENTVSYNC; @@ -441,7 +505,7 @@ namespace lime { } - if (context || sdlRenderer) { + if (context || sdlRenderer || useVulkan) { ((SDLApplication*)currentApplication)->RegisterWindow (this); @@ -462,6 +526,24 @@ namespace lime { } + if (sdlRenderer) { + + SDL_DestroyRenderer (sdlRenderer); + sdlRenderer = 0; + + } else if (context) { + + if (SDL_GL_GetCurrentContext () == context) { + + SDL_GL_MakeCurrent (sdlWindow, NULL); + + } + + SDL_GL_DeleteContext (context); + context = 0; + + } + if (sdlWindow) { #if defined (HX_WINDOWS) && !defined (HX_WINRT) @@ -473,16 +555,6 @@ namespace lime { } - if (sdlRenderer) { - - SDL_DestroyRenderer (sdlRenderer); - - } else if (context) { - - SDL_GL_DeleteContext (context); - - } - } @@ -531,6 +603,24 @@ namespace lime { RestoreResizeEventHook (sdlWindow); #endif + if (sdlRenderer) { + + SDL_DestroyRenderer (sdlRenderer); + sdlRenderer = 0; + + } else if (context) { + + if (SDL_GL_GetCurrentContext () == context) { + + SDL_GL_MakeCurrent (sdlWindow, NULL); + + } + + SDL_GL_DeleteContext (context); + context = 0; + + } + SDL_DestroyWindow (sdlWindow); sdlWindow = 0; @@ -558,6 +648,12 @@ namespace lime { void SDLWindow::ContextFlip () { + if (useVulkan) { + + return; + + } + if (context && !sdlRenderer) { SDL_GL_SwapWindow (sdlWindow); @@ -578,6 +674,13 @@ namespace lime { } + int SDLWindow::GetRequestedVSyncMode () const { + + return requestedVSyncMode; + + } + + double SDLWindow::GetRefreshRate () const { if (!sdlWindow) { @@ -605,6 +708,72 @@ namespace lime { } + uint64_t SDLWindow::CreateVulkanSurface (uintptr_t instance) { + + if (!useVulkan || !instance) { + + return 0; + + } + + SDL_vulkanSurface surface = 0; + if (SDL_Vulkan_CreateSurface (sdlWindow, (SDL_vulkanInstance)instance, &surface) != SDL_TRUE) { + + return 0; + + } + + #if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + return (uint64_t)(uintptr_t)surface; + #else + return (uint64_t)surface; + #endif + + } + + + void SDLWindow::GetVulkanDrawableSize (int* width, int* height) { + + if (!useVulkan) { + + if (width) *width = 0; + if (height) *height = 0; + return; + + } + + SDL_Vulkan_GetDrawableSize (sdlWindow, width, height); + + } + + + bool SDLWindow::GetVulkanInstanceExtensions (unsigned int* count, const char** names) { + + if (!useVulkan) { + + if (count) *count = 0; + return false; + + } + + return SDL_Vulkan_GetInstanceExtensions (sdlWindow, count, names) == SDL_TRUE; + + } + + + void* SDLWindow::GetVulkanInstanceProcAddr () { + + if (!useVulkan) { + + return 0; + + } + + return SDL_Vulkan_GetVkGetInstanceProcAddr (); + + } + + void* SDLWindow::ContextLock (bool useCFFIValue) { if (sdlRenderer) { @@ -692,6 +861,12 @@ namespace lime { void SDLWindow::ContextMakeCurrent () { + if (useVulkan) { + + return; + + } + if (sdlWindow && context) { SDL_GL_MakeCurrent (sdlWindow, context); @@ -723,6 +898,12 @@ namespace lime { void* SDLWindow::GetContext () { + if (useVulkan) { + + return sdlWindow; + + } + return context; } @@ -730,6 +911,12 @@ namespace lime { const char* SDLWindow::GetContextType () { + if (useVulkan) { + + return "vulkan"; + + } + if (context) { return "opengl"; @@ -1333,6 +1520,35 @@ namespace lime { requestedVSyncMode = vsyncMode; activeSwapInterval = 0; + if (useVulkan) { + + switch (vsyncMode) { + + case 1: + activeSwapInterval = 1; + flags |= WINDOW_FLAG_VSYNC; + break; + + case 2: + activeSwapInterval = -1; + flags |= WINDOW_FLAG_VSYNC; + break; + + case 3: + activeSwapInterval = 1; + flags |= WINDOW_FLAG_VSYNC; + break; + + default: + flags &= ~WINDOW_FLAG_VSYNC; + break; + + } + + return; + + } + if (!sdlWindow || !context || sdlRenderer) { flags &= ~WINDOW_FLAG_VSYNC; @@ -1439,7 +1655,16 @@ namespace lime { Window* CreateWindow (Application* application, int width, int height, int flags, const char* title) { - return new SDLWindow (application, width, height, flags, title); + SDLWindow* window = new SDLWindow (application, width, height, flags, title); + + if (!window->sdlWindow) { + + delete window; + return 0; + + } + + return window; } diff --git a/project/src/backend/sdl/SDLWindow.h b/project/src/backend/sdl/SDLWindow.h index 51cd02403a..9c3c20fddd 100644 --- a/project/src/backend/sdl/SDLWindow.h +++ b/project/src/backend/sdl/SDLWindow.h @@ -3,6 +3,7 @@ #include +#include #include #include #include @@ -62,7 +63,12 @@ namespace lime { virtual bool SetVisible (bool visible); virtual void WarpMouse (int x, int y); virtual int GetVSyncInterval () const; + virtual int GetRequestedVSyncMode () const; virtual double GetRefreshRate () const; + virtual uint64_t CreateVulkanSurface (uintptr_t instance); + virtual void GetVulkanDrawableSize (int* width, int* height); + virtual bool GetVulkanInstanceExtensions (unsigned int* count, const char** names); + virtual void* GetVulkanInstanceProcAddr (); SDL_Renderer* sdlRenderer; SDL_Texture* sdlTexture; SDL_Window* sdlWindow; @@ -74,6 +80,7 @@ namespace lime { int contextHeight; int contextWidth; int requestedVSyncMode; + bool useVulkan; }; diff --git a/project/src/graphics/opengl/OpenGLBindings.cpp b/project/src/graphics/opengl/OpenGLBindings.cpp index dbcc4f1aec..4bcd72a01c 100644 --- a/project/src/graphics/opengl/OpenGLBindings.cpp +++ b/project/src/graphics/opengl/OpenGLBindings.cpp @@ -228,10 +228,13 @@ namespace lime { if (glIsRenderbuffer (id)) glDeleteRenderbuffers (1, &id); break; - #ifdef LIME_GLES3_API + #if defined(LIME_GLES3_API) || !defined(LIME_GLES) case TYPE_SAMPLER: - if (glIsSampler (id)) glDeleteSamplers (1, &id); + if (glIsSampler && glIsSampler (id)) { + if (glDeleteSamplers) + glDeleteSamplers (1, &id); + } break; #endif @@ -245,10 +248,20 @@ namespace lime { if (glIsTexture (id)) glDeleteTextures (1, &id); break; - #ifdef LIME_GLES3_API + #if defined(LIME_GLES3_API) || !defined(LIME_GLES) case TYPE_VERTEX_ARRAY_OBJECT: - - if (glIsVertexArray (id)) glDeleteVertexArrays (1, &id); + + #if defined(HX_MACOS) + if (glIsVertexArrayAPPLE && glIsVertexArrayAPPLE (id)) { + if (glDeleteVertexArraysAPPLE) + glDeleteVertexArraysAPPLE (1, &id); + } + else + #endif + if (glIsVertexArray && glIsVertexArray (id)) { + if (glDeleteVertexArrays) + glDeleteVertexArrays (1, &id); + } break; #endif @@ -531,6 +544,12 @@ namespace lime { void lime_gl_bind_vertex_array (int vertexArray) { #if defined (LIME_GLES3_API) || !defined (LIME_GLES) + #if defined (HX_MACOS) + if (glBindVertexArrayAPPLE) { + glBindVertexArrayAPPLE (vertexArray); + } + else + #endif if (glBindVertexArray) { glBindVertexArray (vertexArray); } @@ -542,6 +561,12 @@ namespace lime { HL_PRIM void HL_NAME(hl_gl_bind_vertex_array) (int vertexArray) { #if defined (LIME_GLES3_API) || !defined (LIME_GLES) + #if defined (HX_MACOS) + if (glBindVertexArrayAPPLE) { + glBindVertexArrayAPPLE (vertexArray); + } + else + #endif if (glBindVertexArray) { glBindVertexArray (vertexArray); } @@ -1200,6 +1225,12 @@ namespace lime { GLuint id = 0; #if defined (LIME_GLES3_API) || !defined (LIME_GLES) + #if defined (HX_MACOS) + if (glGenVertexArraysAPPLE) { + glGenVertexArraysAPPLE (1, &id); + } + else + #endif if (glGenVertexArrays) { glGenVertexArrays (1, &id); } @@ -1213,6 +1244,12 @@ namespace lime { GLuint id = 0; #if defined (LIME_GLES3_API) || !defined (LIME_GLES) + #if defined (HX_MACOS) + if (glGenVertexArraysAPPLE) { + glGenVertexArraysAPPLE (1, &id); + } + else + #endif if (glGenVertexArrays) { glGenVertexArrays (1, &id); } @@ -1401,6 +1438,12 @@ namespace lime { void lime_gl_delete_vertex_array (int vertexArray) { #if defined (LIME_GLES3_API) || !defined (LIME_GLES) + #if defined (HX_MACOS) + if (glDeleteVertexArraysAPPLE) { + glDeleteVertexArraysAPPLE (1, (GLuint*)&vertexArray); + } + else + #endif if (glDeleteVertexArrays) { glDeleteVertexArrays (1, (GLuint*)&vertexArray); } @@ -1412,6 +1455,12 @@ namespace lime { HL_PRIM void HL_NAME(hl_gl_delete_vertex_array) (int vertexArray) { #if defined (LIME_GLES3_API) || !defined (LIME_GLES) + #if defined (HX_MACOS) + if (glDeleteVertexArraysAPPLE) { + glDeleteVertexArraysAPPLE (1, (GLuint*)&vertexArray); + } + else + #endif if (glDeleteVertexArrays) { glDeleteVertexArrays (1, (GLuint*)&vertexArray); } @@ -3880,7 +3929,17 @@ namespace lime { bool lime_gl_is_vertex_array (int handle) { #if defined (LIME_GLES3_API) || !defined (LIME_GLES) - return glIsVertexArray ? glIsVertexArray (handle) : false; + #if defined (HX_MACOS) + if (glIsVertexArrayAPPLE) { + return glIsVertexArrayAPPLE (handle); + } + else + #endif + if (glIsVertexArray) { + return glIsVertexArray (handle); + } + + return false; #else return false; #endif @@ -3891,7 +3950,17 @@ namespace lime { HL_PRIM bool HL_NAME(hl_gl_is_vertex_array) (int handle) { #if defined (LIME_GLES3_API) || !defined (LIME_GLES) - return glIsVertexArray ? glIsVertexArray (handle) : false; + #if defined (HX_MACOS) + if (glIsVertexArrayAPPLE) { + return glIsVertexArrayAPPLE (handle); + } + else + #endif + if (glIsVertexArray) { + return glIsVertexArray (handle); + } + + return false; #else return false; #endif diff --git a/project/src/graphics/vulkan/VKRenderer.cpp b/project/src/graphics/vulkan/VKRenderer.cpp new file mode 100644 index 0000000000..a8b9069a0d --- /dev/null +++ b/project/src/graphics/vulkan/VKRenderer.cpp @@ -0,0 +1,1750 @@ +#include + +#include +#include + +#include +#include +#include +#include + + +namespace lime { + + + static const char* VulkanResultToString (VkResult result) { + + switch (result) { + + case VK_SUCCESS: return "VK_SUCCESS"; + case VK_NOT_READY: return "VK_NOT_READY"; + case VK_TIMEOUT: return "VK_TIMEOUT"; + case VK_EVENT_SET: return "VK_EVENT_SET"; + case VK_EVENT_RESET: return "VK_EVENT_RESET"; + case VK_INCOMPLETE: return "VK_INCOMPLETE"; + case VK_ERROR_OUT_OF_HOST_MEMORY: return "VK_ERROR_OUT_OF_HOST_MEMORY"; + case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "VK_ERROR_OUT_OF_DEVICE_MEMORY"; + case VK_ERROR_INITIALIZATION_FAILED: return "VK_ERROR_INITIALIZATION_FAILED"; + case VK_ERROR_DEVICE_LOST: return "VK_ERROR_DEVICE_LOST"; + case VK_ERROR_MEMORY_MAP_FAILED: return "VK_ERROR_MEMORY_MAP_FAILED"; + case VK_ERROR_LAYER_NOT_PRESENT: return "VK_ERROR_LAYER_NOT_PRESENT"; + case VK_ERROR_EXTENSION_NOT_PRESENT: return "VK_ERROR_EXTENSION_NOT_PRESENT"; + case VK_ERROR_FEATURE_NOT_PRESENT: return "VK_ERROR_FEATURE_NOT_PRESENT"; + case VK_ERROR_INCOMPATIBLE_DRIVER: return "VK_ERROR_INCOMPATIBLE_DRIVER"; + case VK_ERROR_TOO_MANY_OBJECTS: return "VK_ERROR_TOO_MANY_OBJECTS"; + case VK_ERROR_FORMAT_NOT_SUPPORTED: return "VK_ERROR_FORMAT_NOT_SUPPORTED"; + case VK_ERROR_SURFACE_LOST_KHR: return "VK_ERROR_SURFACE_LOST_KHR"; + case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"; + case VK_SUBOPTIMAL_KHR: return "VK_SUBOPTIMAL_KHR"; + case VK_ERROR_OUT_OF_DATE_KHR: return "VK_ERROR_OUT_OF_DATE_KHR"; + default: return "VK_RESULT_UNKNOWN"; + + } + + } + + + static std::string FormatVulkanVersion (uint32_t version) { + + std::ostringstream result; + result << VK_API_VERSION_MAJOR (version) << "." << VK_API_VERSION_MINOR (version) << "." << VK_API_VERSION_PATCH (version); + return result.str (); + + } + + + static const char* VulkanPresentModeToString (VkPresentModeKHR mode) { + + switch (mode) { + + case VK_PRESENT_MODE_IMMEDIATE_KHR: return "immediate"; + case VK_PRESENT_MODE_MAILBOX_KHR: return "mailbox"; + case VK_PRESENT_MODE_FIFO_KHR: return "fifo"; + #ifdef VK_PRESENT_MODE_FIFO_RELAXED_KHR + case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return "fifo-relaxed"; + #endif + default: return "unknown"; + + } + + } + + + static VkPresentModeKHR ChoosePresentMode (const std::vector& presentModes, int requestedVSyncMode) { + + bool hasImmediate = false; + bool hasMailbox = false; + bool hasFifo = false; + bool hasFifoRelaxed = false; + + for (size_t i = 0; i < presentModes.size (); ++i) { + + switch (presentModes[i]) { + + case VK_PRESENT_MODE_IMMEDIATE_KHR: + hasImmediate = true; + break; + + case VK_PRESENT_MODE_MAILBOX_KHR: + hasMailbox = true; + break; + + case VK_PRESENT_MODE_FIFO_KHR: + hasFifo = true; + break; + + #ifdef VK_PRESENT_MODE_FIFO_RELAXED_KHR + case VK_PRESENT_MODE_FIFO_RELAXED_KHR: + hasFifoRelaxed = true; + break; + #endif + + default: + break; + + } + + } + + switch (requestedVSyncMode) { + + case 0: + if (hasImmediate) return VK_PRESENT_MODE_IMMEDIATE_KHR; + if (hasMailbox) return VK_PRESENT_MODE_MAILBOX_KHR; + break; + + case 2: + if (hasMailbox) return VK_PRESENT_MODE_MAILBOX_KHR; + #ifdef VK_PRESENT_MODE_FIFO_RELAXED_KHR + if (hasFifoRelaxed) return VK_PRESENT_MODE_FIFO_RELAXED_KHR; + #endif + break; + + case 3: + if (hasMailbox) return VK_PRESENT_MODE_MAILBOX_KHR; + if (hasFifo) return VK_PRESENT_MODE_FIFO_KHR; + if (hasImmediate) return VK_PRESENT_MODE_IMMEDIATE_KHR; + break; + + default: + if (hasFifo) return VK_PRESENT_MODE_FIFO_KHR; + break; + + } + + if (hasFifo) return VK_PRESENT_MODE_FIFO_KHR; + if (hasMailbox) return VK_PRESENT_MODE_MAILBOX_KHR; + if (hasImmediate) return VK_PRESENT_MODE_IMMEDIATE_KHR; + return VK_PRESENT_MODE_FIFO_KHR; + + } + + + VulkanRenderer::VulkanRenderer (Window* window) + : window (window), + vkGetInstanceProcAddr (0), + vkGetDeviceProcAddr (0), + vkAllocateMemory (0), + vkBindBufferMemory (0), + vkCmdCopyBufferToImage (0), + vkCmdPipelineBarrier (0), + vkCreateBuffer (0), + vkCreateDevice (0), + vkCreateFence (0), + vkCreateFramebuffer (0), + vkCreateImageView (0), + vkCreateInstance (0), + vkCreateRenderPass (0), + vkCreateSemaphore (0), + vkCreateSwapchainKHR (0), + vkCreateCommandPool (0), + vkAllocateCommandBuffers (0), + vkAcquireNextImageKHR (0), + vkBeginCommandBuffer (0), + vkCmdBeginRenderPass (0), + vkCmdEndRenderPass (0), + vkDestroyCommandPool (0), + vkDestroyBuffer (0), + vkDestroyDevice (0), + vkDestroyFence (0), + vkDestroyFramebuffer (0), + vkDestroyImageView (0), + vkDestroyInstance (0), + vkDestroyRenderPass (0), + vkDestroySemaphore (0), + vkDestroySurfaceKHR (0), + vkDestroySwapchainKHR (0), + vkDeviceWaitIdle (0), + vkEndCommandBuffer (0), + vkEnumerateDeviceExtensionProperties (0), + vkFreeMemory (0), + vkGetBufferMemoryRequirements (0), + vkEnumerateInstanceExtensionProperties (0), + vkEnumerateInstanceVersion (0), + vkEnumeratePhysicalDevices (0), + vkGetDeviceQueue (0), + vkGetPhysicalDeviceMemoryProperties (0), + vkGetPhysicalDeviceProperties (0), + vkGetPhysicalDeviceQueueFamilyProperties (0), + vkGetPhysicalDeviceSurfaceCapabilitiesKHR (0), + vkGetPhysicalDeviceSurfaceFormatsKHR (0), + vkGetPhysicalDeviceSurfacePresentModesKHR (0), + vkGetPhysicalDeviceSurfaceSupportKHR (0), + vkGetSwapchainImagesKHR (0), + vkMapMemory (0), + vkQueuePresentKHR (0), + vkQueueSubmit (0), + vkResetCommandPool (0), + vkResetFences (0), + vkUnmapMemory (0), + vkWaitForFences (0), + instance (VK_NULL_HANDLE), + surface (VK_NULL_HANDLE), + physicalDevice (VK_NULL_HANDLE), + device (VK_NULL_HANDLE), + queue (VK_NULL_HANDLE), + queueFamilyIndex (0), + swapchain (VK_NULL_HANDLE), + swapchainFormat (VK_FORMAT_UNDEFINED), + swapchainPresentMode (VK_PRESENT_MODE_FIFO_KHR), + requestedVSyncMode (0), + renderPass (VK_NULL_HANDLE), + commandPool (VK_NULL_HANDLE), + imageAvailableSemaphore (VK_NULL_HANDLE), + renderFinishedSemaphore (VK_NULL_HANDLE), + inFlightFence (VK_NULL_HANDLE), + overlayBuffer (VK_NULL_HANDLE), + overlayBufferMemory (VK_NULL_HANDLE), + portabilityEnumerationSupported (false), + portabilitySubsetSupported (false), + swapchainDirty (false), + overlayBufferCapacity (0), + overlayMappedData (0), + overlayWidth (0), + overlayHeight (0), + overlayX (0), + overlayY (0), + overlayEnabled (false) { + + memset (&physicalDeviceProperties, 0, sizeof (physicalDeviceProperties)); + memset (&swapchainExtent, 0, sizeof (swapchainExtent)); + + } + + + VulkanRenderer::~VulkanRenderer () { + + Destroy (); + + } + + + bool VulkanRenderer::Create (const char* applicationName) { + + Destroy (); + lastError.clear (); + info.clear (); + + if (!window) { + + SetError ("Vulkan renderer creation failed: missing window"); + return false; + + } + + if (SDL_Vulkan_LoadLibrary (NULL) != 0) { + + SetError (std::string ("SDL_Vulkan_LoadLibrary failed: ") + SDL_GetError ()); + return false; + + } + + if (!LoadGlobalProcs ()) { + + return false; + + } + + if (!CreateInstance (applicationName)) return false; + if (!LoadInstanceProcs ()) return false; + if (!CreateSurface ()) return false; + if (!PickPhysicalDevice ()) return false; + if (!CreateDevice ()) return false; + if (!LoadDeviceProcs ()) return false; + vkGetDeviceQueue (device, queueFamilyIndex, 0, &queue); + if (!CreateSwapchainResources ()) return false; + if (!CreateSyncObjects ()) return false; + + std::ostringstream result; + result << physicalDeviceProperties.deviceName << " | Vulkan " << FormatVulkanVersion (physicalDeviceProperties.apiVersion) + << " | present " << VulkanPresentModeToString (swapchainPresentMode); + info = result.str (); + return true; + + } + + + bool VulkanRenderer::ClearOverlay () { + + overlayEnabled = false; + overlayWidth = 0; + overlayHeight = 0; + overlayX = 0; + overlayY = 0; + lastError.clear (); + return true; + + } + + + void VulkanRenderer::Destroy () { + + if (device && vkDeviceWaitIdle) { + + vkDeviceWaitIdle (device); + + } + + if (device && vkDestroyFence && inFlightFence) { + + vkDestroyFence (device, inFlightFence, 0); + inFlightFence = VK_NULL_HANDLE; + + } + + if (device && vkDestroySemaphore && renderFinishedSemaphore) { + + vkDestroySemaphore (device, renderFinishedSemaphore, 0); + renderFinishedSemaphore = VK_NULL_HANDLE; + + } + + if (device && vkDestroySemaphore && imageAvailableSemaphore) { + + vkDestroySemaphore (device, imageAvailableSemaphore, 0); + imageAvailableSemaphore = VK_NULL_HANDLE; + + } + + DestroyOverlayResources (); + DestroySwapchainResources (); + + if (device && vkDestroyDevice) { + + vkDestroyDevice (device, 0); + device = VK_NULL_HANDLE; + + } + + queue = VK_NULL_HANDLE; + physicalDevice = VK_NULL_HANDLE; + memset (&physicalDeviceProperties, 0, sizeof (physicalDeviceProperties)); + + if (surface && vkDestroySurfaceKHR && instance) { + + vkDestroySurfaceKHR (instance, surface, 0); + surface = VK_NULL_HANDLE; + + } + + if (instance && vkDestroyInstance) { + + vkDestroyInstance (instance, 0); + instance = VK_NULL_HANDLE; + + } + + instanceExtensions.clear (); + deviceExtensions.clear (); + portabilityEnumerationSupported = false; + portabilitySubsetSupported = false; + swapchainDirty = false; + swapchainFormat = VK_FORMAT_UNDEFINED; + swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; + requestedVSyncMode = 0; + memset (&swapchainExtent, 0, sizeof (swapchainExtent)); + + } + + + bool VulkanRenderer::Render (float red, float green, float blue, float alpha) { + + if (!device) { + + SetError ("Vulkan renderer is not initialized"); + return false; + + } + + int currentRequestedVSyncMode = window ? window->GetRequestedVSyncMode () : 0; + if (swapchainDirty || !swapchain || swapchainExtent.width == 0 || swapchainExtent.height == 0 || currentRequestedVSyncMode != requestedVSyncMode) { + + if (!RecreateSwapchain ()) { + + return false; + + } + + } + + if (!swapchain || swapchainExtent.width == 0 || swapchainExtent.height == 0) { + + return true; + + } + + VkResult result = vkWaitForFences (device, 1, &inFlightFence, VK_TRUE, UINT64_MAX); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkWaitForFences failed: ") + VulkanResultToString (result)); + return false; + + } + + uint32_t imageIndex = 0; + result = vkAcquireNextImageKHR (device, swapchain, UINT64_MAX, imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex); + + if (result == VK_ERROR_OUT_OF_DATE_KHR) { + + return RecreateSwapchain (); + + } + + if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) { + + SetError (std::string ("vkAcquireNextImageKHR failed: ") + VulkanResultToString (result)); + return false; + + } + + result = vkResetFences (device, 1, &inFlightFence); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkResetFences failed: ") + VulkanResultToString (result)); + return false; + + } + + result = vkResetCommandPool (device, commandPool, 0); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkResetCommandPool failed: ") + VulkanResultToString (result)); + return false; + + } + + if (!RecordCommandBuffer (imageIndex, red, green, blue, alpha)) { + + return false; + + } + + VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; + VkSubmitInfo submitInfo; + memset (&submitInfo, 0, sizeof (submitInfo)); + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.waitSemaphoreCount = 1; + submitInfo.pWaitSemaphores = &imageAvailableSemaphore; + submitInfo.pWaitDstStageMask = waitStages; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffers[imageIndex]; + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = &renderFinishedSemaphore; + + result = vkQueueSubmit (queue, 1, &submitInfo, inFlightFence); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkQueueSubmit failed: ") + VulkanResultToString (result)); + return false; + + } + + VkPresentInfoKHR presentInfo; + memset (&presentInfo, 0, sizeof (presentInfo)); + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.waitSemaphoreCount = 1; + presentInfo.pWaitSemaphores = &renderFinishedSemaphore; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &swapchain; + presentInfo.pImageIndices = &imageIndex; + + result = vkQueuePresentKHR (queue, &presentInfo); + if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) { + + return RecreateSwapchain (); + + } + + if (result != VK_SUCCESS) { + + SetError (std::string ("vkQueuePresentKHR failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::Resize () { + + return RecreateSwapchain (); + + } + + + bool VulkanRenderer::SetOverlay (const unsigned char* data, int width, int height, int x, int y) { + + if (!data || width <= 0 || height <= 0) { + + return ClearOverlay (); + + } + + size_t requiredSize = (size_t)width * (size_t)height * 4; + if (!CreateOverlayBuffer (requiredSize)) { + + return false; + + } + + memcpy (overlayMappedData, data, requiredSize); + + overlayWidth = (uint32_t)width; + overlayHeight = (uint32_t)height; + overlayX = x; + overlayY = y; + overlayEnabled = true; + lastError.clear (); + return true; + + } + + + bool VulkanRenderer::CreateCommandBuffers () { + + commandBuffers.clear (); + + if (swapchainImages.empty ()) { + + SetError ("Cannot allocate Vulkan command buffers without swapchain images"); + return false; + + } + + commandBuffers.resize (swapchainImages.size (), VK_NULL_HANDLE); + + VkCommandBufferAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocateInfo.commandPool = commandPool; + allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocateInfo.commandBufferCount = (uint32_t)commandBuffers.size (); + + VkResult result = vkAllocateCommandBuffers (device, &allocateInfo, commandBuffers.data ()); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkAllocateCommandBuffers failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::CreateCommandPool () { + + VkCommandPoolCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + createInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + createInfo.queueFamilyIndex = queueFamilyIndex; + + VkResult result = vkCreateCommandPool (device, &createInfo, 0, &commandPool); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateCommandPool failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::CreateDevice () { + + const float queuePriority = 1.0f; + + VkDeviceQueueCreateInfo queueCreateInfo; + memset (&queueCreateInfo, 0, sizeof (queueCreateInfo)); + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.queueFamilyIndex = queueFamilyIndex; + queueCreateInfo.queueCount = 1; + queueCreateInfo.pQueuePriorities = &queuePriority; + + deviceExtensions.clear (); + deviceExtensions.push_back (VK_KHR_SWAPCHAIN_EXTENSION_NAME); + if (portabilitySubsetSupported) { + + #ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME + deviceExtensions.push_back (VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); + #endif + + } + + VkDeviceCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + createInfo.queueCreateInfoCount = 1; + createInfo.pQueueCreateInfos = &queueCreateInfo; + createInfo.enabledExtensionCount = (uint32_t)deviceExtensions.size (); + createInfo.ppEnabledExtensionNames = deviceExtensions.data (); + + VkResult result = vkCreateDevice (physicalDevice, &createInfo, 0, &device); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateDevice failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::CreateFramebuffers () { + + framebuffers.clear (); + framebuffers.resize (swapchainImageViews.size (), VK_NULL_HANDLE); + + for (size_t i = 0; i < swapchainImageViews.size (); ++i) { + + VkImageView attachments[] = { swapchainImageViews[i] }; + VkFramebufferCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + createInfo.renderPass = renderPass; + createInfo.attachmentCount = 1; + createInfo.pAttachments = attachments; + createInfo.width = swapchainExtent.width; + createInfo.height = swapchainExtent.height; + createInfo.layers = 1; + + VkResult result = vkCreateFramebuffer (device, &createInfo, 0, &framebuffers[i]); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateFramebuffer failed: ") + VulkanResultToString (result)); + return false; + + } + + } + + return true; + + } + + + bool VulkanRenderer::CreateImageViews () { + + swapchainImageViews.clear (); + swapchainImageViews.resize (swapchainImages.size (), VK_NULL_HANDLE); + + for (size_t i = 0; i < swapchainImages.size (); ++i) { + + VkImageViewCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.image = swapchainImages[i]; + createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + createInfo.format = swapchainFormat; + createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + createInfo.subresourceRange.baseMipLevel = 0; + createInfo.subresourceRange.levelCount = 1; + createInfo.subresourceRange.baseArrayLayer = 0; + createInfo.subresourceRange.layerCount = 1; + + VkResult result = vkCreateImageView (device, &createInfo, 0, &swapchainImageViews[i]); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateImageView failed: ") + VulkanResultToString (result)); + return false; + + } + + } + + return true; + + } + + + bool VulkanRenderer::CreateInstance (const char* applicationName) { + + instanceExtensions.clear (); + + unsigned int requiredExtensionCount = 0; + if (!window->GetVulkanInstanceExtensions (&requiredExtensionCount, 0)) { + + SetError ("Failed to query required Vulkan window extensions"); + return false; + + } + + std::vector requiredExtensions (requiredExtensionCount); + if (requiredExtensionCount > 0 && !window->GetVulkanInstanceExtensions (&requiredExtensionCount, requiredExtensions.data ())) { + + SetError ("Failed to fetch required Vulkan window extensions"); + return false; + + } + + for (size_t i = 0; i < requiredExtensions.size (); ++i) { + + instanceExtensions.push_back (requiredExtensions[i]); + + } + + uint32_t availableCount = 0; + if (vkEnumerateInstanceExtensionProperties && + vkEnumerateInstanceExtensionProperties (0, &availableCount, 0) == VK_SUCCESS && availableCount > 0) { + + std::vector availableExtensions (availableCount); + if (vkEnumerateInstanceExtensionProperties (0, &availableCount, availableExtensions.data ()) == VK_SUCCESS) { + + for (size_t i = 0; i < availableExtensions.size (); ++i) { + + #ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME + if (strcmp (availableExtensions[i].extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) { + + portabilityEnumerationSupported = true; + + } + #endif + + } + + } + + } + + if (portabilityEnumerationSupported) { + + #ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME + instanceExtensions.push_back (VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + #endif + + } + + uint32_t instanceVersion = VK_API_VERSION_1_0; + if (vkEnumerateInstanceVersion) { + + vkEnumerateInstanceVersion (&instanceVersion); + + } + + VkApplicationInfo applicationInfo; + memset (&applicationInfo, 0, sizeof (applicationInfo)); + applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + applicationInfo.pApplicationName = applicationName ? applicationName : "Lime Vulkan Sample"; + applicationInfo.pEngineName = "Lime"; + applicationInfo.applicationVersion = VK_MAKE_VERSION (1, 0, 0); + applicationInfo.engineVersion = VK_MAKE_VERSION (1, 0, 0); + applicationInfo.apiVersion = instanceVersion >= VK_API_VERSION_1_0 ? VK_API_VERSION_1_0 : instanceVersion; + + VkInstanceCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &applicationInfo; + createInfo.enabledExtensionCount = (uint32_t)instanceExtensions.size (); + createInfo.ppEnabledExtensionNames = instanceExtensions.empty () ? 0 : instanceExtensions.data (); + + #ifdef VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR + if (portabilityEnumerationSupported) { + + createInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + + } + #endif + + VkResult result = vkCreateInstance (&createInfo, 0, &instance); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateInstance failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::CreateOverlayBuffer (size_t requiredSize) { + + if (!device) { + + SetError ("Cannot create Vulkan overlay buffer before device initialization"); + return false; + + } + + if (requiredSize == 0) { + + DestroyOverlayResources (); + return true; + + } + + if (overlayBuffer != VK_NULL_HANDLE && overlayMappedData && overlayBufferCapacity >= requiredSize) { + + return true; + + } + + DestroyOverlayResources (); + + VkBufferCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + createInfo.size = requiredSize; + createInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VkResult result = vkCreateBuffer (device, &createInfo, 0, &overlayBuffer); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateBuffer failed for overlay upload: ") + VulkanResultToString (result)); + return false; + + } + + VkMemoryRequirements memoryRequirements; + memset (&memoryRequirements, 0, sizeof (memoryRequirements)); + vkGetBufferMemoryRequirements (device, overlayBuffer, &memoryRequirements); + + VkMemoryAllocateInfo allocateInfo; + memset (&allocateInfo, 0, sizeof (allocateInfo)); + allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocateInfo.allocationSize = memoryRequirements.size; + allocateInfo.memoryTypeIndex = FindMemoryType ( + memoryRequirements.memoryTypeBits, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + ); + if (allocateInfo.memoryTypeIndex == UINT32_MAX) { + + return false; + + } + + result = vkAllocateMemory (device, &allocateInfo, 0, &overlayBufferMemory); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkAllocateMemory failed for overlay upload: ") + VulkanResultToString (result)); + return false; + + } + + result = vkBindBufferMemory (device, overlayBuffer, overlayBufferMemory, 0); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkBindBufferMemory failed for overlay upload: ") + VulkanResultToString (result)); + return false; + + } + + void* mappedData = 0; + result = vkMapMemory (device, overlayBufferMemory, 0, allocateInfo.allocationSize, 0, &mappedData); + if (result != VK_SUCCESS || !mappedData) { + + SetError (std::string ("vkMapMemory failed for overlay upload: ") + VulkanResultToString (result)); + return false; + + } + + overlayMappedData = (unsigned char*)mappedData; + overlayBufferCapacity = requiredSize; + return true; + + } + + + bool VulkanRenderer::CreateRenderPass () { + + VkAttachmentDescription colorAttachment; + memset (&colorAttachment, 0, sizeof (colorAttachment)); + colorAttachment.format = swapchainFormat; + colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; + colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + colorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference colorAttachmentRef; + memset (&colorAttachmentRef, 0, sizeof (colorAttachmentRef)); + colorAttachmentRef.attachment = 0; + colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass; + memset (&subpass, 0, sizeof (subpass)); + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &colorAttachmentRef; + + VkSubpassDependency dependency; + memset (&dependency, 0, sizeof (dependency)); + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + VkRenderPassCreateInfo createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + createInfo.attachmentCount = 1; + createInfo.pAttachments = &colorAttachment; + createInfo.subpassCount = 1; + createInfo.pSubpasses = &subpass; + createInfo.dependencyCount = 1; + createInfo.pDependencies = &dependency; + + VkResult result = vkCreateRenderPass (device, &createInfo, 0, &renderPass); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateRenderPass failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::CreateSurface () { + + uint64_t nativeSurface = window->CreateVulkanSurface ((uintptr_t)instance); + if (!nativeSurface) { + + SetError ("Failed to create Vulkan surface from Lime window"); + return false; + + } + + surface = (VkSurfaceKHR)(uintptr_t)nativeSurface; + return true; + + } + + + bool VulkanRenderer::CreateSwapchain () { + + VkSurfaceCapabilitiesKHR capabilities; + memset (&capabilities, 0, sizeof (capabilities)); + VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR (physicalDevice, surface, &capabilities); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed: ") + VulkanResultToString (result)); + return false; + + } + + uint32_t formatCount = 0; + result = vkGetPhysicalDeviceSurfaceFormatsKHR (physicalDevice, surface, &formatCount, 0); + if (result != VK_SUCCESS || formatCount == 0) { + + SetError ("Failed to query Vulkan surface formats"); + return false; + + } + + std::vector formats (formatCount); + vkGetPhysicalDeviceSurfaceFormatsKHR (physicalDevice, surface, &formatCount, formats.data ()); + + VkSurfaceFormatKHR surfaceFormat = formats[0]; + for (size_t i = 0; i < formats.size (); ++i) { + + if (formats[i].format == VK_FORMAT_B8G8R8A8_UNORM && formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + + surfaceFormat = formats[i]; + break; + + } + + } + + uint32_t presentModeCount = 0; + vkGetPhysicalDeviceSurfacePresentModesKHR (physicalDevice, surface, &presentModeCount, 0); + std::vector presentModes (presentModeCount > 0 ? presentModeCount : 1, VK_PRESENT_MODE_FIFO_KHR); + if (presentModeCount > 0) { + + vkGetPhysicalDeviceSurfacePresentModesKHR (physicalDevice, surface, &presentModeCount, presentModes.data ()); + + } + + int currentRequestedVSyncMode = window ? window->GetRequestedVSyncMode () : 0; + VkPresentModeKHR presentMode = ChoosePresentMode (presentModes, currentRequestedVSyncMode); + + int drawableWidth = 0; + int drawableHeight = 0; + window->GetVulkanDrawableSize (&drawableWidth, &drawableHeight); + if (drawableWidth <= 0 || drawableHeight <= 0) { + + swapchainExtent.width = 0; + swapchainExtent.height = 0; + swapchainDirty = true; + return true; + + } + + if (capabilities.currentExtent.width != UINT32_MAX) { + + swapchainExtent = capabilities.currentExtent; + + } else { + + swapchainExtent.width = (uint32_t)(std::max) ((int)capabilities.minImageExtent.width, + (std::min) (drawableWidth, (int)capabilities.maxImageExtent.width)); + swapchainExtent.height = (uint32_t)(std::max) ((int)capabilities.minImageExtent.height, + (std::min) (drawableHeight, (int)capabilities.maxImageExtent.height)); + + } + + uint32_t imageCount = capabilities.minImageCount + 1; + if (capabilities.maxImageCount > 0 && imageCount > capabilities.maxImageCount) { + + imageCount = capabilities.maxImageCount; + + } + + VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + const bool transparentWindow = window && ((window->flags & WINDOW_FLAG_TRANSPARENT) != 0); + const VkCompositeAlphaFlagBitsKHR opaqueCompositeAlphaFlags[] = { + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR + }; + const VkCompositeAlphaFlagBitsKHR transparentCompositeAlphaFlags[] = { + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR + }; + const VkCompositeAlphaFlagBitsKHR* compositeAlphaFlags = transparentWindow ? transparentCompositeAlphaFlags : opaqueCompositeAlphaFlags; + const size_t compositeAlphaFlagCount = transparentWindow + ? sizeof (transparentCompositeAlphaFlags) / sizeof (transparentCompositeAlphaFlags[0]) + : sizeof (opaqueCompositeAlphaFlags) / sizeof (opaqueCompositeAlphaFlags[0]); + + for (size_t i = 0; i < compositeAlphaFlagCount; ++i) { + + if (capabilities.supportedCompositeAlpha & compositeAlphaFlags[i]) { + + compositeAlpha = compositeAlphaFlags[i]; + break; + + } + + } + + VkSwapchainCreateInfoKHR createInfo; + memset (&createInfo, 0, sizeof (createInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + createInfo.surface = surface; + createInfo.minImageCount = imageCount; + createInfo.imageFormat = surfaceFormat.format; + createInfo.imageColorSpace = surfaceFormat.colorSpace; + createInfo.imageExtent = swapchainExtent; + createInfo.imageArrayLayers = 1; + createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + createInfo.preTransform = capabilities.currentTransform; + createInfo.compositeAlpha = compositeAlpha; + createInfo.presentMode = presentMode; + createInfo.clipped = VK_TRUE; + createInfo.oldSwapchain = VK_NULL_HANDLE; + + result = vkCreateSwapchainKHR (device, &createInfo, 0, &swapchain); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateSwapchainKHR failed: ") + VulkanResultToString (result)); + return false; + + } + + swapchainFormat = surfaceFormat.format; + swapchainPresentMode = presentMode; + requestedVSyncMode = currentRequestedVSyncMode; + swapchainDirty = false; + + uint32_t swapchainImageCount = 0; + result = vkGetSwapchainImagesKHR (device, swapchain, &swapchainImageCount, 0); + if (result != VK_SUCCESS || swapchainImageCount == 0) { + + SetError ("Failed to query Vulkan swapchain images"); + return false; + + } + + swapchainImages.resize (swapchainImageCount); + result = vkGetSwapchainImagesKHR (device, swapchain, &swapchainImageCount, swapchainImages.data ()); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkGetSwapchainImagesKHR failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::CreateSwapchainResources () { + + if (!CreateSwapchain ()) return false; + if (swapchainExtent.width == 0 || swapchainExtent.height == 0) return true; + if (!CreateImageViews ()) return false; + if (!CreateRenderPass ()) return false; + if (!CreateCommandPool ()) return false; + if (!CreateFramebuffers ()) return false; + if (!CreateCommandBuffers ()) return false; + return true; + + } + + + bool VulkanRenderer::CreateSyncObjects () { + + VkSemaphoreCreateInfo semaphoreInfo; + memset (&semaphoreInfo, 0, sizeof (semaphoreInfo)); + semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + VkFenceCreateInfo fenceInfo; + memset (&fenceInfo, 0, sizeof (fenceInfo)); + fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; + + VkResult result = vkCreateSemaphore (device, &semaphoreInfo, 0, &imageAvailableSemaphore); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateSemaphore failed: ") + VulkanResultToString (result)); + return false; + + } + + result = vkCreateSemaphore (device, &semaphoreInfo, 0, &renderFinishedSemaphore); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateSemaphore failed: ") + VulkanResultToString (result)); + return false; + + } + + result = vkCreateFence (device, &fenceInfo, 0, &inFlightFence); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkCreateFence failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + void VulkanRenderer::DestroyOverlayResources () { + + overlayEnabled = false; + overlayWidth = 0; + overlayHeight = 0; + overlayX = 0; + overlayY = 0; + + if (device && overlayBufferMemory && overlayMappedData && vkUnmapMemory) { + + vkUnmapMemory (device, overlayBufferMemory); + overlayMappedData = 0; + + } + + if (device && vkDestroyBuffer && overlayBuffer) { + + vkDestroyBuffer (device, overlayBuffer, 0); + overlayBuffer = VK_NULL_HANDLE; + + } + + if (device && vkFreeMemory && overlayBufferMemory) { + + vkFreeMemory (device, overlayBufferMemory, 0); + overlayBufferMemory = VK_NULL_HANDLE; + + } + + overlayMappedData = 0; + overlayBufferCapacity = 0; + + } + + + void VulkanRenderer::DestroySwapchainResources () { + + commandBuffers.clear (); + + if (device && vkDestroyCommandPool && commandPool) { + + vkDestroyCommandPool (device, commandPool, 0); + commandPool = VK_NULL_HANDLE; + + } + + for (size_t i = 0; i < framebuffers.size (); ++i) { + + if (framebuffers[i] && device && vkDestroyFramebuffer) { + + vkDestroyFramebuffer (device, framebuffers[i], 0); + + } + + } + + framebuffers.clear (); + + if (device && vkDestroyRenderPass && renderPass) { + + vkDestroyRenderPass (device, renderPass, 0); + renderPass = VK_NULL_HANDLE; + + } + + for (size_t i = 0; i < swapchainImageViews.size (); ++i) { + + if (swapchainImageViews[i] && device && vkDestroyImageView) { + + vkDestroyImageView (device, swapchainImageViews[i], 0); + + } + + } + + swapchainImageViews.clear (); + swapchainImages.clear (); + + if (device && vkDestroySwapchainKHR && swapchain) { + + vkDestroySwapchainKHR (device, swapchain, 0); + swapchain = VK_NULL_HANDLE; + + } + + } + + + uint32_t VulkanRenderer::FindMemoryType (uint32_t typeFilter, VkMemoryPropertyFlags properties) { + + VkPhysicalDeviceMemoryProperties memoryProperties; + memset (&memoryProperties, 0, sizeof (memoryProperties)); + vkGetPhysicalDeviceMemoryProperties (physicalDevice, &memoryProperties); + + for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) { + + if ((typeFilter & (1u << i)) && + (memoryProperties.memoryTypes[i].propertyFlags & properties) == properties) { + + return i; + + } + + } + + SetError ("Failed to find a compatible Vulkan memory type"); + return UINT32_MAX; + + } + + + bool VulkanRenderer::LoadDeviceProcs () { + + if (!vkGetDeviceProcAddr) { + + SetError ("Missing vkGetDeviceProcAddr"); + return false; + + } + + #define LIME_LOAD_DEVICE_PROC(name) \ + name = (PFN_##name)vkGetDeviceProcAddr (device, #name); \ + if (!name) { SetError (std::string ("Missing Vulkan device proc: ") + #name); return false; } + + LIME_LOAD_DEVICE_PROC (vkAllocateMemory); + LIME_LOAD_DEVICE_PROC (vkAcquireNextImageKHR); + LIME_LOAD_DEVICE_PROC (vkAllocateCommandBuffers); + LIME_LOAD_DEVICE_PROC (vkBeginCommandBuffer); + LIME_LOAD_DEVICE_PROC (vkBindBufferMemory); + LIME_LOAD_DEVICE_PROC (vkCmdCopyBufferToImage); + LIME_LOAD_DEVICE_PROC (vkCmdBeginRenderPass); + LIME_LOAD_DEVICE_PROC (vkCmdEndRenderPass); + LIME_LOAD_DEVICE_PROC (vkCmdPipelineBarrier); + LIME_LOAD_DEVICE_PROC (vkCreateBuffer); + LIME_LOAD_DEVICE_PROC (vkCreateCommandPool); + LIME_LOAD_DEVICE_PROC (vkCreateFence); + LIME_LOAD_DEVICE_PROC (vkCreateFramebuffer); + LIME_LOAD_DEVICE_PROC (vkCreateImageView); + LIME_LOAD_DEVICE_PROC (vkCreateRenderPass); + LIME_LOAD_DEVICE_PROC (vkCreateSemaphore); + LIME_LOAD_DEVICE_PROC (vkCreateSwapchainKHR); + LIME_LOAD_DEVICE_PROC (vkDestroyCommandPool); + LIME_LOAD_DEVICE_PROC (vkDestroyBuffer); + LIME_LOAD_DEVICE_PROC (vkDestroyDevice); + LIME_LOAD_DEVICE_PROC (vkDestroyFence); + LIME_LOAD_DEVICE_PROC (vkDestroyFramebuffer); + LIME_LOAD_DEVICE_PROC (vkDestroyImageView); + LIME_LOAD_DEVICE_PROC (vkDestroyRenderPass); + LIME_LOAD_DEVICE_PROC (vkDestroySemaphore); + LIME_LOAD_DEVICE_PROC (vkDestroySwapchainKHR); + LIME_LOAD_DEVICE_PROC (vkDeviceWaitIdle); + LIME_LOAD_DEVICE_PROC (vkEndCommandBuffer); + LIME_LOAD_DEVICE_PROC (vkFreeMemory); + LIME_LOAD_DEVICE_PROC (vkGetBufferMemoryRequirements); + LIME_LOAD_DEVICE_PROC (vkGetSwapchainImagesKHR); + LIME_LOAD_DEVICE_PROC (vkMapMemory); + LIME_LOAD_DEVICE_PROC (vkQueuePresentKHR); + LIME_LOAD_DEVICE_PROC (vkQueueSubmit); + LIME_LOAD_DEVICE_PROC (vkResetCommandPool); + LIME_LOAD_DEVICE_PROC (vkResetFences); + LIME_LOAD_DEVICE_PROC (vkUnmapMemory); + LIME_LOAD_DEVICE_PROC (vkWaitForFences); + + #undef LIME_LOAD_DEVICE_PROC + + return true; + + } + + + bool VulkanRenderer::LoadGlobalProcs () { + + vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)window->GetVulkanInstanceProcAddr (); + + if (!vkGetInstanceProcAddr) { + + SetError ("SDL did not expose vkGetInstanceProcAddr"); + return false; + + } + + #define LIME_LOAD_GLOBAL_PROC(name) \ + name = (PFN_##name)vkGetInstanceProcAddr (VK_NULL_HANDLE, #name); \ + if (!name) { SetError (std::string ("Missing Vulkan global proc: ") + #name); return false; } + + LIME_LOAD_GLOBAL_PROC (vkCreateInstance); + LIME_LOAD_GLOBAL_PROC (vkEnumerateInstanceExtensionProperties); + vkEnumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion)vkGetInstanceProcAddr (VK_NULL_HANDLE, "vkEnumerateInstanceVersion"); + + #undef LIME_LOAD_GLOBAL_PROC + + return true; + + } + + + bool VulkanRenderer::LoadInstanceProcs () { + + #define LIME_LOAD_INSTANCE_PROC(name) \ + name = (PFN_##name)vkGetInstanceProcAddr (instance, #name); \ + if (!name) { SetError (std::string ("Missing Vulkan instance proc: ") + #name); return false; } + + LIME_LOAD_INSTANCE_PROC (vkCreateDevice); + LIME_LOAD_INSTANCE_PROC (vkDestroyInstance); + LIME_LOAD_INSTANCE_PROC (vkDestroySurfaceKHR); + LIME_LOAD_INSTANCE_PROC (vkEnumerateDeviceExtensionProperties); + LIME_LOAD_INSTANCE_PROC (vkEnumeratePhysicalDevices); + LIME_LOAD_INSTANCE_PROC (vkGetDeviceProcAddr); + LIME_LOAD_INSTANCE_PROC (vkGetPhysicalDeviceMemoryProperties); + LIME_LOAD_INSTANCE_PROC (vkGetPhysicalDeviceProperties); + LIME_LOAD_INSTANCE_PROC (vkGetPhysicalDeviceQueueFamilyProperties); + LIME_LOAD_INSTANCE_PROC (vkGetPhysicalDeviceSurfaceCapabilitiesKHR); + LIME_LOAD_INSTANCE_PROC (vkGetPhysicalDeviceSurfaceFormatsKHR); + LIME_LOAD_INSTANCE_PROC (vkGetPhysicalDeviceSurfacePresentModesKHR); + LIME_LOAD_INSTANCE_PROC (vkGetPhysicalDeviceSurfaceSupportKHR); + LIME_LOAD_INSTANCE_PROC (vkGetDeviceQueue); + + #undef LIME_LOAD_INSTANCE_PROC + + return true; + + } + + + bool VulkanRenderer::PickPhysicalDevice () { + + uint32_t deviceCount = 0; + VkResult result = vkEnumeratePhysicalDevices (instance, &deviceCount, 0); + if (result != VK_SUCCESS || deviceCount == 0) { + + SetError ("No Vulkan physical devices were found"); + return false; + + } + + std::vector physicalDevices (deviceCount); + vkEnumeratePhysicalDevices (instance, &deviceCount, physicalDevices.data ()); + + for (size_t deviceIndex = 0; deviceIndex < physicalDevices.size (); ++deviceIndex) { + + VkPhysicalDevice candidate = physicalDevices[deviceIndex]; + + uint32_t extensionCount = 0; + vkEnumerateDeviceExtensionProperties (candidate, 0, &extensionCount, 0); + std::vector extensions (extensionCount); + if (extensionCount > 0) { + + vkEnumerateDeviceExtensionProperties (candidate, 0, &extensionCount, extensions.data ()); + + } + + bool hasSwapchain = false; + bool hasPortabilitySubset = false; + + for (size_t i = 0; i < extensions.size (); ++i) { + + if (strcmp (extensions[i].extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) { + + hasSwapchain = true; + + } + + #ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME + if (strcmp (extensions[i].extensionName, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0) { + + hasPortabilitySubset = true; + + } + #endif + + } + + if (!hasSwapchain) { + + continue; + + } + + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties (candidate, &queueFamilyCount, 0); + if (queueFamilyCount == 0) { + + continue; + + } + + std::vector queueFamilies (queueFamilyCount); + vkGetPhysicalDeviceQueueFamilyProperties (candidate, &queueFamilyCount, queueFamilies.data ()); + + for (uint32_t queueIndex = 0; queueIndex < queueFamilyCount; ++queueIndex) { + + VkBool32 supportsPresent = VK_FALSE; + vkGetPhysicalDeviceSurfaceSupportKHR (candidate, queueIndex, surface, &supportsPresent); + + if ((queueFamilies[queueIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT) && supportsPresent) { + + physicalDevice = candidate; + queueFamilyIndex = queueIndex; + portabilitySubsetSupported = hasPortabilitySubset; + vkGetPhysicalDeviceProperties (physicalDevice, &physicalDeviceProperties); + return true; + + } + + } + + } + + SetError ("Failed to find a Vulkan physical device with graphics and present support"); + return false; + + } + + + bool VulkanRenderer::RecordCommandBuffer (uint32_t imageIndex, float red, float green, float blue, float alpha) { + + if (imageIndex >= commandBuffers.size () || imageIndex >= framebuffers.size ()) { + + SetError ("Invalid Vulkan swapchain image index"); + return false; + + } + + VkCommandBuffer commandBuffer = commandBuffers[imageIndex]; + + VkCommandBufferBeginInfo beginInfo; + memset (&beginInfo, 0, sizeof (beginInfo)); + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + + VkResult result = vkBeginCommandBuffer (commandBuffer, &beginInfo); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkBeginCommandBuffer failed: ") + VulkanResultToString (result)); + return false; + + } + + VkClearValue clearValue; + clearValue.color.float32[0] = red; + clearValue.color.float32[1] = green; + clearValue.color.float32[2] = blue; + clearValue.color.float32[3] = alpha; + + VkRenderPassBeginInfo renderPassInfo; + memset (&renderPassInfo, 0, sizeof (renderPassInfo)); + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + renderPassInfo.renderPass = renderPass; + renderPassInfo.framebuffer = framebuffers[imageIndex]; + renderPassInfo.renderArea.offset.x = 0; + renderPassInfo.renderArea.offset.y = 0; + renderPassInfo.renderArea.extent = swapchainExtent; + renderPassInfo.clearValueCount = 1; + renderPassInfo.pClearValues = &clearValue; + + vkCmdBeginRenderPass (commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); + vkCmdEndRenderPass (commandBuffer); + + uint32_t copyWidth = overlayWidth; + uint32_t copyHeight = overlayHeight; + int copyX = overlayX; + int copyY = overlayY; + VkDeviceSize bufferOffset = 0; + bool hasOverlayCopy = overlayEnabled && overlayBuffer && overlayMappedData && overlayWidth > 0 && overlayHeight > 0; + + if (hasOverlayCopy) { + + if (copyX < 0) { + + uint32_t clipped = (uint32_t)(-copyX); + if (clipped >= copyWidth) { + + hasOverlayCopy = false; + + } else { + + bufferOffset += (VkDeviceSize)clipped * 4; + copyWidth -= clipped; + copyX = 0; + + } + + } + + if (hasOverlayCopy && copyY < 0) { + + uint32_t clipped = (uint32_t)(-copyY); + if (clipped >= copyHeight) { + + hasOverlayCopy = false; + + } else { + + bufferOffset += (VkDeviceSize)clipped * (VkDeviceSize)overlayWidth * 4; + copyHeight -= clipped; + copyY = 0; + + } + + } + + if (hasOverlayCopy && + (copyX >= (int)swapchainExtent.width || copyY >= (int)swapchainExtent.height)) { + + hasOverlayCopy = false; + + } + + if (hasOverlayCopy && (uint32_t)copyX + copyWidth > swapchainExtent.width) { + + copyWidth = swapchainExtent.width - (uint32_t)copyX; + + } + + if (hasOverlayCopy && (uint32_t)copyY + copyHeight > swapchainExtent.height) { + + copyHeight = swapchainExtent.height - (uint32_t)copyY; + + } + + hasOverlayCopy = hasOverlayCopy && copyWidth > 0 && copyHeight > 0; + + } + + VkImageMemoryBarrier imageBarrier; + memset (&imageBarrier, 0, sizeof (imageBarrier)); + imageBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imageBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageBarrier.image = swapchainImages[imageIndex]; + imageBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageBarrier.subresourceRange.baseMipLevel = 0; + imageBarrier.subresourceRange.levelCount = 1; + imageBarrier.subresourceRange.baseArrayLayer = 0; + imageBarrier.subresourceRange.layerCount = 1; + + if (hasOverlayCopy) { + + imageBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + imageBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + imageBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + + vkCmdPipelineBarrier ( + commandBuffer, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, + 0, 0, + 0, 0, + 1, &imageBarrier + ); + + VkBufferImageCopy copyRegion; + memset (©Region, 0, sizeof (copyRegion)); + copyRegion.bufferOffset = bufferOffset; + copyRegion.bufferRowLength = overlayWidth; + copyRegion.bufferImageHeight = overlayHeight; + copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copyRegion.imageSubresource.mipLevel = 0; + copyRegion.imageSubresource.baseArrayLayer = 0; + copyRegion.imageSubresource.layerCount = 1; + copyRegion.imageOffset.x = copyX; + copyRegion.imageOffset.y = copyY; + copyRegion.imageOffset.z = 0; + copyRegion.imageExtent.width = copyWidth; + copyRegion.imageExtent.height = copyHeight; + copyRegion.imageExtent.depth = 1; + + vkCmdCopyBufferToImage (commandBuffer, overlayBuffer, swapchainImages[imageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); + + imageBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + imageBarrier.dstAccessMask = 0; + imageBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + imageBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + + vkCmdPipelineBarrier ( + commandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, + 0, 0, + 0, 0, + 1, &imageBarrier + ); + + } else { + + imageBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imageBarrier.dstAccessMask = 0; + imageBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + imageBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + + vkCmdPipelineBarrier ( + commandBuffer, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, + 0, 0, + 0, 0, + 1, &imageBarrier + ); + + } + + result = vkEndCommandBuffer (commandBuffer); + if (result != VK_SUCCESS) { + + SetError (std::string ("vkEndCommandBuffer failed: ") + VulkanResultToString (result)); + return false; + + } + + return true; + + } + + + bool VulkanRenderer::RecreateSwapchain () { + + if (!device) { + + return false; + + } + + int drawableWidth = 0; + int drawableHeight = 0; + window->GetVulkanDrawableSize (&drawableWidth, &drawableHeight); + if (drawableWidth <= 0 || drawableHeight <= 0) { + + if (swapchain || !swapchainImages.empty () || !swapchainImageViews.empty () || !framebuffers.empty () || !commandBuffers.empty () || commandPool || renderPass) { + + if (vkDeviceWaitIdle (device) != VK_SUCCESS) { + + SetError ("vkDeviceWaitIdle failed while suspending the swapchain"); + return false; + + } + + DestroySwapchainResources (); + + } + + swapchainExtent.width = 0; + swapchainExtent.height = 0; + swapchainDirty = true; + lastError.clear (); + return true; + + } + + if (vkDeviceWaitIdle (device) != VK_SUCCESS) { + + SetError ("vkDeviceWaitIdle failed during swapchain recreation"); + return false; + + } + + DestroySwapchainResources (); + if (!CreateSwapchainResources ()) { + + swapchainDirty = true; + return false; + + } + + swapchainDirty = (swapchain == VK_NULL_HANDLE || swapchainExtent.width == 0 || swapchainExtent.height == 0); + lastError.clear (); + return true; + + } + + + void VulkanRenderer::SetError (const std::string& value) { + + lastError = value; + + } + + +} diff --git a/project/src/media/openal/OpenALBindings.cpp b/project/src/media/openal/OpenALBindings.cpp index a26c5c679a..cd682d444d 100644 --- a/project/src/media/openal/OpenALBindings.cpp +++ b/project/src/media/openal/OpenALBindings.cpp @@ -170,6 +170,7 @@ namespace lime { } */ + void lime_al_auxf (value aux, int param, float value) { #ifdef LIME_OPENALSOFT @@ -2317,6 +2318,30 @@ namespace lime { } + bool lime_alc_is_extension_present (value device, HxString extname) { + + #ifdef LIME_OPENALSOFT + ALCdevice* alcDevice = val_is_null (device) ? NULL : (ALCdevice*)val_data (device); + return extname.__s ? alcIsExtensionPresent (alcDevice, extname.__s) : false; + #else + return false; + #endif + + } + + + HL_PRIM bool HL_NAME(hl_alc_is_extension_present) (HL_CFFIPointer* device, hl_vstring* extname) { + + #ifdef LIME_OPENALSOFT + ALCdevice* alcDevice = device ? (ALCdevice*)device->ptr : NULL; + return extname ? alcIsExtensionPresent (alcDevice, hl_to_utf8 (extname->bytes)) : false; + #else + return false; + #endif + + } + + bool lime_al_is_filter (value filter) { #ifdef LIME_OPENALSOFT @@ -3379,7 +3404,7 @@ namespace lime { value lime_alc_get_string (value device, int param) { - ALCdevice* alcDevice = (ALCdevice*)val_data (device); + ALCdevice* alcDevice = val_is_null (device) ? NULL : (ALCdevice*)val_data (device); const char* result = alcGetString (alcDevice, param); return result ? alloc_string (result) : alloc_null (); @@ -3388,8 +3413,9 @@ namespace lime { HL_PRIM vbyte* HL_NAME(hl_alc_get_string) (HL_CFFIPointer* device, int param) { - ALCdevice* alcDevice = device ? (ALCdevice*)device->ptr : 0; + ALCdevice* alcDevice = device ? (ALCdevice*)device->ptr : NULL; const char* result = alcGetString (alcDevice, param); + if (!result) return 0; int length = strlen (result); char* _result = (char*)malloc (length + 1); strcpy (_result, result); @@ -3512,6 +3538,101 @@ namespace lime { } + value lime_alc_capture_open_device (HxString devicename, int frequency, int format, int buffersize) { + + ALCdevice* alcDevice = alcCaptureOpenDevice (devicename.__s, frequency, format, buffersize); + + value ptr = CFFIPointer (alcDevice, gc_alc_object); + alcObjects[alcDevice] = ptr; + return ptr; + + } + + + HL_PRIM HL_CFFIPointer* HL_NAME(hl_alc_capture_open_device) (hl_vstring* devicename, int frequency, int format, int buffersize) { + + ALCdevice* alcDevice = alcCaptureOpenDevice (devicename ? (char*)hl_to_utf8 ((const uchar*)devicename->bytes) : 0, frequency, format, buffersize); + + HL_CFFIPointer* ptr = HLCFFIPointer (alcDevice, (hl_finalizer)hl_gc_alc_object); + alcObjects[alcDevice] = ptr; + return ptr; + + } + + + bool lime_alc_capture_close_device (value device) { + + al_gc_mutex.Lock (); + ALCdevice* alcDevice = (ALCdevice*)val_data (device); + alcObjects.erase (alcDevice); + al_gc_mutex.Unlock (); + + return alcCaptureCloseDevice (alcDevice); + + } + + + HL_PRIM bool HL_NAME(hl_alc_capture_close_device) (HL_CFFIPointer* device) { + + al_gc_mutex.Lock (); + ALCdevice* alcDevice = (ALCdevice*)device->ptr; + alcObjects.erase (alcDevice); + al_gc_mutex.Unlock (); + + return alcCaptureCloseDevice (alcDevice); + + } + + + void lime_alc_capture_start (value device) { + + ALCdevice* alcDevice = (ALCdevice*)val_data (device); + alcCaptureStart (alcDevice); + + } + + + HL_PRIM void HL_NAME(hl_alc_capture_start) (HL_CFFIPointer* device) { + + ALCdevice* alcDevice = (ALCdevice*)device->ptr; + alcCaptureStart (alcDevice); + + } + + + void lime_alc_capture_stop (value device) { + + ALCdevice* alcDevice = (ALCdevice*)val_data (device); + alcCaptureStop (alcDevice); + + } + + + HL_PRIM void HL_NAME(hl_alc_capture_stop) (HL_CFFIPointer* device) { + + ALCdevice* alcDevice = (ALCdevice*)device->ptr; + alcCaptureStop (alcDevice); + + } + + + void lime_alc_capture_samples (value device, value buffer, int samples) { + + ALCdevice* alcDevice = (ALCdevice*)val_data (device); + Bytes bytes (buffer); + alcCaptureSamples (alcDevice, bytes.b, samples); + + } + + + HL_PRIM void HL_NAME(hl_alc_capture_samples) (HL_CFFIPointer* device, Bytes* buffer, int samples) { + + ALCdevice* alcDevice = (ALCdevice*)device->ptr; + alcCaptureSamples (alcDevice, buffer->b, samples); + + } + + DEFINE_PRIME3v (lime_al_auxf); @@ -3587,6 +3708,7 @@ namespace lime { DEFINE_PRIME1 (lime_al_is_effect); DEFINE_PRIME1 (lime_al_is_enabled); DEFINE_PRIME1 (lime_al_is_extension_present); + DEFINE_PRIME2 (lime_alc_is_extension_present); DEFINE_PRIME1 (lime_al_is_filter); DEFINE_PRIME1 (lime_al_is_source); DEFINE_PRIME4v (lime_al_listener3f); @@ -3628,6 +3750,11 @@ namespace lime { DEFINE_PRIME1v (lime_alc_process_context); DEFINE_PRIME1v (lime_alc_resume_device); DEFINE_PRIME1v (lime_alc_suspend_context); + DEFINE_PRIME4 (lime_alc_capture_open_device); + DEFINE_PRIME1 (lime_alc_capture_close_device); + DEFINE_PRIME1v (lime_alc_capture_start); + DEFINE_PRIME1v (lime_alc_capture_stop); + DEFINE_PRIME3v (lime_alc_capture_samples); #define _TBYTES _OBJ (_I32 _BYTES) @@ -3711,6 +3838,7 @@ namespace lime { DEFINE_HL_PRIM (_BOOL, hl_al_is_effect, _TCFFIPOINTER); DEFINE_HL_PRIM (_BOOL, hl_al_is_enabled, _I32); DEFINE_HL_PRIM (_BOOL, hl_al_is_extension_present, _STRING); + DEFINE_HL_PRIM (_BOOL, hl_alc_is_extension_present, _TCFFIPOINTER _STRING); DEFINE_HL_PRIM (_BOOL, hl_al_is_filter, _TCFFIPOINTER); DEFINE_HL_PRIM (_BOOL, hl_al_is_source, _TCFFIPOINTER); DEFINE_HL_PRIM (_VOID, hl_al_listener3f, _I32 _F32 _F32 _F32); @@ -3752,6 +3880,11 @@ namespace lime { DEFINE_HL_PRIM (_VOID, hl_alc_process_context, _TCFFIPOINTER); DEFINE_HL_PRIM (_VOID, hl_alc_resume_device, _TCFFIPOINTER); DEFINE_HL_PRIM (_VOID, hl_alc_suspend_context, _TCFFIPOINTER); + DEFINE_HL_PRIM (_TCFFIPOINTER, hl_alc_capture_open_device, _STRING _I32 _I32 _I32); + DEFINE_HL_PRIM (_BOOL, hl_alc_capture_close_device, _TCFFIPOINTER); + DEFINE_HL_PRIM (_VOID, hl_alc_capture_start, _TCFFIPOINTER); + DEFINE_HL_PRIM (_VOID, hl_alc_capture_stop, _TCFFIPOINTER); + DEFINE_HL_PRIM (_VOID, hl_alc_capture_samples, _TCFFIPOINTER _TBYTES _I32); } diff --git a/project/src/ui/FileDialog.cpp b/project/src/ui/FileDialog.cpp index b4ce57fdd1..ec561973b1 100644 --- a/project/src/ui/FileDialog.cpp +++ b/project/src/ui/FileDialog.cpp @@ -6,298 +6,164 @@ #include +#ifdef HX_WINDOWS +#define tinyfd_selectFolderDialog tinyfd_selectFolderDialogW +#define tinyfd_openFileDialog tinyfd_openFileDialogW +#define tinyfd_saveFileDialog tinyfd_saveFileDialogW -namespace lime { - - - std::string* wstring_to_string (std::wstring* source) { +#define FD_STR(str) L##str +#else +#define FD_STR(str) str +#endif - if (!source) return NULL; +using char_t = lime::FileDialog::char_t; +using string_t = std::basic_string; - int size = std::wcslen (source->c_str ()); - char* temp = (char*)malloc (size + 1); - std::wcstombs (temp, source->c_str (), size); - temp[size] = '\0'; - - std::string* data = new std::string (temp); - free (temp); - return data; +namespace lime { + static bool is_null_or_empty (const char_t* str) { + return str == nullptr || str[0] == 0; } + static string_t normalize_filter (const string_t& filter) { - std::wstring* FileDialog::OpenDirectory (std::wstring* title, std::wstring* filter, std::wstring* defaultPath) { - - // TODO: Filter? - - #ifdef HX_WINDOWS - - const wchar_t* path = tinyfd_selectFolderDialogW (title ? title->c_str () : 0, defaultPath ? defaultPath->c_str () : 0); + if (filter.empty () || filter.find (FD_STR('*')) != string_t::npos || filter.find (FD_STR('?')) != string_t::npos) { - if (path && std::wcslen(path) > 0) { - - std::wstring* _path = new std::wstring (path); - return _path; + return filter; } - #else - - std::string* _title = wstring_to_string (title); - //std::string* _filter = wstring_to_string (filter); - std::string* _defaultPath = wstring_to_string (defaultPath); - - const char* path = tinyfd_selectFolderDialog (_title ? _title->c_str () : NULL, _defaultPath ? _defaultPath->c_str () : NULL); - - if (_title) delete _title; - //if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; - - if (path && std::strlen(path) > 0) { + if (filter[0] == FD_STR('.')) { - std::string _path = std::string (path); - std::wstring* __path = new std::wstring (_path.begin (), _path.end ()); - return __path; + return string_t (FD_STR("*")) + filter; } - #endif - - return 0; + return string_t (FD_STR("*.")) + filter; } + static std::vector normalize_filters (const char_t* filter) { - std::wstring* FileDialog::OpenFile (std::wstring* title, std::wstring* filter, std::wstring* defaultPath) { + std::vector filters; - #ifdef HX_WINDOWS - - std::vector filters_vec; if (filter) { - std::wstring temp (L"*."); - std::wstring line; - std::wstringstream ss(*filter); - while(std::getline(ss, line, L',')) { - filters_vec.push_back(temp + line); - } - } - const int numFilters = filter ? filters_vec.size() : 1; - const wchar_t **filters = new const wchar_t*[numFilters]; - if (filter && numFilters > 0) { - for (int index = 0; index < numFilters; index++) { - filters[index] = const_cast(filters_vec[index].c_str()); - } - } else { - filters[0] = NULL; - } + string_t line; + std::basic_stringstream ss (filter); - const wchar_t* path = tinyfd_openFileDialogW (title ? title->c_str () : 0, defaultPath ? defaultPath->c_str () : 0, filter ? numFilters : 0, filter ? filters : NULL, NULL, 0); + while (std::getline (ss, line, FD_STR(','))) { - delete[] filters; + filters.push_back (normalize_filter (line)); - if (path && std::wcslen(path) > 0) { - - std::wstring* _path = new std::wstring (path); - return _path; + } } - #else + return filters; - std::string* _title = wstring_to_string (title); - std::string* _filter = wstring_to_string (filter); - std::string* _defaultPath = wstring_to_string (defaultPath); - - std::vector filters_vec; - if (_filter) { - std::string line; - std::stringstream ss(*_filter); - while(std::getline(ss, line, ',')) { - line.insert (0, "*."); - filters_vec.push_back(line); - } - } - - const int numFilters = _filter ? filters_vec.size() : 1; - const char **filters = new const char*[numFilters]; - if (_filter && numFilters > 0) { - for (int index = 0; index < numFilters; index++) { - filters[index] = const_cast(filters_vec[index].c_str()); - } - } else { - filters[0] = NULL; - } + } - const char* path = tinyfd_openFileDialog (_title ? _title->c_str () : NULL, _defaultPath ? _defaultPath->c_str () : NULL, _filter ? numFilters : 0, _filter ? filters : NULL, NULL, 0); + const char_t* FileDialog::OpenDirectory (const char_t* title, const char_t* filter, const char_t* defaultPath) { - delete[] filters; + // TODO: Filter? - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + const char_t* path = tinyfd_selectFolderDialog(title, defaultPath); - if (path && std::strlen(path) > 0) { + if (!is_null_or_empty(path)) { - std::string _path = std::string (path); - std::wstring* __path = new std::wstring (_path.begin (), _path.end ()); - return __path; + return path; } - #endif - return 0; } - void FileDialog::OpenFiles (std::vector* files, std::wstring* title, std::wstring* filter, std::wstring* defaultPath) { - - std::wstring* __paths = 0; + const char_t* FileDialog::OpenFile (const char_t* title, const char_t* filter, const char_t* defaultPath) { - #ifdef HX_WINDOWS + std::vector filters_vec = normalize_filters (filter); - std::vector filters_vec; - if (filter) { - std::wstring temp (L"*."); - std::wstring line; - std::wstringstream ss(*filter); - while(std::getline(ss, line, L',')) { - filters_vec.push_back(temp + line); - } - } - - const int numFilters = filter ? filters_vec.size() : 1; - const wchar_t **filters = new const wchar_t*[numFilters]; - if (filter && numFilters > 0) { + const int numFilters = filters_vec.size (); + const char_t **filters = numFilters > 0 ? new const char_t*[numFilters] : NULL; + if (numFilters > 0) { for (int index = 0; index < numFilters; index++) { - filters[index] = const_cast(filters_vec[index].c_str()); + filters[index] = filters_vec[index].c_str(); } - } else { - filters[0] = NULL; } - const wchar_t* paths = tinyfd_openFileDialogW (title ? title->c_str () : 0, defaultPath ? defaultPath->c_str () : 0, filter ? numFilters : 0, filter ? filters : NULL, NULL, 1); + const char_t* path = tinyfd_openFileDialog (title, defaultPath, numFilters, filters, NULL, 0); delete[] filters; - if (paths) { + if (!is_null_or_empty(path)) { - __paths = new std::wstring (paths); + return path; } - #else + return 0; - std::string* _title = wstring_to_string (title); - std::string* _filter = wstring_to_string (filter); - std::string* _defaultPath = wstring_to_string (defaultPath); + } - std::vector filters_vec; - if (_filter) { - std::string line; - std::stringstream ss(*_filter); - while(std::getline(ss, line, ',')) { - line.insert (0, "*."); - filters_vec.push_back(line); - } - } - const int numFilters = _filter ? filters_vec.size() : 1; - const char **filters = new const char*[numFilters]; - if (_filter && numFilters > 0) { + std::vector FileDialog::OpenFiles (const char_t* title, const char_t* filter, const char_t* defaultPath) { + std::vector files; + + std::vector filters_vec = normalize_filters (filter); + + const int numFilters = filters_vec.size (); + const char_t **filters = numFilters > 0 ? new const char_t*[numFilters] : NULL; + if (numFilters > 0) { for (int index = 0; index < numFilters; index++) { - filters[index] = const_cast(filters_vec[index].c_str()); + filters[index] = filters_vec[index].c_str(); } - } else { - filters[0] = NULL; } - const char* paths = tinyfd_openFileDialog (_title ? _title->c_str () : NULL, _defaultPath ? _defaultPath->c_str () : NULL, _filter ? numFilters : 0, _filter ? filters : NULL, NULL, 1); + const char_t* paths = tinyfd_openFileDialog (title, defaultPath, numFilters, filters, NULL, 1); delete[] filters; - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; - - if (paths) { - - std::string _paths = std::string (paths); - __paths = new std::wstring (_paths.begin (), _paths.end ()); - - } - - #endif - - if (__paths) { + if (!is_null_or_empty(paths)) { - std::wstring sep = L"|"; + char_t sep = FD_STR('|'); - std::size_t start = 0, end = 0; + const char_t* start = paths, + * cur = paths; - while ((end = __paths->find (sep, start)) != std::wstring::npos) { - - files->push_back (new std::wstring (__paths->substr (start, end - start).c_str ())); - start = end + 1; + while (*cur) { + if (*cur == sep) { + files.emplace_back(start, cur - start); + start = cur + 1; + } + cur++; } - files->push_back (new std::wstring (__paths->substr (start).c_str ())); + files.emplace_back(start, cur - start); } - } - - - std::wstring* FileDialog::SaveFile (std::wstring* title, std::wstring* filter, std::wstring* defaultPath) { - - #ifdef HX_WINDOWS - - std::wstring temp (L"*."); - const wchar_t* filters[] = { filter ? (temp + *filter).c_str () : NULL }; - - const wchar_t* path = tinyfd_saveFileDialogW (title ? title->c_str () : 0, defaultPath ? defaultPath->c_str () : 0, filter ? 1 : 0, filter ? filters : NULL, NULL); - - if (path && std::wcslen(path) > 0) { - - std::wstring* _path = new std::wstring (path); - return _path; + return files; - } - - #else - - std::string* _title = wstring_to_string (title); - std::string* _filter = wstring_to_string (filter); - std::string* _defaultPath = wstring_to_string (defaultPath); - - const char* filters[] = { NULL }; - - if (_filter) { + } - _filter->insert (0, "*."); - filters[0] = _filter->c_str (); - } + const char_t* FileDialog::SaveFile (const char_t* title, const char_t* filter, const char_t* defaultPath) { - const char* path = tinyfd_saveFileDialog (_title ? _title->c_str () : NULL, _defaultPath ? _defaultPath->c_str () : NULL, _filter ? 1 : 0, _filter ? filters : NULL, NULL); + std::vector filters_vec = normalize_filters (filter); + const int numFilters = filters_vec.size () > 0 ? 1 : 0; + const char_t* filters[] = { numFilters > 0 ? filters_vec[0].c_str () : NULL }; - if (_title) delete _title; - if (_filter) delete _filter; - if (_defaultPath) delete _defaultPath; + const char_t* path = tinyfd_saveFileDialog (title, defaultPath, numFilters, numFilters > 0 ? filters : NULL, NULL); - if (path && std::strlen(path) > 0) { + if (!is_null_or_empty(path)) { - std::string _path = std::string (path); - std::wstring* __path = new std::wstring (_path.begin (), _path.end ()); - return __path; + return path; } - #endif - return 0; } diff --git a/project/src/ui/GamepadEvent.cpp b/project/src/ui/GamepadEvent.cpp index 64fa1c5384..6c4b3fd74b 100644 --- a/project/src/ui/GamepadEvent.cpp +++ b/project/src/ui/GamepadEvent.cpp @@ -11,6 +11,7 @@ namespace lime { static double id_axis; static int id_button; static int id_id; + static int id_timestamp; static int id_type; static int id_value; static bool init = false; @@ -22,6 +23,7 @@ namespace lime { axisValue = 0; button = 0; id = 0; + timestamp = 0; type = GAMEPAD_AXIS_MOVE; } @@ -38,6 +40,7 @@ namespace lime { id_axis = val_id ("axis"); id_button = val_id ("button"); id_id = val_id ("id"); + id_timestamp = val_id ("timestamp"); id_type = val_id ("type"); id_value = val_id ("axisValue"); init = true; @@ -49,6 +52,7 @@ namespace lime { alloc_field (object, id_axis, alloc_int (event->axis)); alloc_field (object, id_button, alloc_int (event->button)); alloc_field (object, id_id, alloc_int (event->id)); + alloc_field (object, id_timestamp, alloc_int (event->timestamp)); alloc_field (object, id_type, alloc_int (event->type)); alloc_field (object, id_value, alloc_float (event->axisValue)); @@ -59,6 +63,7 @@ namespace lime { eventObject->axis = event->axis; eventObject->button = event->button; eventObject->id = event->id; + eventObject->timestamp = event->timestamp; eventObject->type = event->type; eventObject->axisValue = event->axisValue; @@ -71,4 +76,4 @@ namespace lime { } -} \ No newline at end of file +} diff --git a/project/src/ui/KeyEvent.cpp b/project/src/ui/KeyEvent.cpp index 42acd15560..871d8d1146 100644 --- a/project/src/ui/KeyEvent.cpp +++ b/project/src/ui/KeyEvent.cpp @@ -10,6 +10,7 @@ namespace lime { static double id_keyCode; static int id_modifier; + static int id_timestamp; static int id_type; static int id_windowID; static bool init = false; @@ -19,6 +20,7 @@ namespace lime { keyCode = 0; modifier = 0; + timestamp = 0; type = KEY_DOWN; windowID = 0; @@ -35,6 +37,7 @@ namespace lime { id_keyCode = val_id ("keyCode"); id_modifier = val_id ("modifier"); + id_timestamp = val_id ("timestamp"); id_type = val_id ("type"); id_windowID = val_id ("windowID"); init = true; @@ -45,6 +48,7 @@ namespace lime { alloc_field (object, id_keyCode, alloc_float (event->keyCode)); alloc_field (object, id_modifier, alloc_int (event->modifier)); + alloc_field (object, id_timestamp, alloc_int (event->timestamp)); alloc_field (object, id_type, alloc_int (event->type)); alloc_field (object, id_windowID, alloc_int (event->windowID)); @@ -54,6 +58,7 @@ namespace lime { eventObject->keyCode = event->keyCode; eventObject->modifier = event->modifier; + eventObject->timestamp = event->timestamp; eventObject->type = event->type; eventObject->windowID = event->windowID; @@ -66,4 +71,4 @@ namespace lime { } -} \ No newline at end of file +} diff --git a/project/src/utils/Bytes.cpp b/project/src/utils/Bytes.cpp index 83f028f2dd..9cf89dbd40 100644 --- a/project/src/utils/Bytes.cpp +++ b/project/src/utils/Bytes.cpp @@ -40,7 +40,9 @@ namespace lime { Bytes::Bytes () { + #ifndef LIME_HASHLINK _initializeBytes (); + #endif b = 0; length = 0; @@ -122,73 +124,51 @@ namespace lime { if (size != length || (length > 0 && !b)) { - mutex.Lock (); - - if (size <= 0) { - - if (b) { - - if (usingValue.find (this) != usingValue.end ()) { - - usingValue.erase (this); - - } else { - - free (b); - - } + unsigned char* data = 0; + unsigned char* oldB = b; + bool freeOldB = false; - } else if (usingValue.find (this) != usingValue.end ()) { + if (size > 0) { - usingValue.erase (this); - - } - - b = 0; - length = 0; - - } else { - - unsigned char* data = (unsigned char*)malloc (sizeof (char) * size); + data = (unsigned char*)malloc (sizeof (char) * size); if (!data) { - mutex.Unlock (); return false; } - if (b) { + if (b && length) { - if (length) { + memcpy (data, b, length < size ? length : size); + + } - memcpy (data, b, length < size ? length : size); + } - } + mutex.Lock (); - if (usingValue.find (this) != usingValue.end ()) { + if (usingValue.find (this) != usingValue.end ()) { - usingValue.erase (this); + usingValue.erase (this); - } else { + } else if (oldB) { - free (b); + freeOldB = true; - } + } - } else if (usingValue.find (this) != usingValue.end ()) { + b = data; + length = size > 0 ? size : 0; - usingValue.erase (this); + mutex.Unlock (); - } + if (freeOldB) { - b = data; - length = size; + free (oldB); } - mutex.Unlock (); - } return (size == length || (size <= 0 && length == 0)); @@ -203,22 +183,22 @@ namespace lime { } - void Bytes::Set(value bytes) { - + void Bytes::Set(value bytes) { + int newLength = 0; unsigned char* newB = 0; bool isNull = val_is_null(bytes); - + if (!isNull) { - + //here we can extract the values before calling our mutex to avoid potential deadlock or contention value lengthVal = val_field(bytes, id_length); value bVal = val_field(bytes, id_b); - + newLength = val_int(lengthVal); - + if (newLength > 0) { - + if (val_is_string(bVal)) { newB = (unsigned char*)val_string(bVal); } else { @@ -226,7 +206,7 @@ namespace lime { } } } - + //and now it should be save to lock mutex.Lock(); @@ -251,7 +231,7 @@ namespace lime { usingHaxeValue = false; } - + if (isNull) { length = 0; b = 0; @@ -261,7 +241,7 @@ namespace lime { length = newLength; b = newB; } - + mutex.Unlock(); } diff --git a/run.n b/run.n index deae46fd3a..1436727e31 100644 Binary files a/run.n and b/run.n differ diff --git a/src/lime/_internal/backend/air/AIRWindow.hx b/src/lime/_internal/backend/air/AIRWindow.hx index 0c5e022fda..195d78fbc4 100644 --- a/src/lime/_internal/backend/air/AIRWindow.hx +++ b/src/lime/_internal/backend/air/AIRWindow.hx @@ -187,7 +187,8 @@ class AIRWindow extends FlashWindow if (parent.application.window == parent) { var newDeviceOrientation:Orientation = UNKNOWN; - switch (parent.stage.deviceOrientation) { + switch (parent.stage.deviceOrientation) + { case DEFAULT: newDeviceOrientation = PORTRAIT; case UPSIDE_DOWN: @@ -202,7 +203,8 @@ class AIRWindow extends FlashWindow parent.application.onDeviceOrientationChange.dispatch(newDeviceOrientation); } var newDisplayOrientation:Orientation = UNKNOWN; - switch (event.afterOrientation) { + switch (event.afterOrientation) + { case DEFAULT: newDisplayOrientation = PORTRAIT; case UPSIDE_DOWN: diff --git a/src/lime/_internal/backend/emscripten/EmscriptenFetch.hx b/src/lime/_internal/backend/emscripten/EmscriptenFetch.hx index 91fc89814e..8777ae7134 100644 --- a/src/lime/_internal/backend/emscripten/EmscriptenFetch.hx +++ b/src/lime/_internal/backend/emscripten/EmscriptenFetch.hx @@ -7,44 +7,46 @@ import cpp.ConstCharStar; @:include("emscripten/fetch.h") @:native -extern class EmscriptenFetch { +extern class EmscriptenFetch +{ + @:native("emscripten_fetch_attr_init") + public static function emscripten_fetch_attr_init(attr:Pointer):Void; - @:native("emscripten_fetch_attr_init") - public static function emscripten_fetch_attr_init(attr:Pointer):Void; + @:native("emscripten_fetch") + public static function emscripten_fetch(attr:Pointer, url:ConstCharStar):Pointer; - @:native("emscripten_fetch") - public static function emscripten_fetch(attr:Pointer, url:ConstCharStar):Pointer; - - @:native("emscripten_fetch_close") - public static function emscripten_fetch_close(fetch:Pointer):Void; + @:native("emscripten_fetch_close") + public static function emscripten_fetch_close(fetch:Pointer):Void; } @:include("emscripten/fetch.h") @:native("emscripten_fetch_attr_t") @:structAccess @:unreflective -extern class EmscriptenFetchAttrType { - public var requestMethod:ConstCharStar; - public var onsuccess:Star->Void; - public var onprogress:Star->Void; - public var onerror:Star->Void; - public var attributes:Int; - public var userData:Star; +extern class EmscriptenFetchAttrType +{ + public var requestMethod:ConstCharStar; + public var onsuccess:Star->Void; + public var onprogress:Star->Void; + public var onerror:Star->Void; + public var attributes:Int; + public var userData:Star; } @:include("emscripten/fetch.h") @:native("emscripten_fetch_t") @:structAccess -extern class EmscriptenFetchType { - public var id:Int; - public var numBytes:Int; - public var dataOffset:Int; - public var totalBytes:Int; - public var url:ConstCharStar; - public var readyState:Int; - public var status:Int; - public var statusText:ConstCharStar; - public var data:Pointer; - public var userData:Star; +extern class EmscriptenFetchType +{ + public var id:Int; + public var numBytes:Int; + public var dataOffset:Int; + public var totalBytes:Int; + public var url:ConstCharStar; + public var readyState:Int; + public var status:Int; + public var statusText:ConstCharStar; + public var data:Pointer; + public var userData:Star; } -#end \ No newline at end of file +#end diff --git a/src/lime/_internal/backend/emscripten/EmscriptenHTTPRequest.hx b/src/lime/_internal/backend/emscripten/EmscriptenHTTPRequest.hx index 435afeff94..bb726fa0a8 100644 --- a/src/lime/_internal/backend/emscripten/EmscriptenHTTPRequest.hx +++ b/src/lime/_internal/backend/emscripten/EmscriptenHTTPRequest.hx @@ -16,238 +16,237 @@ import lime.net.HTTPRequest._HTTPRequestErrorResponse; @:access(lime.graphics.Image) class EmscriptenHTTPRequest { - private static var fetchId:Int = 0; - private static var activeFetches = new Map(); - - private var binary:Bool; - private var parent:_IHTTPRequest; - private var currentFetchId:Int = -1; - - public function new() - { - } - - public function cancel():Void - { - if (currentFetchId >= 0 && activeFetches.exists(currentFetchId)) - { - var context = activeFetches.get(currentFetchId); - if (context != null && context.fetchPtr != null) - { - EmscriptenFetch.emscripten_fetch_close(context.fetchPtr); - } - activeFetches.remove(currentFetchId); - currentFetchId = -1; - } - } - - public function init(parent:_IHTTPRequest):Void - { - this.parent = parent; - } - - public function loadData(uri:String):Future - { - var promise = new Promise(); - binary = true; - __load(uri, promise, LoadType.BINARY); - return promise.future; - } - - public function loadText(uri:String):Future - { - var promise = new Promise(); - binary = false; - __load(uri, promise, LoadType.TEXT); - return promise.future; - } - - private function __load(uri:String, promise:Dynamic, loadType:LoadType):Void - { - var id = fetchId++; - currentFetchId = id; - - var context:FetchContext = { - id: id, - promise: promise, - parent: parent, - loadType: loadType, - binary: binary, - fetchPtr: null - }; - - activeFetches.set(id, context); - - var attr:EmscriptenFetchAttrType = untyped __cpp__("{}"); - var attrPtr:Pointer = Pointer.addressOf(attr); - EmscriptenFetch.emscripten_fetch_attr_init(attrPtr); - - // Set request method - var method = parent.method != null ? Std.string(parent.method) : "GET"; - untyped __cpp__('strcpy({0}, {1})', attr.requestMethod, method); - - // Set callbacks - attr.onsuccess = untyped __cpp__("onFetchSuccess"); - attr.onprogress = untyped __cpp__("onFetchProgress"); - attr.onerror = untyped __cpp__("onFetchError"); - - // Store fetch ID in userData - var idPointer:Star = untyped __cpp__('(int*)malloc(sizeof(int))'); - untyped __cpp__('*{0} = {1}', idPointer, id); - attr.userData = cast idPointer; - - // Set EMSCRIPTEN_FETCH_LOAD_TO_MEMORY - attr.attributes = 1; - - // Start fetch - var fetchPtr = EmscriptenFetch.emscripten_fetch(attrPtr, uri); - context.fetchPtr = fetchPtr; - } - - @:keep - private static function onFetchSuccess(fetchPtr:Star):Void - { - var fetch:EmscriptenFetchType = Pointer.fromStar(fetchPtr).value; - var idPointer:Star = cast fetch.userData; - var id:Int = untyped __cpp__('*(int*){0}', idPointer); - - cpp.Native.free(idPointer); - fetch.userData = null; - - if (!activeFetches.exists(id)) - { - EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); - return; - } - - var context = activeFetches.get(id); - activeFetches.remove(id); - if(context == null) - trace("EmscriptenHTTPRequest.onFetchSuccess: context is null"); - - // Process response - if (context.parent.enableResponseHeaders) - { - context.parent.responseHeaders = []; - // Note: Emscripten Fetch API has limited header access - // You may need to parse headers from fetch.statusText if available - } - - context.parent.responseStatus = fetch.status; - - // Create bytes from fetch data - var bytes:Bytes = null; - if (fetch.numBytes > 0 && fetch.data != null) - { - bytes = Bytes.ofData(cast fetch.data.toUnmanagedArray(fetch.numBytes).copy()); - } - else - { - bytes = Bytes.alloc(0); - } - - EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); - - // Complete promise based on load type - if (fetch.status >= 200 && fetch.status < 400) - { - switch (context.loadType) - { - case LoadType.BINARY: - cast(context.promise, Promise).complete(bytes); - - case LoadType.TEXT: - var text = bytes.getString(0, bytes.length, UTF8); - cast(context.promise, Promise).complete(text); - - case LoadType.IMAGE: - // For images, we need to decode the bytes - var img = new Image(); - img.__fromBytes(bytes, function(image) - { - cast(context.promise, Promise).complete(image); - }); - } - } - else - { - var errorResponse:_HTTPRequestErrorResponse; - if(context.loadType == LoadType.BINARY) { - errorResponse = new _HTTPRequestErrorResponse(fetch.status, bytes); - cast(context.promise, Promise).error(errorResponse); - }else { - errorResponse = new _HTTPRequestErrorResponse(fetch.status, bytes.getString(0, bytes.length, UTF8)); - cast(context.promise, Promise).error(errorResponse); - } - } - } - - @:keep - private static function onFetchProgress(fetchPtr:Star):Void - { - var fetch:EmscriptenFetchType = Pointer.fromStar(fetchPtr).value; - var idPointer:Star = cast fetch.userData; - var id:Int = untyped __cpp__('*(int*){0}', idPointer); - - if (activeFetches.exists(id)) - { - var context = activeFetches.get(id); - if (fetch.totalBytes > 0) - { - if(context.loadType == LoadType.BINARY) - cast(context.promise, Promise).progress(fetch.dataOffset + fetch.numBytes, fetch.totalBytes); - else if(context.loadType == LoadType.TEXT) - cast(context.promise, Promise).progress(fetch.dataOffset + fetch.numBytes, fetch.totalBytes); - } - } - } - - @:keep - private static function onFetchError(fetchPtr:Star):Void - { - var fetch:EmscriptenFetchType = Pointer.fromStar(fetchPtr).value; - var idPointer:Star = cast fetch.userData; - var id:Int = untyped __cpp__('*(int*){0}', idPointer); - - cpp.Native.free(idPointer); - - if (!activeFetches.exists(id)) - { - EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); - return; - } - - var context = activeFetches.get(id); - activeFetches.remove(id); - - context.parent.responseStatus = fetch.status; - - EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); - - var errorResponse = new _HTTPRequestErrorResponse(fetch.status, null); - if(context.loadType == LoadType.BINARY) - cast(context.promise, Promise).error(errorResponse); - else - cast(context.promise, Promise).error(errorResponse); - } + private static var fetchId:Int = 0; + private static var activeFetches = new Map(); + + private var binary:Bool; + private var parent:_IHTTPRequest; + private var currentFetchId:Int = -1; + + public function new() {} + + public function cancel():Void + { + if (currentFetchId >= 0 && activeFetches.exists(currentFetchId)) + { + var context = activeFetches.get(currentFetchId); + if (context != null && context.fetchPtr != null) + { + EmscriptenFetch.emscripten_fetch_close(context.fetchPtr); + } + activeFetches.remove(currentFetchId); + currentFetchId = -1; + } + } + + public function init(parent:_IHTTPRequest):Void + { + this.parent = parent; + } + + public function loadData(uri:String):Future + { + var promise = new Promise(); + binary = true; + __load(uri, promise, LoadType.BINARY); + return promise.future; + } + + public function loadText(uri:String):Future + { + var promise = new Promise(); + binary = false; + __load(uri, promise, LoadType.TEXT); + return promise.future; + } + + private function __load(uri:String, promise:Dynamic, loadType:LoadType):Void + { + var id = fetchId++; + currentFetchId = id; + + var context:FetchContext = + { + id: id, + promise: promise, + parent: parent, + loadType: loadType, + binary: binary, + fetchPtr: null + }; + + activeFetches.set(id, context); + + var attr:EmscriptenFetchAttrType = untyped __cpp__("{}"); + var attrPtr:Pointer = Pointer.addressOf(attr); + EmscriptenFetch.emscripten_fetch_attr_init(attrPtr); + + // Set request method + var method = parent.method != null ? Std.string(parent.method) : "GET"; + untyped __cpp__('strcpy({0}, {1})', attr.requestMethod, method); + + // Set callbacks + attr.onsuccess = untyped __cpp__("onFetchSuccess"); + attr.onprogress = untyped __cpp__("onFetchProgress"); + attr.onerror = untyped __cpp__("onFetchError"); + + // Store fetch ID in userData + var idPointer:Star = untyped __cpp__('(int*)malloc(sizeof(int))'); + untyped __cpp__('*{0} = {1}', idPointer, id); + attr.userData = cast idPointer; + + // Set EMSCRIPTEN_FETCH_LOAD_TO_MEMORY + attr.attributes = 1; + + // Start fetch + var fetchPtr = EmscriptenFetch.emscripten_fetch(attrPtr, uri); + context.fetchPtr = fetchPtr; + } + + @:keep + private static function onFetchSuccess(fetchPtr:Star):Void + { + var fetch:EmscriptenFetchType = Pointer.fromStar(fetchPtr).value; + var idPointer:Star = cast fetch.userData; + var id:Int = untyped __cpp__('*(int*){0}', idPointer); + + cpp.Native.free(idPointer); + fetch.userData = null; + + if (!activeFetches.exists(id)) + { + EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); + return; + } + + var context = activeFetches.get(id); + activeFetches.remove(id); + if (context == null) trace("EmscriptenHTTPRequest.onFetchSuccess: context is null"); + + // Process response + if (context.parent.enableResponseHeaders) + { + context.parent.responseHeaders = []; + // Note: Emscripten Fetch API has limited header access + // You may need to parse headers from fetch.statusText if available + } + + context.parent.responseStatus = fetch.status; + + // Create bytes from fetch data + var bytes:Bytes = null; + if (fetch.numBytes > 0 && fetch.data != null) + { + bytes = Bytes.ofData(cast fetch.data.toUnmanagedArray(fetch.numBytes).copy()); + } + else + { + bytes = Bytes.alloc(0); + } + + EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); + + // Complete promise based on load type + if (fetch.status >= 200 && fetch.status < 400) + { + switch (context.loadType) + { + case LoadType.BINARY: + cast(context.promise, Promise).complete(bytes); + + case LoadType.TEXT: + var text = bytes.getString(0, bytes.length, UTF8); + cast(context.promise, Promise).complete(text); + + case LoadType.IMAGE: + // For images, we need to decode the bytes + var img = new Image(); + img.__fromBytes(bytes, function(image) + { + cast(context.promise, Promise).complete(image); + }); + } + } + else + { + var errorResponse:_HTTPRequestErrorResponse; + if (context.loadType == LoadType.BINARY) + { + errorResponse = new _HTTPRequestErrorResponse(fetch.status, bytes); + cast(context.promise, Promise).error(errorResponse); + } + else + { + errorResponse = new _HTTPRequestErrorResponse(fetch.status, bytes.getString(0, bytes.length, UTF8)); + cast(context.promise, Promise).error(errorResponse); + } + } + } + + @:keep + private static function onFetchProgress(fetchPtr:Star):Void + { + var fetch:EmscriptenFetchType = Pointer.fromStar(fetchPtr).value; + var idPointer:Star = cast fetch.userData; + var id:Int = untyped __cpp__('*(int*){0}', idPointer); + + if (activeFetches.exists(id)) + { + var context = activeFetches.get(id); + if (fetch.totalBytes > 0) + { + if (context.loadType == LoadType.BINARY) cast(context.promise, Promise).progress(fetch.dataOffset + fetch.numBytes, fetch.totalBytes); + else if (context.loadType == LoadType.TEXT) cast(context.promise, Promise).progress(fetch.dataOffset + fetch.numBytes, + fetch.totalBytes); + } + } + } + + @:keep + private static function onFetchError(fetchPtr:Star):Void + { + var fetch:EmscriptenFetchType = Pointer.fromStar(fetchPtr).value; + var idPointer:Star = cast fetch.userData; + var id:Int = untyped __cpp__('*(int*){0}', idPointer); + + cpp.Native.free(idPointer); + + if (!activeFetches.exists(id)) + { + EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); + return; + } + + var context = activeFetches.get(id); + activeFetches.remove(id); + + context.parent.responseStatus = fetch.status; + + EmscriptenFetch.emscripten_fetch_close(Pointer.fromStar(fetchPtr)); + + var errorResponse = new _HTTPRequestErrorResponse(fetch.status, null); + if (context.loadType == LoadType.BINARY) cast(context.promise, Promise).error(errorResponse); + else + cast(context.promise, Promise).error(errorResponse); + } } @:dox(hide) enum LoadType { - BINARY; - TEXT; - IMAGE; + BINARY; + TEXT; + IMAGE; } @:dox(hide) typedef FetchContext = { - var id:Int; - var promise:Dynamic; - var parent:_IHTTPRequest; - var loadType:LoadType; - var binary:Bool; - var fetchPtr:Pointer; + var id:Int; + var promise:Dynamic; + var parent:_IHTTPRequest; + var loadType:LoadType; + var binary:Bool; + var fetchPtr:Pointer; } -#end \ No newline at end of file +#end diff --git a/src/lime/_internal/backend/flash/FlashAudioInput.hx b/src/lime/_internal/backend/flash/FlashAudioInput.hx new file mode 100644 index 0000000000..59f0012252 --- /dev/null +++ b/src/lime/_internal/backend/flash/FlashAudioInput.hx @@ -0,0 +1,288 @@ +package lime._internal.backend.flash; + +import flash.events.SampleDataEvent; +import flash.media.Microphone; +import haxe.io.Bytes; +import lime.media.AudioInput; +import lime.media.AudioInputDevice; + +private typedef AudioInputData = +{ + var bytes:Bytes; + var offset:Int; +} + +@:access(lime.media.AudioInput) +class FlashAudioInput +{ + private static inline var MAX_QUEUED_MS = 10000; + + private var buffers:Array; + private var frameSize:Int; + private var microphone:Microphone; + private var parent:AudioInput; + private var queuedBytes:Int; + + public static function getDefaultDevice():AudioInputDevice + { + if (!isSupported()) + { + return null; + } + + var microphone = Microphone.getMicrophone(); + + if (microphone != null) + { + return new AudioInputDevice(microphone.name, Std.string(microphone.index), true); + } + + var devices = getDevices(); + return devices.length > 0 ? devices[0] : null; + } + + public static function getDevices():Array + { + var devices:Array = []; + + if (!isSupported() || Microphone.names == null) + { + return devices; + } + + for (i in 0...Microphone.names.length) + { + var name = Std.string(Microphone.names[i]); + devices.push(new AudioInputDevice(name, Std.string(i), i == 0)); + } + + return devices; + } + + public static function isSupported():Bool + { + return Microphone.isSupported; + } + + public function new(parent:AudioInput) + { + this.parent = parent; + + buffers = []; + frameSize = getFrameSize(); + queuedBytes = 0; + } + + public function dispose():Void + { + stop(); + buffers.resize(0); + queuedBytes = 0; + } + + public function getSamplesAvailable():Int + { + if (frameSize <= 0) + { + return 0; + } + + return Std.int(queuedBytes / frameSize); + } + + public function read(buffer:Bytes, samples:Int):Int + { + if (buffer == null || samples <= 0 || frameSize <= 0) + { + return 0; + } + + var samplesToRead = samples; + var available = getSamplesAvailable(); + var maxSamples = Std.int(buffer.length / frameSize); + + if (samplesToRead > available) + { + samplesToRead = available; + } + + if (samplesToRead > maxSamples) + { + samplesToRead = maxSamples; + } + + if (samplesToRead <= 0) + { + return 0; + } + + var bytesToRead = samplesToRead * frameSize; + var remaining = bytesToRead; + var writePosition = 0; + + while (remaining > 0 && buffers.length > 0) + { + var data = buffers[0]; + var availableBytes = data.bytes.length - data.offset; + var copyBytes = availableBytes < remaining ? availableBytes : remaining; + + buffer.blit(writePosition, data.bytes, data.offset, copyBytes); + + data.offset += copyBytes; + writePosition += copyBytes; + remaining -= copyBytes; + queuedBytes -= copyBytes; + + if (data.offset >= data.bytes.length) + { + buffers.shift(); + } + } + + return Std.int((bytesToRead - remaining) / frameSize); + } + + public function start():Bool + { + if (parent.running || !isSupported() || !isFormatSupported()) + { + return parent.running; + } + + var index = -1; + + if (parent.device != null && !parent.device.isDefault && parent.device.id != null) + { + var parsedIndex = Std.parseInt(parent.device.id); + + if (parsedIndex != null) + { + index = parsedIndex; + } + } + + microphone = Microphone.getMicrophone(index); + + if (microphone == null) + { + return false; + } + + microphone.rate = getMicrophoneRate(parent.sampleRate); + parent.sampleRate = microphone.rate * 1000; + + microphone.setLoopBack(false); + microphone.setSilenceLevel(0, -1); + microphone.setUseEchoSuppression(false); + microphone.addEventListener(SampleDataEvent.SAMPLE_DATA, microphone_onSampleData); + + return true; + } + + public function stop():Void + { + parent.running = false; + + if (microphone != null) + { + microphone.removeEventListener(SampleDataEvent.SAMPLE_DATA, microphone_onSampleData); + microphone = null; + } + } + + private function appendSample(bytes:Bytes, position:Int, sample:Float):Int + { + if (sample > 1) + { + sample = 1; + } + else if (sample < -1) + { + sample = -1; + } + + if (parent.bitsPerSample == 8) + { + bytes.set(position++, Std.int((sample * 0.5 + 0.5) * 255) & 0xFF); + } + else + { + var value = sample < 0 ? Std.int(sample * 32768) : Std.int(sample * 32767); + bytes.set(position++, value & 0xFF); + bytes.set(position++, (value >> 8) & 0xFF); + } + + return position; + } + + private function getFrameSize():Int + { + return Std.int((parent.channels * parent.bitsPerSample) / 8); + } + + private function getMicrophoneRate(sampleRate:Int):Int + { + if (sampleRate >= 44100) + { + return 44; + } + else if (sampleRate >= 22050) + { + return 22; + } + else if (sampleRate >= 11025) + { + return 11; + } + else if (sampleRate >= 8000) + { + return 8; + } + + return 5; + } + + private function isFormatSupported():Bool + { + return (parent.channels == 1 || parent.channels == 2) && (parent.bitsPerSample == 8 || parent.bitsPerSample == 16); + } + + private function microphone_onSampleData(event:SampleDataEvent):Void + { + if (!parent.running || frameSize <= 0) + { + return; + } + + event.data.position = 0; + + var samples = Std.int(event.data.bytesAvailable / 4); + var bytes = Bytes.alloc(samples * frameSize); + var position = 0; + + for (i in 0...samples) + { + var sample = event.data.readFloat(); + + for (channel in 0...parent.channels) + { + position = appendSample(bytes, position, sample); + } + } + + buffers.push({bytes: bytes, offset: 0}); + queuedBytes += bytes.length; + trimQueue(); + } + + private function trimQueue():Void + { + var maxQueuedBytes = Std.int((parent.sampleRate * MAX_QUEUED_MS / 1000) * frameSize); + + while (queuedBytes > maxQueuedBytes && buffers.length > 0) + { + var data = buffers.shift(); + queuedBytes -= data.bytes.length - data.offset; + } + } +} diff --git a/src/lime/_internal/backend/flash/FlashHTTPRequest.hx b/src/lime/_internal/backend/flash/FlashHTTPRequest.hx index 67861d810a..e44164755f 100644 --- a/src/lime/_internal/backend/flash/FlashHTTPRequest.hx +++ b/src/lime/_internal/backend/flash/FlashHTTPRequest.hx @@ -174,4 +174,4 @@ class FlashHTTPRequest urlLoader.load(urlRequest); return promise.future; } -} \ No newline at end of file +} diff --git a/src/lime/_internal/backend/flash/FlashWindow.hx b/src/lime/_internal/backend/flash/FlashWindow.hx index 1935a11208..ad9df272bd 100644 --- a/src/lime/_internal/backend/flash/FlashWindow.hx +++ b/src/lime/_internal/backend/flash/FlashWindow.hx @@ -225,8 +225,7 @@ class FlashWindow "middleMouseMove", "middleMouseUp" #if ((!openfl && !disable_flash_right_click) - || enable_flash_right_click), "rightMouseDown", "rightMouseMove", "rightMouseUp" - #end + || enable_flash_right_click), "rightMouseDown", "rightMouseMove", "rightMouseUp" #end ]; for (event in events) diff --git a/src/lime/_internal/backend/html5/HTML5Application.hx b/src/lime/_internal/backend/html5/HTML5Application.hx index e451eb3545..99279c350c 100644 --- a/src/lime/_internal/backend/html5/HTML5Application.hx +++ b/src/lime/_internal/backend/html5/HTML5Application.hx @@ -11,6 +11,7 @@ import lime.media.AudioManager; import lime.system.Orientation; import lime.system.Sensor; import lime.system.SensorType; +import lime.system.System; import lime.ui.GamepadAxis; import lime.ui.KeyCode; import lime.ui.KeyModifier; @@ -275,7 +276,18 @@ class HTML5Application public function configureFrameTiming(profile:FrameProfile, frameRate:Float, options:FrameOptions):Void { - framePeriod = frameRate > 0 ? (1000.0 / frameRate) : -1; + if (frameRate >= 60) + { + framePeriod = -1; + } + else if (frameRate > 0) + { + framePeriod = 1000.0 / frameRate; + } + else + { + framePeriod = 1000; + } } public function exec():Int @@ -444,10 +456,11 @@ class HTML5Application var keyCode = cast convertKeyCode(event.keyCode != null ? event.keyCode : event.which); var modifier = (event.shiftKey ? (KeyModifier.SHIFT) : 0) | (event.ctrlKey ? (KeyModifier.CTRL) : 0) | (event.altKey ? (KeyModifier.ALT) : 0) | (event.metaKey ? (KeyModifier.META) : 0); + var timestamp = Std.int(event.timeStamp); if (event.type == "keydown") { - parent.window.onKeyDown.dispatch(keyCode, modifier); + @:privateAccess parent.window.onKeyDown.__dispatchWithTimestamp(timestamp, keyCode, modifier); if (parent.window.onKeyDown.canceled && event.cancelable) { @@ -456,7 +469,7 @@ class HTML5Application } else { - parent.window.onKeyUp.dispatch(keyCode, modifier); + @:privateAccess parent.window.onKeyUp.__dispatchWithTimestamp(timestamp, keyCode, modifier); if (parent.window.onKeyUp.canceled && event.cancelable) { @@ -601,18 +614,19 @@ class HTML5Application for (i in 0...data.buttons.length) { value = data.buttons[i].value; + var timestamp = System.getTimer(); if (value != cache.buttons[i]) { if (i == 6) { joystick.onAxisMove.dispatch(data.axes.length, value); - if (gamepad != null) gamepad.onAxisMove.dispatch(GamepadAxis.TRIGGER_LEFT, value); + if (gamepad != null) @:privateAccess gamepad.onAxisMove.__dispatchWithTimestamp(timestamp, GamepadAxis.TRIGGER_LEFT, value); } else if (i == 7) { joystick.onAxisMove.dispatch(data.axes.length + 1, value); - if (gamepad != null) gamepad.onAxisMove.dispatch(GamepadAxis.TRIGGER_RIGHT, value); + if (gamepad != null) @:privateAccess gamepad.onAxisMove.__dispatchWithTimestamp(timestamp, GamepadAxis.TRIGGER_RIGHT, value); } else { @@ -649,11 +663,11 @@ class HTML5Application if (value > 0) { - gamepad.onButtonDown.dispatch(button); + @:privateAccess gamepad.onButtonDown.__dispatchWithTimestamp(timestamp, button); } else { - gamepad.onButtonUp.dispatch(button); + @:privateAccess gamepad.onButtonUp.__dispatchWithTimestamp(timestamp, button); } } } @@ -667,7 +681,7 @@ class HTML5Application if (data.axes[i] != cache.axes[i]) { joystick.onAxisMove.dispatch(i, data.axes[i]); - if (gamepad != null) gamepad.onAxisMove.dispatch(i, data.axes[i]); + if (gamepad != null) @:privateAccess gamepad.onAxisMove.__dispatchWithTimestamp(System.getTimer(), i, data.axes[i]); cache.axes[i] = data.axes[i]; } } diff --git a/src/lime/_internal/backend/html5/HTML5AudioInput.hx b/src/lime/_internal/backend/html5/HTML5AudioInput.hx new file mode 100644 index 0000000000..856ddd8aad --- /dev/null +++ b/src/lime/_internal/backend/html5/HTML5AudioInput.hx @@ -0,0 +1,444 @@ +package lime._internal.backend.html5; + +import haxe.io.Bytes; +import js.Browser; +import lime.media.AudioInput; +import lime.media.AudioInputDevice; + +private typedef AudioInputData = +{ + var bytes:Bytes; + var offset:Int; +} + +@:access(lime.media.AudioInput) +class HTML5AudioInput +{ + private static inline var MAX_QUEUED_MS = 10000; + + private static var cachedDevices:Array; + private static var enumeratingDevices:Bool; + + private var audioContext:Dynamic; + private var buffers:Array; + private var disposed:Bool; + private var frameSize:Int; + private var mediaStream:Dynamic; + private var parent:AudioInput; + private var processorNode:Dynamic; + private var queuedBytes:Int; + private var sourceNode:Dynamic; + private var starting:Bool; + + public static function getDefaultDevice():AudioInputDevice + { + if (!isSupported()) + { + return null; + } + + return new AudioInputDevice("Default Audio Input", null, true); + } + + public static function getDevices():Array + { + refreshDevices(); + + if (cachedDevices != null) + { + return cachedDevices.copy(); + } + + var defaultDevice = getDefaultDevice(); + return defaultDevice != null ? [defaultDevice] : []; + } + + public static function isSupported():Bool + { + var navigator:Dynamic = Browser.navigator; + return navigator != null && navigator.mediaDevices != null && navigator.mediaDevices.getUserMedia != null; + } + + public function new(parent:AudioInput) + { + this.parent = parent; + + buffers = []; + frameSize = getFrameSize(); + queuedBytes = 0; + } + + public function dispose():Void + { + disposed = true; + stop(); + buffers.resize(0); + queuedBytes = 0; + } + + public function getSamplesAvailable():Int + { + if (frameSize <= 0) + { + return 0; + } + + return Std.int(queuedBytes / frameSize); + } + + public function read(buffer:Bytes, samples:Int):Int + { + if (buffer == null || samples <= 0 || frameSize <= 0) + { + return 0; + } + + var samplesToRead = samples; + var available = getSamplesAvailable(); + var maxSamples = Std.int(buffer.length / frameSize); + + if (samplesToRead > available) + { + samplesToRead = available; + } + + if (samplesToRead > maxSamples) + { + samplesToRead = maxSamples; + } + + if (samplesToRead <= 0) + { + return 0; + } + + var bytesToRead = samplesToRead * frameSize; + var remaining = bytesToRead; + var writePosition = 0; + + while (remaining > 0 && buffers.length > 0) + { + var data = buffers[0]; + var availableBytes = data.bytes.length - data.offset; + var copyBytes = availableBytes < remaining ? availableBytes : remaining; + + buffer.blit(writePosition, data.bytes, data.offset, copyBytes); + + data.offset += copyBytes; + writePosition += copyBytes; + remaining -= copyBytes; + queuedBytes -= copyBytes; + + if (data.offset >= data.bytes.length) + { + buffers.shift(); + } + } + + return Std.int((bytesToRead - remaining) / frameSize); + } + + public function start():Bool + { + if (disposed || starting || parent.running || !isSupported() || !isFormatSupported()) + { + return parent.running; + } + + starting = true; + audioContext = createAudioContext(); + + if (audioContext == null) + { + starting = false; + return false; + } + + if (audioContext.resume != null) + { + audioContext.resume(); + } + + var constraints:Dynamic = + { + audio: + { + channelCount: parent.channels, + echoCancellation: false, + noiseSuppression: false, + autoGainControl: false + } + }; + + if (parent.sampleRate > 0) + { + constraints.audio.sampleRate = parent.sampleRate; + } + + if (parent.device != null && !parent.device.isDefault && parent.device.id != null && parent.device.id != "") + { + constraints.audio.deviceId = {exact: parent.device.id}; + } + + var navigator:Dynamic = Browser.navigator; + var promise:Dynamic = navigator.mediaDevices.getUserMedia(constraints); + + promise.then(function(stream) + { + if (disposed || !starting) + { + stopMediaStream(stream); + return; + } + + open(stream); + }, function(error) + { + starting = false; + parent.running = false; + }); + + return false; + } + + public function stop():Void + { + starting = false; + parent.running = false; + + if (sourceNode != null) + { + sourceNode.disconnect(); + sourceNode = null; + } + + if (processorNode != null) + { + processorNode.disconnect(); + processorNode.onaudioprocess = null; + processorNode = null; + } + + if (audioContext != null && audioContext.close != null) + { + audioContext.close(); + audioContext = null; + } + + if (mediaStream != null) + { + stopMediaStream(mediaStream); + mediaStream = null; + } + } + + private function appendSamples(event:Dynamic):Void + { + var outputBuffer:Dynamic = event.outputBuffer; + + if (outputBuffer != null) + { + for (channel in 0...outputBuffer.numberOfChannels) + { + var output = outputBuffer.getChannelData(channel); + + for (frame in 0...outputBuffer.length) + { + output[frame] = 0; + } + } + } + + if (!parent.running || disposed || frameSize <= 0) + { + return; + } + + var inputBuffer:Dynamic = event.inputBuffer; + var frames:Int = inputBuffer.length; + var inputChannels:Int = inputBuffer.numberOfChannels; + var channelData:Array = []; + + for (channel in 0...parent.channels) + { + var sourceChannel = channel < inputChannels ? channel : 0; + channelData.push(inputBuffer.getChannelData(sourceChannel)); + } + + var bytes = Bytes.alloc(frames * frameSize); + var position = 0; + + for (frame in 0...frames) + { + for (channel in 0...parent.channels) + { + var sample:Float = channelData[channel][frame]; + + if (sample > 1) + { + sample = 1; + } + else if (sample < -1) + { + sample = -1; + } + + if (parent.bitsPerSample == 8) + { + bytes.set(position++, Std.int((sample * 0.5 + 0.5) * 255) & 0xFF); + } + else + { + var value = sample < 0 ? Std.int(sample * 32768) : Std.int(sample * 32767); + bytes.set(position++, value & 0xFF); + bytes.set(position++, (value >> 8) & 0xFF); + } + } + } + + buffers.push({bytes: bytes, offset: 0}); + queuedBytes += bytes.length; + trimQueue(); + } + + private function createAudioContext():Dynamic + { + var window:Dynamic = Browser.window; + var audioContextClass:Dynamic = window.AudioContext != null ? window.AudioContext : window.webkitAudioContext; + + if (audioContextClass == null) + { + return null; + } + + try + { + return untyped #if haxe4 js.Syntax.code #else __js__ #end ("new audioContextClass({ sampleRate: {0} })", parent.sampleRate); + } + catch (e:Dynamic) + { + return untyped #if haxe4 js.Syntax.code #else __js__ #end ("new audioContextClass()"); + } + } + + private function getFrameSize():Int + { + return Std.int((parent.channels * parent.bitsPerSample) / 8); + } + + private function getProcessorBufferSize():Int + { + var size = 256; + + while (size < parent.bufferSize && size < 16384) + { + size *= 2; + } + + return size; + } + + private function isFormatSupported():Bool + { + return (parent.channels == 1 || parent.channels == 2) && (parent.bitsPerSample == 8 || parent.bitsPerSample == 16); + } + + private function open(stream:Dynamic):Void + { + if (audioContext == null) + { + starting = false; + stopMediaStream(stream); + return; + } + + if (audioContext.sampleRate != null) + { + parent.sampleRate = Std.int(audioContext.sampleRate); + } + + mediaStream = stream; + sourceNode = audioContext.createMediaStreamSource(stream); + processorNode = audioContext.createScriptProcessor(getProcessorBufferSize(), parent.channels, parent.channels); + + processorNode.onaudioprocess = appendSamples; + sourceNode.connect(processorNode); + processorNode.connect(audioContext.destination); + + if (audioContext.resume != null) + { + audioContext.resume(); + } + + starting = false; + parent.running = true; + refreshDevices(); + } + + private static function refreshDevices():Void + { + if (enumeratingDevices || !isSupported()) + { + return; + } + + enumeratingDevices = true; + + var navigator:Dynamic = Browser.navigator; + var promise:Dynamic = navigator.mediaDevices.enumerateDevices(); + + promise.then(function(devices) + { + var result:Array = []; + var length:Int = devices.length; + + for (i in 0...length) + { + var device:Dynamic = devices[i]; + + if (device.kind == "audioinput") + { + var label:String = device.label != null && device.label != "" ? device.label : "Audio Input"; + result.push(new AudioInputDevice(label, device.deviceId, result.length == 0)); + } + } + + if (result.length > 0) + { + cachedDevices = result; + } + + enumeratingDevices = false; + }, function(error) + { + enumeratingDevices = false; + }); + } + + private function stopMediaStream(stream:Dynamic):Void + { + if (stream == null || stream.getTracks == null) + { + return; + } + + var tracks:Dynamic = stream.getTracks(); + var length:Int = tracks.length; + + for (i in 0...length) + { + tracks[i].stop(); + } + } + + private function trimQueue():Void + { + var maxQueuedBytes = Std.int((parent.sampleRate * MAX_QUEUED_MS / 1000) * frameSize); + + while (queuedBytes > maxQueuedBytes && buffers.length > 0) + { + var data = buffers.shift(); + queuedBytes -= data.bytes.length - data.offset; + } + } +} diff --git a/src/lime/_internal/backend/html5/HTML5AudioSource.hx b/src/lime/_internal/backend/html5/HTML5AudioSource.hx index f2b9fe80b2..a898c7ad16 100644 --- a/src/lime/_internal/backend/html5/HTML5AudioSource.hx +++ b/src/lime/_internal/backend/html5/HTML5AudioSource.hx @@ -261,7 +261,8 @@ class HTML5AudioSource position.w = value.w; #if lime_howlerjs - if (parent.buffer != null && parent.buffer.__srcHowl != null && parent.buffer.__srcHowl.pos != null) parent.buffer.__srcHowl.pos(position.x, position.y, position.z, id); + if (parent.buffer != null && parent.buffer.__srcHowl != null && parent.buffer.__srcHowl.pos != null) parent.buffer.__srcHowl.pos(position.x, + position.y, position.z, id); // There are more settings to the position of the sound on the "pannerAttr()" function of howler. Maybe somebody who understands sound should look into it? #end diff --git a/src/lime/_internal/backend/html5/HTML5HTTPRequest.hx b/src/lime/_internal/backend/html5/HTML5HTTPRequest.hx index 4b94560e66..547d2f348e 100644 --- a/src/lime/_internal/backend/html5/HTML5HTTPRequest.hx +++ b/src/lime/_internal/backend/html5/HTML5HTTPRequest.hx @@ -64,8 +64,7 @@ class HTML5HTTPRequest if (parent.method == POST) { - if(request.upload != null) - request.upload.addEventListener("progress", progress, false); + if (request.upload != null) request.upload.addEventListener("progress", progress, false); } else { diff --git a/src/lime/_internal/backend/html5/HTML5Thread.hx b/src/lime/_internal/backend/html5/HTML5Thread.hx index 9f744e59e1..02caf2ca0c 100644 --- a/src/lime/_internal/backend/html5/HTML5Thread.hx +++ b/src/lime/_internal/backend/html5/HTML5Thread.hx @@ -1,7 +1,6 @@ package lime._internal.backend.html5; import lime.app.Event; - #if macro import haxe.macro.Context; import haxe.macro.Expr; @@ -30,7 +29,8 @@ import lime.app.Application; /** Emulates much of the `sys.thread.Thread` API using web workers. **/ -class HTML5Thread { +class HTML5Thread +{ private static var __current:HTML5Thread = new HTML5Thread(Lib.global.location.href); private static var __isWorker:Bool #if !macro = #if !haxe4 untyped __js__ #else Syntax.code #end ('typeof window == "undefined"') #end; private static var __messages:List = new List(); @@ -80,8 +80,7 @@ class HTML5Thread { #if !macro // Find the URL of the primary JS file. var url:URL = new URL(__current.__href); - url.pathname = url.pathname.substr(0, url.pathname.lastIndexOf("/") + 1) - + Application.current.meta["file"] + ".js"; + url.pathname = url.pathname.substr(0, url.pathname.lastIndexOf("/") + 1) + Application.current.meta["file"] + ".js"; // Use the hash to distinguish workers. if (url.hash.length > 0) url.hash += "_"; @@ -108,9 +107,9 @@ class HTML5Thread { private static inline function zeroDelay():Promise { return new Promise(function(resolve, _):Void - { - js.Lib.global.setTimeout(resolve); - }); + { + js.Lib.global.setTimeout(resolve); + }); } #end @@ -128,8 +127,8 @@ class HTML5Thread { // suspended, so we must insert `await` even if `block` is false. // TODO: find a more efficient way to read messages. var zeroDelayExpr:Expr = macro @:privateAccess - $jsCode("await {0}", lime._internal.backend.html5.HTML5Thread.zeroDelay()) - .then(function(_) return lime._internal.backend.html5.HTML5Thread.__messages.pop()); + $jsCode("await {0}", lime._internal.backend.html5.HTML5Thread.zeroDelay()).then(function(_) return + lime._internal.backend.html5.HTML5Thread.__messages.pop()); switch (block.expr) { @@ -138,15 +137,18 @@ class HTML5Thread { default: return macro if ($block && @:privateAccess lime._internal.backend.html5.HTML5Thread.__messages.isEmpty()) { - $jsCode("await {0}", new #if haxe4 js.lib.Promise #else js.Promise #end + $jsCode("await {0}", new + #if haxe4 + js.lib.Promise + #else + js.Promise + #end (function(resolve, _):Void { @:privateAccess lime._internal.backend.html5.HTML5Thread.__resolveMethods.add(resolve); - } - )); + })); } - else - $zeroDelayExpr; + else $zeroDelayExpr; } } @@ -294,18 +296,18 @@ abstract WorkFunction(WorkFunctionData) from Wor as the `initialExpr`. For instance, `array[i].foo.bar` will result in `chain == ["foo", "bar"]` and `initialExpr == array[i]`. **/ - private static function parseFieldChain(chain:Expr):{ chain:Array, ?initialExpr:Expr } + private static function parseFieldChain(chain:Expr):{chain:Array, ?initialExpr:Expr} { - switch(chain.expr) + switch (chain.expr) { case EConst(CIdent(ident)): - return { chain: [ident] }; + return {chain: [ident]}; case EField(e, field): var out = parseFieldChain(e); out.chain.push(field); return out; default: - return { chain: [], initialExpr: chain }; + return {chain: [], initialExpr: chain}; } } #end @@ -314,9 +316,10 @@ abstract WorkFunction(WorkFunctionData) from Wor @:noCompletion @:dox(hide) #if !macro @:from #end public static #if !macro macro #end function fromFunction(func:ExprOf) { - var defaultOutput:Expr = macro { - func: $func - }; + var defaultOutput:Expr = macro + { + func: $func + }; if (!Context.defined("lime-threads")) { @@ -343,11 +346,12 @@ abstract WorkFunction(WorkFunctionData) from Wor var classPath:String = matcher.matched(1); var functionName:String = matcher.matched(2); - return macro { - func: $func, - classPath: $v{classPath}, - functionName: $v{functionName} - }; + return macro + { + func: $func, + classPath: $v{classPath}, + functionName: $v{functionName} + }; } } @@ -416,7 +420,7 @@ abstract WorkFunction(WorkFunctionData) from Wor else { #if !macro - this.sourceCode = (cast this.func #if haxe4 :Function #end).toString(); + this.sourceCode = (cast this.func #if haxe4 : Function #end).toString(); if (this.sourceCode.indexOf("[native code]") < 0) { // All set. @@ -456,7 +460,8 @@ abstract WorkFunction(WorkFunctionData) from Wor Stores the class path and function name of a function, so that it can be found again in the background thread. **/ -typedef WorkFunctionData = { +typedef WorkFunctionData = +{ @:optional var classPath:String; @:optional var functionName:String; @:optional var sourceCode:String; @@ -475,17 +480,15 @@ abstract Message(Dynamic) from Dynamic to Dynamic private static inline function skip(object:Dynamic):Bool { // Skip `null` for obvious reasons. - return object == null - // No need to preserve a primitive type. - || !#if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (object, Object) - // Objects with this field have been deliberately excluded. - || Reflect.field(object, SKIP_FIELD) == true - // A `Uint8Array` (the type used by `haxe.io.Bytes`) can have - // thousands or millions of fields, which can take entire seconds to - // enumerate. This also applies to `Int8Array`, `Float64Array`, etc. - || object.byteLength != null && object.byteOffset != null - && object.buffer != null - && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (object.buffer, #if haxe4 js.lib.ArrayBuffer #else js.html.ArrayBuffer #end); + return object == null // No need to preserve a primitive type. + || !#if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (object, Object) // Objects with this field have been deliberately excluded. + || Reflect.field(object, SKIP_FIELD) == true // A `Uint8Array` (the type used by `haxe.io.Bytes`) can have + // thousands or millions of fields, which can take entire seconds to + // enumerate. This also applies to `Int8Array`, `Float64Array`, etc. + || object.byteLength != null + && object.byteOffset != null + && object.buffer != null + && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (object.buffer, #if haxe4 js.lib.ArrayBuffer #else js.html.ArrayBuffer #end); } #end @@ -556,7 +559,7 @@ abstract Message(Dynamic) from Dynamic to Dynamic // Recurse. for (child in Object.values(this)) { - (child:Message).preserveClasses(); + (child : Message).preserveClasses(); } #end } @@ -600,9 +603,8 @@ abstract Message(Dynamic) from Dynamic to Dynamic { try { - Object.setPrototypeOf(this, - #if haxe4 Syntax.code #else untyped __js__ #end - ("$hxClasses[{0}].prototype", Reflect.field(this, PROTOTYPE_FIELD))); + Object.setPrototypeOf(this, #if haxe4 Syntax.code #else untyped __js__ #end ("$hxClasses[{0}].prototype", Reflect.field(this, + PROTOTYPE_FIELD))); } catch (e:Dynamic) {} } @@ -610,7 +612,7 @@ abstract Message(Dynamic) from Dynamic to Dynamic // Recurse. for (child in Object.values(this)) { - (child:Message).restoreClasses(flag); + (child : Message).restoreClasses(flag); } #end } @@ -620,13 +622,15 @@ abstract Message(Dynamic) from Dynamic to Dynamic typedef Worker = Dynamic; typedef URL = Dynamic; class Object {} + class Browser { public static var window:Dynamic; } + class Lib { - public static var global:Dynamic = { location: {} }; + public static var global:Dynamic = {location: {}}; } #end @@ -641,15 +645,15 @@ class Lib **/ // Mozilla uses "transferable" and "transferrable" interchangeably, but the HTML // specification only uses the former. + @:forward -abstract Transferable(Dynamic) #if macro from Dynamic - #else from lime.utils.ArrayBuffer from js.html.MessagePort from js.html.ImageBitmap #end -{ -} +abstract Transferable(Dynamic) #if macro from Dynamic #else from lime.utils.ArrayBuffer from js.html.MessagePort from js.html.ImageBitmap #end +{} #if (!haxe4 && !macro) @:native("Object") -extern class Object { +extern class Object +{ static function setPrototypeOf(obj:T, prototype:Null<{}>):T; @:pure static function values(obj:{}):Array; static var prototype(default, never):Dynamic; diff --git a/src/lime/_internal/backend/html5/HTML5Window.hx b/src/lime/_internal/backend/html5/HTML5Window.hx index 8e7b662b08..e36aa53e34 100644 --- a/src/lime/_internal/backend/html5/HTML5Window.hx +++ b/src/lime/_internal/backend/html5/HTML5Window.hx @@ -320,7 +320,8 @@ class HTML5Window if (forceWebGL || (!forceCanvas && (!Reflect.hasField(contextAttributes, "hardware") || contextAttributes.hardware))) { - var transparentBackground = Reflect.hasField(contextAttributes, "background") && contextAttributes.background == null; + var transparentBackground = (Reflect.hasField(contextAttributes, "background") && contextAttributes.background == null) + || parent.transparent; var colorDepth = Reflect.hasField(contextAttributes, "colorDepth") ? contextAttributes.colorDepth : 16; var options = diff --git a/src/lime/_internal/backend/native/NativeApplication.hx b/src/lime/_internal/backend/native/NativeApplication.hx index 1be8e8df77..ad45bbaba0 100644 --- a/src/lime/_internal/backend/native/NativeApplication.hx +++ b/src/lime/_internal/backend/native/NativeApplication.hx @@ -292,13 +292,14 @@ class NativeApplication { case AXIS_MOVE: var gamepad = Gamepad.devices.get(gamepadEventInfo.id); - if (gamepad != null) gamepad.onAxisMove.dispatch(gamepadEventInfo.axis, gamepadEventInfo.axisValue); + if (gamepad != null) @:privateAccess gamepad.onAxisMove.__dispatchWithTimestamp(gamepadEventInfo.timestamp, gamepadEventInfo.axis, + gamepadEventInfo.axisValue); case BUTTON_DOWN: var gamepad = Gamepad.devices.get(gamepadEventInfo.id); - if (gamepad != null) gamepad.onButtonDown.dispatch(gamepadEventInfo.button); + if (gamepad != null) @:privateAccess gamepad.onButtonDown.__dispatchWithTimestamp(gamepadEventInfo.timestamp, gamepadEventInfo.button); case BUTTON_UP: var gamepad = Gamepad.devices.get(gamepadEventInfo.id); - if (gamepad != null) gamepad.onButtonUp.dispatch(gamepadEventInfo.button); + if (gamepad != null) @:privateAccess gamepad.onButtonUp.__dispatchWithTimestamp(gamepadEventInfo.timestamp, gamepadEventInfo.button); case CONNECT: Gamepad.__connect(gamepadEventInfo.id); @@ -345,9 +346,9 @@ class NativeApplication switch (type) { case KEY_DOWN: - window.onKeyDown.dispatch(keyCode, modifier); + @:privateAccess window.onKeyDown.__dispatchWithTimestamp(keyEventInfo.timestamp, keyCode, modifier); case KEY_UP: - window.onKeyUp.dispatch(keyCode, modifier); + @:privateAccess window.onKeyUp.__dispatchWithTimestamp(keyEventInfo.timestamp, keyCode, modifier); } #if (windows || linux) @@ -466,6 +467,9 @@ class NativeApplication switch (renderEventInfo.type) { case RENDER: + #if lime_skip_invisible_windows + if (!window.visible) continue; + #end if (window.context != null) { window.__backend.render(); @@ -776,19 +780,21 @@ class NativeApplication public var id:Int; public var type:GamepadEventType; public var axisValue:Float; + public var timestamp:Int; - public function new(type:GamepadEventType = null, id:Int = 0, button:Int = 0, axis:Int = 0, value:Float = 0) + public function new(type:GamepadEventType = null, id:Int = 0, button:Int = 0, axis:Int = 0, value:Float = 0, timestamp:Int = 0) { this.type = type; this.id = id; this.button = button; this.axis = axis; this.axisValue = value; + this.timestamp = timestamp; } public function clone():GamepadEventInfo { - return new GamepadEventInfo(type, id, button, axis, axisValue); + return new GamepadEventInfo(type, id, button, axis, axisValue, timestamp); } } @@ -843,18 +849,20 @@ class NativeApplication public var modifier:Int; public var type:KeyEventType; public var windowID:Int; + public var timestamp:Int; - public function new(type:KeyEventType = null, windowID:Int = 0, keyCode:Float = 0, modifier:Int = 0) + public function new(type:KeyEventType = null, windowID:Int = 0, keyCode:Float = 0, modifier:Int = 0, timestamp:Int = 0) { this.type = type; this.windowID = windowID; this.keyCode = keyCode; this.modifier = modifier; + this.timestamp = timestamp; } public function clone():KeyEventInfo { - return new KeyEventInfo(type, windowID, keyCode, modifier); + return new KeyEventInfo(type, windowID, keyCode, modifier, timestamp); } } diff --git a/src/lime/_internal/backend/native/NativeAudioInput.hx b/src/lime/_internal/backend/native/NativeAudioInput.hx new file mode 100644 index 0000000000..813a146684 --- /dev/null +++ b/src/lime/_internal/backend/native/NativeAudioInput.hx @@ -0,0 +1,275 @@ +package lime._internal.backend.native; + +import haxe.io.Bytes; +import lime.media.AudioInput; +import lime.media.AudioInputDevice; +#if (!lime_doc_gen || lime_openal) +import lime.media.openal.AL; +import lime.media.openal.ALC; +import lime.media.openal.ALDevice; +#end + +#if !lime_debug +@:fileXml('tags="haxe,release"') +@:noDebug +#end +@:access(lime.media.AudioInput) +class NativeAudioInput +{ + private var disposed:Bool; + private var handle:#if (!lime_doc_gen || lime_openal) ALDevice #else Dynamic #end; + private var parent:AudioInput; + private var started:Bool; + + public static function getDefaultDevice():AudioInputDevice + { + #if (!lime_doc_gen || lime_openal) + var name = ALC.getString(null, ALC.CAPTURE_DEFAULT_DEVICE_SPECIFIER); + + if (name == null || name == "") + { + return null; + } + + return new AudioInputDevice(name, name, true); + #else + return null; + #end + } + + public static function getDevices():Array + { + #if (!lime_doc_gen || lime_openal) + var defaultDevice = getDefaultDevice(); + var defaultName = defaultDevice != null ? defaultDevice.name : null; + var devices = parseDeviceList(ALC.getString(null, ALC.CAPTURE_DEVICE_SPECIFIER), defaultName); + + if (devices.length == 0 && defaultDevice != null) + { + devices.push(defaultDevice); + } + + return devices; + #else + return []; + #end + } + + public static function isSupported():Bool + { + return getDefaultDevice() != null || getDevices().length > 0; + } + + public function new(parent:AudioInput) + { + this.parent = parent; + + open(); + } + + public function dispose():Void + { + if (disposed) + { + return; + } + + stop(); + + #if (!lime_doc_gen || lime_openal) + if (handle != null) + { + ALC.captureCloseDevice(handle); + handle = null; + } + #end + + disposed = true; + } + + public function getSamplesAvailable():Int + { + #if (!lime_doc_gen || lime_openal) + if (handle == null) + { + return 0; + } + + var values = ALC.getIntegerv(handle, ALC.CAPTURE_SAMPLES, 1); + + if (values != null && values.length > 0) + { + return values[0]; + } + #end + + return 0; + } + + public function read(buffer:Bytes, samples:Int):Int + { + #if (!lime_doc_gen || lime_openal) + if (!started || handle == null || buffer == null || samples <= 0) + { + return 0; + } + + var available = getSamplesAvailable(); + + if (available <= 0) + { + return 0; + } + + var samplesToRead = samples < available ? samples : available; + var frameSize = getFrameSize(); + + if (frameSize <= 0) + { + return 0; + } + + var maxSamples = Std.int(buffer.length / frameSize); + + if (samplesToRead > maxSamples) + { + samplesToRead = maxSamples; + } + + if (samplesToRead <= 0) + { + return 0; + } + + ALC.captureSamples(handle, buffer, samplesToRead); + return samplesToRead; + #end + + return 0; + } + + public function start():Bool + { + #if (!lime_doc_gen || lime_openal) + if (disposed) + { + return false; + } + + if (handle == null) + { + open(); + } + + if (handle == null) + { + return false; + } + + ALC.captureStart(handle); + started = true; + return true; + #else + return false; + #end + } + + public function stop():Void + { + #if (!lime_doc_gen || lime_openal) + if (started && handle != null) + { + ALC.captureStop(handle); + } + #end + + started = false; + } + + private function getFormat():Int + { + #if (!lime_doc_gen || lime_openal) + if (parent.channels == 1) + { + if (parent.bitsPerSample == 8) + { + return AL.FORMAT_MONO8; + } + else if (parent.bitsPerSample == 16) + { + return AL.FORMAT_MONO16; + } + } + else if (parent.channels == 2) + { + if (parent.bitsPerSample == 8) + { + return AL.FORMAT_STEREO8; + } + else if (parent.bitsPerSample == 16) + { + return AL.FORMAT_STEREO16; + } + } + #end + + return 0; + } + + private function getFrameSize():Int + { + return Std.int((parent.channels * parent.bitsPerSample) / 8); + } + + private function open():Void + { + #if (!lime_doc_gen || lime_openal) + if (handle != null) + { + return; + } + + var format = getFormat(); + + if (format == 0) + { + return; + } + + var deviceName = parent.device != null && !parent.device.isDefault ? parent.device.id : null; + handle = ALC.captureOpenDevice(deviceName, parent.sampleRate, format, parent.bufferSize); + #end + } + + private static function parseDeviceList(value:String, defaultName:String):Array + { + var devices = []; + + if (value == null || value == "") + { + return devices; + } + + var hasDefault = false; + var names = value.split(String.fromCharCode(0)); + + for (name in names) + { + if (name == null || name == "") + { + continue; + } + + var isDefault = name == defaultName; + hasDefault = hasDefault || isDefault; + devices.push(new AudioInputDevice(name, name, isDefault)); + } + + if (!hasDefault && defaultName != null && defaultName != "") + { + devices.unshift(new AudioInputDevice(defaultName, defaultName, true)); + } + + return devices; + } +} diff --git a/src/lime/_internal/backend/native/NativeAudioSource.hx b/src/lime/_internal/backend/native/NativeAudioSource.hx index 363aa63117..51c587d73b 100644 --- a/src/lime/_internal/backend/native/NativeAudioSource.hx +++ b/src/lime/_internal/backend/native/NativeAudioSource.hx @@ -32,6 +32,7 @@ class NativeAudioSource #if lime_openalsoft private static var hasDirectChannelsExt:Null; #end + private static var activeSources:Array = []; private var buffers:Array; private var bufferTimeBlocks:Array; @@ -46,8 +47,19 @@ class NativeAudioSource private var playing:Bool; private var position:Vector4; private var queuedBufferCount:Int; + private var queuedBufferLoopCounts:Array; + private var queuedStreamLoopCount:Int; private var readArray:UInt8Array; private var readBuffer:Bytes; + private var recoveryCompleted:Bool; + private var recoveryGain:Float; + private var recoveryLength:Null; + private var recoveryLoops:Int; + private var recoveryPending:Bool; + private var recoveryPitch:Float; + private var recoveryPlaying:Bool; + private var recoveryPosition:Vector4; + private var recoveryTime:Int; private var sdlSoundStream:CFFIPointer; private var samples:Int; private var stream:Bool; @@ -64,10 +76,31 @@ class NativeAudioSource this.parent = parent; position = new Vector4(); + activeSources.push(this); + } + + @:allow(lime.media.AudioManager) + private static function prepareAudioContextRecovery():Void + { + for (source in activeSources.copy()) + { + source.prepareAudioContextRecoverySource(); + } + } + + @:allow(lime.media.AudioManager) + private static function restoreAudioContextRecovery():Void + { + for (source in activeSources.copy()) + { + source.restoreAudioContextRecoverySource(); + } } public function dispose():Void { + activeSources.remove(this); + if (handle != null) { stop(); @@ -100,6 +133,8 @@ class NativeAudioSource streamExhausted = false; streamPosition = 0; queuedBufferCount = 0; + queuedBufferLoopCounts = []; + queuedStreamLoopCount = 0; ownsVorbisStream = false; clearVorbisStream(); clearSDLSoundStream(); @@ -195,8 +230,15 @@ class NativeAudioSource if (parent.buffer.__srcBuffer != null) { AL.bufferData(parent.buffer.__srcBuffer, format, parent.buffer.data, parent.buffer.data.length, parent.buffer.sampleRate); + parent.buffer.__srcBufferContext = AudioManager.__contextGeneration; } } + else if (parent.buffer.__srcBufferContext != AudioManager.__contextGeneration) + { + parent.buffer.__srcBuffer = null; + init(); + return; + } dataLength = parent.buffer.data.length; @@ -211,7 +253,8 @@ class NativeAudioSource #if lime_openalsoft if (hasDirectChannelsExt == null) { - hasDirectChannelsExt = AL.isExtensionPresent("AL_SOFT_direct_channels") && AL.isExtensionPresent("AL_SOFT_direct_channels_remix"); + hasDirectChannelsExt = AL.isExtensionPresent("AL_SOFT_direct_channels") + && AL.isExtensionPresent("AL_SOFT_direct_channels_remix"); } if (hasDirectChannelsExt) @@ -487,6 +530,79 @@ class NativeAudioSource return length - (length % frameSize); } + private function getStreamBytePosition(useSDLSound:Bool, vorbisFile:VorbisFile):Int + { + if (useSDLSound) + { + return Std.int(streamPosition * streamByteRate); + } + + #if lime_vorbis + return (vorbisFile != null) ? Int64.toInt(vorbisFile.pcmTell()) : 0; + #else + return 0; + #end + } + + private function shouldLoopStreamInline():Bool + { + return stream && loops > 0 && length == null; + } + + private function resetStreamForLoop(useSDLSound:Bool):Bool + { + if (!shouldLoopStreamInline() || loops <= queuedStreamLoopCount) + { + return false; + } + + var streamTime = parent.offset; + var reset = useSDLSound ? resetSDLSoundStream(streamTime) : resetVorbisStream(streamTime); + + if (!reset) + { + return false; + } + + queuedStreamLoopCount++; + streamExhausted = false; + return true; + } + + private function consumeProcessedStreamLoopCounts(processed:Int):Void + { + if (queuedBufferLoopCounts == null || processed <= 0) + { + return; + } + + var completedLoops = 0; + for (i in 0...processed) + { + if (queuedBufferLoopCounts.length == 0) + { + break; + } + + completedLoops += queuedBufferLoopCounts.shift(); + } + + if (completedLoops > 0) + { + loops -= completedLoops; + if (loops < 0) + { + loops = 0; + } + + queuedStreamLoopCount -= completedLoops; + if (queuedStreamLoopCount < 0) + { + queuedStreamLoopCount = 0; + } + } + } + private function clearQueuedBuffers():Void { if (handle == null) @@ -503,6 +619,88 @@ class NativeAudioSource } queuedBufferCount = 0; + queuedBufferLoopCounts = []; + queuedStreamLoopCount = 0; + } + + private function prepareAudioContextRecoverySource():Void + { + if (parent.buffer == null) + { + recoveryPending = false; + return; + } + + recoveryPending = true; + recoveryCompleted = completed; + recoveryGain = getGain(); + recoveryLength = length; + recoveryLoops = loops; + recoveryPitch = getPitch(); + recoveryPlaying = playing; + recoveryPosition = getPosition().clone(); + recoveryTime = getCurrentTime(); + + if (streamTimer != null) + { + streamTimer.stop(); + streamTimer = null; + } + + if (timer != null) + { + timer.stop(); + timer = null; + } + + playing = false; + handle = null; + buffers = null; + bufferTimeBlocks = null; + queuedBufferCount = 0; + queuedBufferLoopCounts = []; + queuedStreamLoopCount = 0; + + if (parent.buffer != null) + { + parent.buffer.__srcBuffer = null; + parent.buffer.__srcBufferContext = 0; + } + + clearSDLSoundStream(); + clearVorbisStream(); + } + + private function restoreAudioContextRecoverySource():Void + { + if (!recoveryPending || parent.buffer == null) + { + return; + } + + recoveryPending = false; + completed = recoveryCompleted; + length = recoveryLength; + loops = recoveryLoops; + playing = false; + + init(); + + if (handle == null) + { + return; + } + + setGain(recoveryGain); + setPitch(recoveryPitch); + setPosition(recoveryPosition); + setCurrentTime(recoveryTime); + completed = recoveryCompleted; + + if (recoveryPlaying) + { + play(); + } } private function ensureReadBuffer(length:Int):Bool @@ -622,10 +820,12 @@ class NativeAudioSource if (buffers != null) { queuedBufferCount -= buffers.length; + consumeProcessedStreamLoopCounts(buffers.length); } else { queuedBufferCount -= buffersProcessed; + consumeProcessedStreamLoopCounts(buffersProcessed); } if (queuedBufferCount < 0) @@ -654,13 +854,30 @@ class NativeAudioSource var numBuffers = 0; var bytesRead = 0; + var newBufferLoopCounts = []; for (buffer in buffers) { + var bufferLoopCount = 0; + if (hasKnownStreamLength && position >= dataLength) { - streamExhausted = true; - break; + if (resetStreamForLoop(useSDLSound)) + { + if (!useSDLSound) + { + #if lime_vorbis + vorbisFile = vorbisStream; + #end + } + + position = getStreamBytePosition(useSDLSound, vorbisFile); + } + else + { + streamExhausted = true; + break; + } } var requestLength = hasKnownStreamLength ? (dataLength - position) : STREAM_BUFFER_SIZE; @@ -687,17 +904,57 @@ class NativeAudioSource if (bytesRead <= 0 || readArray == null) { - streamExhausted = true; - break; + if (resetStreamForLoop(useSDLSound)) + { + if (!useSDLSound) + { + #if lime_vorbis + vorbisFile = vorbisStream; + #end + } + + position = getStreamBytePosition(useSDLSound, vorbisFile); + continue; + } + else + { + streamExhausted = true; + break; + } } AL.bufferData(buffer, format, readArray, bytesRead, parent.buffer.sampleRate); position += bytesRead; numBuffers++; + var stopAfterBuffer = false; + if (bytesRead < requestLength || (hasKnownStreamLength && position >= dataLength)) { - streamExhausted = true; + if (resetStreamForLoop(useSDLSound)) + { + bufferLoopCount++; + + if (!useSDLSound) + { + #if lime_vorbis + vorbisFile = vorbisStream; + #end + } + + position = getStreamBytePosition(useSDLSound, vorbisFile); + } + else + { + streamExhausted = true; + stopAfterBuffer = true; + } + } + + newBufferLoopCounts.push(bufferLoopCount); + + if (stopAfterBuffer) + { break; } } @@ -707,6 +964,11 @@ class NativeAudioSource var buffersToQueue = (numBuffers == buffers.length) ? buffers : buffers.slice(0, numBuffers); AL.sourceQueueBuffers(handle, numBuffers, buffersToQueue); queuedBufferCount += numBuffers; + + for (i in 0...numBuffers) + { + queuedBufferLoopCounts.push(newBufferLoopCounts[i]); + } } // OpenAL can unexpectedly stop playback if the buffers run out @@ -754,7 +1016,12 @@ class NativeAudioSource refillBuffers(); - if (playing && timer == null && streamExhausted && queuedBufferCount == 0 && handle != null && AL.getSourcei(handle, AL.SOURCE_STATE) != AL.PLAYING) + if (playing + && timer == null + && streamExhausted + && queuedBufferCount == 0 + && handle != null + && AL.getSourcei(handle, AL.SOURCE_STATE) != AL.PLAYING) { if (length == null && parent.buffer.__srcSDLSoundDuration <= 0) { @@ -824,9 +1091,9 @@ class NativeAudioSource { // `setCurrentTime()` has side effects and is never safe to skip. /* if (value == getCurrentTime()) - { - return value; - } */ + { + return value; + }*/ if (handle != null) { @@ -898,13 +1165,13 @@ class NativeAudioSource var totalLength = getLength(); var timeRemaining = Std.int((totalLength - value) / getPitch()); - if (timeRemaining > 0) + if (timeRemaining > 0 && !shouldLoopStreamInline()) { completed = false; timer = new Timer(timeRemaining); timer.run = timer_onRun; } - else if (stream && totalLength <= 0) + else if (stream && (totalLength <= 0 || shouldLoopStreamInline())) { completed = false; timer = null; diff --git a/src/lime/_internal/backend/native/NativeCFFI.hx b/src/lime/_internal/backend/native/NativeCFFI.hx index fe8bb2cb41..906d38d1fe 100644 --- a/src/lime/_internal/backend/native/NativeCFFI.hx +++ b/src/lime/_internal/backend/native/NativeCFFI.hx @@ -328,6 +328,8 @@ class NativeCFFI @:cffi private static function lime_window_get_context_type(handle:Dynamic):Dynamic; + @:cffi private static function lime_window_create_vulkan_surface(handle:Dynamic, instanceHigh:Int, instanceLow:Int):Dynamic; + @:cffi private static function lime_window_get_display(handle:Dynamic):Int; @:cffi private static function lime_window_get_display_mode(handle:Dynamic):Dynamic; @@ -344,6 +346,316 @@ class NativeCFFI @:cffi private static function lime_window_get_text_input_enabled(handle:Dynamic):Bool; + @:cffi private static function lime_window_get_vulkan_drawable_size(handle:Dynamic):Dynamic; + + @:cffi private static function lime_window_get_vulkan_instance_extensions(handle:Dynamic):Array; + + @:cffi private static function lime_window_get_vulkan_instance_proc_addr(handle:Dynamic):Dynamic; + + @:cffi private static function lime_vk_create_instance(handle:Dynamic, applicationName:String):Dynamic; + + @:cffi private static function lime_vk_destroy_instance(handle:Dynamic, instanceHigh:Int, instanceLow:Int):Void; + + @:cffi private static function lime_vk_destroy_surface(handle:Dynamic, instanceHigh:Int, instanceLow:Int, surfaceHigh:Int, surfaceLow:Int):Void; + + @:cffi private static function lime_vk_get_physical_devices(handle:Dynamic, instanceHigh:Int, instanceLow:Int, surfaceHigh:Int, surfaceLow:Int):Dynamic; + + #if lime_vulkan + @:cffi private static function lime_vk_create_device(handle:Dynamic, instanceHigh:Int, instanceLow:Int, physicalDeviceHigh:Int, physicalDeviceLow:Int, + queueFamilyIndex:Int, extensions:Array):Dynamic; + + @:cffi private static function lime_vk_destroy_device(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int):Void; + + @:cffi private static function lime_vk_device_wait_idle(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int):Bool; + + @:cffi private static function lime_vk_queue_wait_idle(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueHigh:Int, + queueLow:Int):Bool; + + @:cffi private static function lime_vk_create_command_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + queueFamilyIndex:Int, flags:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_command_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandPoolHigh:Int, commandPoolLow:Int):Void; + + @:cffi private static function lime_vk_reset_command_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandPoolHigh:Int, commandPoolLow:Int, flags:Int):Bool; + + @:cffi private static function lime_vk_allocate_command_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandPoolHigh:Int, commandPoolLow:Int, level:Int):Dynamic; + + @:cffi private static function lime_vk_free_command_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandPoolHigh:Int, commandPoolLow:Int, commandBufferHigh:Int, commandBufferLow:Int):Void; + + @:cffi private static function lime_vk_begin_command_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, flags:Int):Bool; + + @:cffi private static function lime_vk_end_command_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int):Bool; + + @:cffi private static function lime_vk_reset_command_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, flags:Int):Bool; + + @:cffi private static function lime_vk_create_semaphore(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_semaphore(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + semaphoreHigh:Int, semaphoreLow:Int):Void; + + @:cffi private static function lime_vk_create_fence(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, flags:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_fence(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, fenceHigh:Int, + fenceLow:Int):Void; + + @:cffi private static function lime_vk_wait_for_fence(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, fenceHigh:Int, + fenceLow:Int, timeoutHigh:Int, timeoutLow:Int):Bool; + + @:cffi private static function lime_vk_reset_fence(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, fenceHigh:Int, + fenceLow:Int):Bool; + + @:cffi private static function lime_vk_queue_submit(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueHigh:Int, + queueLow:Int, commandBufferHigh:Int, commandBufferLow:Int, fenceHigh:Int, fenceLow:Int):Bool; + + @:cffi private static function lime_vk_allocate_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, physicalDeviceHigh:Int, physicalDeviceLow:Int, + deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, memoryTypeBits:Int, properties:Int):Dynamic; + + @:cffi private static function lime_vk_free_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, + memoryLow:Int):Void; + + @:cffi private static function lime_vk_upload_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, + memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Dynamic, byteOffset:Int, byteLength:Int):Bool; + + @:cffi private static function lime_vk_download_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, + memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Dynamic, byteOffset:Int, byteLength:Int):Bool; + + @:cffi private static function lime_vk_map_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, + memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int, flags:Int):Bool; + + @:cffi private static function lime_vk_unmap_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, + memoryLow:Int):Void; + + @:cffi private static function lime_vk_write_mapped_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Dynamic, byteOffset:Int, byteLength:Int):Bool; + + @:cffi private static function lime_vk_flush_mapped_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int):Bool; + + @:cffi private static function lime_vk_invalidate_mapped_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int):Bool; + + @:cffi private static function lime_vk_create_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, sizeHigh:Int, + sizeLow:Int, usage:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, bufferHigh:Int, + bufferLow:Int):Void; + + @:cffi private static function lime_vk_get_buffer_memory_requirements(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + bufferHigh:Int, bufferLow:Int):Dynamic; + + @:cffi private static function lime_vk_bind_buffer_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + bufferHigh:Int, bufferLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int):Bool; + + @:cffi private static function lime_vk_create_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, width:Int, + height:Int, depth:Int, mipLevels:Int, arrayLayers:Int, format:Int, imageType:Int, tiling:Int, usage:Int, samples:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, + imageLow:Int):Void; + + @:cffi private static function lime_vk_get_image_memory_requirements(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + imageHigh:Int, imageLow:Int):Dynamic; + + @:cffi private static function lime_vk_bind_image_memory(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, + imageLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int):Bool; + + @:cffi private static function lime_vk_create_swapchain(handle:Dynamic, instanceHigh:Int, instanceLow:Int, physicalDeviceHigh:Int, physicalDeviceLow:Int, + deviceHigh:Int, deviceLow:Int, surfaceHigh:Int, surfaceLow:Int, queueFamilyIndex:Int, width:Int, height:Int, presentMode:Int, oldSwapchainHigh:Int, + oldSwapchainLow:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_swapchain(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + swapchainHigh:Int, swapchainLow:Int):Void; + + @:cffi private static function lime_vk_get_swapchain_images(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + swapchainHigh:Int, swapchainLow:Int):Dynamic; + + @:cffi private static function lime_vk_acquire_next_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + swapchainHigh:Int, swapchainLow:Int, timeoutHigh:Int, timeoutLow:Int, semaphoreHigh:Int, semaphoreLow:Int, fenceHigh:Int, fenceLow:Int):Dynamic; + + @:cffi private static function lime_vk_queue_present(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, queueHigh:Int, + queueLow:Int, swapchainHigh:Int, swapchainLow:Int, imageIndex:Int, waitSemaphoreHigh:Int, waitSemaphoreLow:Int):Int; + + @:cffi private static function lime_vk_create_image_view(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, + imageLow:Int, format:Int, aspectMask:Int, viewType:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_image_view(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + imageViewHigh:Int, imageViewLow:Int):Void; + + @:cffi private static function lime_vk_create_image_view_ex(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + imageHigh:Int, imageLow:Int, format:Int, aspectMask:Int, viewType:Int, baseMipLevel:Int, levelCount:Int, baseArrayLayer:Int, layerCount:Int):Dynamic; + + @:cffi private static function lime_vk_create_render_pass(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + state:Array):Dynamic; + + @:cffi private static function lime_vk_destroy_render_pass(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + renderPassHigh:Int, renderPassLow:Int):Void; + + @:cffi private static function lime_vk_create_framebuffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + renderPassHigh:Int, renderPassLow:Int, attachments:Array, width:Int, height:Int, layers:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_framebuffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + framebufferHigh:Int, framebufferLow:Int):Void; + + @:cffi private static function lime_vk_create_shader_module(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + bytes:Dynamic, byteOffset:Int, byteLength:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_shader_module(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + shaderModuleHigh:Int, shaderModuleLow:Int):Void; + + @:cffi private static function lime_vk_create_sampler(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, filter:Int, + addressMode:Int, mipmapMode:Int, anisotropyEnable:Bool, maxAnisotropy:Float, compareOp:Int, minLod:Float, maxLod:Float):Dynamic; + + @:cffi private static function lime_vk_destroy_sampler(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, samplerHigh:Int, + samplerLow:Int):Void; + + @:cffi private static function lime_vk_create_descriptor_set_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + bindings:Array):Dynamic; + + @:cffi private static function lime_vk_destroy_descriptor_set_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + layoutHigh:Int, layoutLow:Int):Void; + + @:cffi private static function lime_vk_create_descriptor_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + poolSizes:Array):Dynamic; + + @:cffi private static function lime_vk_destroy_descriptor_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + poolHigh:Int, poolLow:Int):Void; + + @:cffi private static function lime_vk_reset_descriptor_pool(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + poolHigh:Int, poolLow:Int, flags:Int):Bool; + + @:cffi private static function lime_vk_allocate_descriptor_set(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + poolHigh:Int, poolLow:Int, layoutHigh:Int, layoutLow:Int):Dynamic; + + @:cffi private static function lime_vk_update_descriptor_set_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, imageViewHigh:Int, imageViewLow:Int, samplerHigh:Int, samplerLow:Int, imageLayout:Int):Bool; + + @:cffi private static function lime_vk_update_descriptor_set_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, bufferHigh:Int, bufferLow:Int, offset:Int, range:Int):Bool; + + @:cffi private static function lime_vk_update_descriptor_sets(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + writes:Array):Bool; + + @:cffi private static function lime_vk_create_pipeline_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + setLayouts:Array, pushConstantStages:Int, pushConstantSize:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_pipeline_layout(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + layoutHigh:Int, layoutLow:Int):Void; + + @:cffi private static function lime_vk_create_pipeline_cache(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + bytes:Dynamic, byteOffset:Int, byteLength:Int):Dynamic; + + @:cffi private static function lime_vk_destroy_pipeline_cache(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + cacheHigh:Int, cacheLow:Int):Void; + + @:cffi private static function lime_vk_get_pipeline_cache_data(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + cacheHigh:Int, cacheLow:Int, bytes:Dynamic):Bool; + + @:cffi private static function lime_vk_create_graphics_pipeline(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + renderPassHigh:Int, renderPassLow:Int, layoutHigh:Int, layoutLow:Int, vertexShaderHigh:Int, vertexShaderLow:Int, fragmentShaderHigh:Int, + fragmentShaderLow:Int, state:Array):Dynamic; + + @:cffi private static function lime_vk_destroy_pipeline(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + pipelineHigh:Int, pipelineLow:Int):Void; + + @:cffi private static function lime_vk_queue_submit_synced(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + queueHigh:Int, queueLow:Int, commandBufferHigh:Int, commandBufferLow:Int, state:Array):Bool; + + @:cffi private static function lime_vk_cmd_begin_render_pass(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, renderPassHigh:Int, renderPassLow:Int, framebufferHigh:Int, framebufferLow:Int, state:Array, + clear:Array):Bool; + + @:cffi private static function lime_vk_cmd_end_render_pass(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int):Bool; + + @:cffi private static function lime_vk_cmd_bind_pipeline(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, pipelineHigh:Int, pipelineLow:Int, bindPoint:Int):Bool; + + @:cffi private static function lime_vk_cmd_bind_descriptor_set(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, bindPoint:Int, firstSet:Int):Bool; + + @:cffi private static function lime_vk_cmd_bind_descriptor_set_ex(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, state:Array):Bool; + + @:cffi private static function lime_vk_cmd_bind_descriptor_set_dynamic_offset(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, setLow:Int, dynamicOffset:Int, firstSet:Int, + bindPoint:Int):Bool; + + @:cffi private static function lime_vk_cmd_bind_vertex_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, binding:Int, offsetHigh:Int, offsetLow:Int):Bool; + + @:cffi private static function lime_vk_cmd_bind_index_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, offsetHigh:Int, offsetLow:Int, indexType:Int):Bool; + + @:cffi private static function lime_vk_cmd_set_viewport(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, x:Float, y:Float, width:Float, height:Float, minDepth:Float, maxDepth:Float):Bool; + + @:cffi private static function lime_vk_cmd_set_scissor(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, x:Int, y:Int, width:Int, height:Int):Bool; + + @:cffi private static function lime_vk_cmd_draw(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, + commandBufferLow:Int, vertexCount:Int, instanceCount:Int, firstVertex:Int, firstInstance:Int):Bool; + + @:cffi private static function lime_vk_cmd_draw_indexed(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, indexCount:Int, instanceCount:Int, firstIndex:Int, vertexOffset:Int, firstInstance:Int):Bool; + + @:cffi private static function lime_vk_cmd_draw_indirect(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, offsetHigh:Int, offsetLow:Int, drawCount:Int, stride:Int):Bool; + + @:cffi private static function lime_vk_cmd_draw_indexed_indirect(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, offsetHigh:Int, offsetLow:Int, drawCount:Int, stride:Int):Bool; + + @:cffi private static function lime_vk_cmd_copy_buffer(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, destinationLow:Int, state:Array):Bool; + + @:cffi private static function lime_vk_cmd_copy_buffer_to_image_region(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, imageHigh:Int, imageLow:Int, state:Array):Bool; + + @:cffi private static function lime_vk_cmd_copy_image_to_buffer_region(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, bufferHigh:Int, bufferLow:Int, state:Array):Bool; + + @:cffi private static function lime_vk_cmd_pipeline_barrier_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, state:Array):Bool; + + @:cffi private static function lime_vk_cmd_clear_color_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, layout:Int, aspectMask:Int, clear:Array):Bool; + + @:cffi private static function lime_vk_cmd_clear_depth_stencil_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, state:Array, clear:Array):Bool; + + @:cffi private static function lime_vk_cmd_clear_attachments(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, state:Array, clear:Array):Bool; + + @:cffi private static function lime_vk_cmd_blit_image(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, destinationLow:Int, state:Array):Bool; + + @:cffi private static function lime_vk_cmd_push_constants(handle:Dynamic, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, + commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, state:Array, bytes:Dynamic):Bool; + #end + + @:cffi private static function lime_vk_get_last_error():Dynamic; + + @:cffi private static function lime_vulkan_renderer_create(handle:Dynamic, applicationName:String):CFFIPointer; + + @:cffi private static function lime_vulkan_renderer_destroy(handle:Dynamic):Void; + + @:cffi private static function lime_vulkan_renderer_get_info(handle:Dynamic):Dynamic; + + @:cffi private static function lime_vulkan_renderer_get_last_error():Dynamic; + + @:cffi private static function lime_vulkan_renderer_set_overlay(handle:Dynamic, bytes:Dynamic, width:Int, height:Int, x:Int, y:Int):Bool; + + @:cffi private static function lime_vulkan_renderer_clear_overlay(handle:Dynamic):Bool; + + @:cffi private static function lime_vulkan_renderer_render(handle:Dynamic, red:Float, green:Float, blue:Float, alpha:Float):Bool; + + @:cffi private static function lime_vulkan_renderer_resize(handle:Dynamic):Bool; + @:cffi private static function lime_window_get_width(handle:Dynamic):Int; @:cffi private static function lime_window_get_x(handle:Dynamic):Int; @@ -422,16 +734,16 @@ class NativeCFFI "lime_sdl_sound_get_info_from_file", "so", false)); private static var lime_sdl_sound_stream_from_bytes = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_sdl_sound_stream_from_bytes", "oo", false)); - private static var lime_sdl_sound_stream_from_file = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", - "lime_sdl_sound_stream_from_file", "so", false)); + private static var lime_sdl_sound_stream_from_file = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_sdl_sound_stream_from_file", + "so", false)); private static var lime_sdl_sound_stream_read = new cpp.Callablecpp.Object->Int->Int>(cpp.Prime._loadPrime("lime", "lime_sdl_sound_stream_read", "ooii", false)); - private static var lime_sdl_sound_stream_rewind = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", - "lime_sdl_sound_stream_rewind", "ob", false)); - private static var lime_sdl_sound_stream_seek = new cpp.CallableInt->Bool>(cpp.Prime._loadPrime("lime", - "lime_sdl_sound_stream_seek", "oib", false)); - private static var lime_sdl_sound_stream_clear = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", - "lime_sdl_sound_stream_clear", "ov", false)); + private static var lime_sdl_sound_stream_rewind = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_sdl_sound_stream_rewind", "ob", + false)); + private static var lime_sdl_sound_stream_seek = new cpp.CallableInt->Bool>(cpp.Prime._loadPrime("lime", "lime_sdl_sound_stream_seek", "oib", + false)); + private static var lime_sdl_sound_stream_clear = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_sdl_sound_stream_clear", "ov", + false)); private static var lime_bytes_from_data_pointer = new cpp.CallableInt->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_bytes_from_data_pointer", "dioo", false)); private static var lime_bytes_get_data_pointer = new cpp.CallableFloat>(cpp.Prime._loadPrime("lime", "lime_bytes_get_data_pointer", "od", @@ -468,8 +780,7 @@ class NativeCFFI "lime_file_watcher_add_directory", "oobo", false)); private static var lime_file_watcher_remove_directory = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_file_watcher_remove_directory", "oov", false)); - private static var lime_file_watcher_update = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_file_watcher_update", "ov", - false)); + private static var lime_file_watcher_update = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_file_watcher_update", "ov", false)); private static var lime_font_get_ascender = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_font_get_ascender", "oi", false)); private static var lime_font_get_descender = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_font_get_descender", "oi", false)); private static var lime_font_get_family_name = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_font_get_family_name", "oo", @@ -486,10 +797,10 @@ class NativeCFFI "oi", false)); private static var lime_font_get_underline_thickness = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_font_get_underline_thickness", "oi", false)); - private static var lime_font_get_strikethrough_position = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_font_get_strikethrough_position", - "oi", false)); - private static var lime_font_get_strikethrough_thickness = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_font_get_strikethrough_thickness", - "oi", false)); + private static var lime_font_get_strikethrough_position = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", + "lime_font_get_strikethrough_position", "oi", false)); + private static var lime_font_get_strikethrough_thickness = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", + "lime_font_get_strikethrough_thickness", "oi", false)); private static var lime_font_get_units_per_em = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_font_get_units_per_em", "oi", false)); private static var lime_font_load = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_font_load", "oo", false)); private static var lime_font_load_bytes = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_font_load_bytes", "oo", false)); @@ -566,10 +877,8 @@ class NativeCFFI "lime_jpeg_decode_bytes", "oboo", false)); private static var lime_jpeg_decode_file = new cpp.CallableBool->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_jpeg_decode_file", "sboo", false)); - private static var lime_key_code_from_scan_code = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_key_code_from_scan_code", - "ii", false)); - private static var lime_key_code_to_scan_code = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_key_code_to_scan_code", - "ii", false)); + private static var lime_key_code_from_scan_code = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_key_code_from_scan_code", "ii", false)); + private static var lime_key_code_to_scan_code = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_key_code_to_scan_code", "ii", false)); private static var lime_key_event_manager_register = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_key_event_manager_register", "oov", false)); private static var lime_lzma_compress = new cpp.Callablecpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_lzma_compress", "ooo", @@ -602,7 +911,8 @@ class NativeCFFI private static var lime_system_get_display = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_system_get_display", "io", false)); private static var lime_system_get_ios_tablet = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_system_get_ios_tablet", "b", false)); private static var lime_system_get_num_displays = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_system_get_num_displays", "i", false)); - private static var lime_system_get_device_orientation = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_system_get_device_orientation", "i", false)); + private static var lime_system_get_device_orientation = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_system_get_device_orientation", + "i", false)); private static var lime_system_get_platform_label = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_system_get_platform_label", "o", false)); private static var lime_system_get_platform_name = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_system_get_platform_name", "o", @@ -619,8 +929,7 @@ class NativeCFFI private static var lime_window_alert = new cpp.CallableString->String->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_alert", "ossv", false)); private static var lime_window_close = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_close", "ov", false)); - private static var lime_window_context_flip = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_context_flip", "ov", - false)); + private static var lime_window_context_flip = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_context_flip", "ov", false)); private static var lime_window_context_lock = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_window_context_lock", "oo", false)); private static var lime_window_context_make_current = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", @@ -633,29 +942,246 @@ class NativeCFFI private static var lime_window_get_context = new cpp.CallableFloat>(cpp.Prime._loadPrime("lime", "lime_window_get_context", "od", false)); private static var lime_window_get_context_type = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_window_get_context_type", "oo", false)); + private static var lime_window_create_vulkan_surface = new cpp.CallableInt->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_window_create_vulkan_surface", "oiio", false)); private static var lime_window_get_display = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_window_get_display", "oi", false)); private static var lime_window_get_display_mode = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_window_get_display_mode", "oo", false)); private static var lime_window_get_height = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_window_get_height", "oi", false)); private static var lime_window_get_id = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_window_get_id", "oi", false)); - private static var lime_window_get_mouse_lock = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_window_get_mouse_lock", "ob", - false)); + private static var lime_window_get_mouse_lock = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_window_get_mouse_lock", "ob", false)); private static var lime_window_get_opacity = new cpp.CallableFloat>(cpp.Prime._loadPrime("lime", "lime_window_get_opacity", "od", false)); private static var lime_window_get_scale = new cpp.CallableFloat>(cpp.Prime._loadPrime("lime", "lime_window_get_scale", "od", false)); private static var lime_window_get_text_input_enabled = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_window_get_text_input_enabled", "ob", false)); + private static var lime_window_get_vulkan_drawable_size = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", + "lime_window_get_vulkan_drawable_size", "oo", false)); + private static var lime_window_get_vulkan_instance_extensions = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", + "lime_window_get_vulkan_instance_extensions", "oo", false)); + private static var lime_window_get_vulkan_instance_proc_addr = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", + "lime_window_get_vulkan_instance_proc_addr", "oo", false)); + private static var lime_vk_create_instance = new cpp.CallableString->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_instance", + "oso", false)); + private static var lime_vk_destroy_instance = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_instance", + "oiiv", false)); + private static var lime_vk_destroy_surface = new cpp.CallableInt->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_surface", "oiiiiv", false)); + private static var lime_vk_get_physical_devices = new cpp.CallableInt->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_get_physical_devices", "oiiiio", false)); + #if lime_vulkan + private static var lime_vk_create_device = new cpp.CallableInt->Int->Int->Int->Int->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_device", "oiiiiioo", false)); + private static var lime_vk_destroy_device = new cpp.CallableInt->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_device", "oiiiiv", false)); + private static var lime_vk_device_wait_idle = new cpp.CallableInt->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_device_wait_idle", "oiiiib", false)); + private static var lime_vk_queue_wait_idle = new cpp.CallableInt->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_queue_wait_idle", "oiiiiiib", false)); + private static var lime_vk_create_command_pool = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_command_pool", "oiiiiiio", false)); + private static var lime_vk_destroy_command_pool = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_command_pool", "oiiiiiiv", false)); + private static var lime_vk_reset_command_pool = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_reset_command_pool", "oiiiiiiib", false)); + private static var lime_vk_allocate_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_allocate_command_buffer", "oiiiiiiio", false)); + private static var lime_vk_free_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int-> + cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_free_command_buffer", "oiiiiiiiiv", false)); + private static var lime_vk_begin_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_begin_command_buffer", "oiiiiiiib", false)); + private static var lime_vk_end_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_end_command_buffer", "oiiiiiib", false)); + private static var lime_vk_reset_command_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_reset_command_buffer", "oiiiiiiib", false)); + private static var lime_vk_create_semaphore = new cpp.CallableInt->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_semaphore", "oiiiio", false)); + private static var lime_vk_destroy_semaphore = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_semaphore", "oiiiiiiv", false)); + private static var lime_vk_create_fence = new cpp.CallableInt->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_fence", "oiiiiio", false)); + private static var lime_vk_destroy_fence = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_fence", "oiiiiiiv", false)); + private static var lime_vk_wait_for_fence = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_wait_for_fence", "oiiiiiiiib", false)); + private static var lime_vk_reset_fence = new cpp.CallableInt->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_reset_fence", "oiiiiiib", false)); + private static var lime_vk_queue_submit = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_queue_submit", "oiiiiiiiiiib", false)); + private static var lime_vk_allocate_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_allocate_memory", "oiiiiiiiiiio", false)); + private static var lime_vk_free_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_free_memory", "oiiiiiiv", false)); + private static var lime_vk_upload_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_upload_memory", "oiiiiiiiioiib", false)); + private static var lime_vk_download_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_download_memory", "oiiiiiiiioiib", false)); + private static var lime_vk_map_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_map_memory", "oiiiiiiiiiiib", false)); + private static var lime_vk_unmap_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_unmap_memory", "oiiiiiiv", false)); + private static var lime_vk_write_mapped_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_write_mapped_memory", "oiiiiiiiioiib", false)); + private static var lime_vk_flush_mapped_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_flush_mapped_memory", "oiiiiiiiiiib", false)); + private static var lime_vk_invalidate_mapped_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_invalidate_mapped_memory", "oiiiiiiiiiib", false)); + private static var lime_vk_create_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_buffer", "oiiiiiiio", false)); + private static var lime_vk_destroy_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_buffer", "oiiiiiiv", false)); + private static var lime_vk_get_buffer_memory_requirements = new cpp.CallableInt->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_get_buffer_memory_requirements", "oiiiiiio", false)); + private static var lime_vk_bind_buffer_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_bind_buffer_memory", "oiiiiiiiiiib", false)); + private static var lime_vk_create_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_image", "oiiiiiiiiiiiiiio", false)); + private static var lime_vk_destroy_image = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_image", "oiiiiiiv", false)); + private static var lime_vk_get_image_memory_requirements = new cpp.CallableInt->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_get_image_memory_requirements", "oiiiiiio", false)); + private static var lime_vk_bind_image_memory = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_bind_image_memory", "oiiiiiiiiiib", false)); + private static var lime_vk_create_swapchain = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_swapchain", "oiiiiiiiiiiiiiio", false)); + private static var lime_vk_destroy_swapchain = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_swapchain", "oiiiiiiv", false)); + private static var lime_vk_get_swapchain_images = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_get_swapchain_images", "oiiiiiio", false)); + private static var lime_vk_acquire_next_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_acquire_next_image", "oiiiiiiiiiiiio", false)); + private static var lime_vk_queue_present = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Int>(cpp.Prime._loadPrime("lime", "lime_vk_queue_present", "oiiiiiiiiiiii", false)); + private static var lime_vk_create_image_view = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_image_view", "oiiiiiiiiio", false)); + private static var lime_vk_destroy_image_view = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_image_view", "oiiiiiiv", false)); + private static var lime_vk_create_image_view_ex = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_image_view_ex", "oiiiiiiiiiiiiio", false)); + private static var lime_vk_create_render_pass = new cpp.CallableInt->Int->Int->Int->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_render_pass", "oiiiioo", false)); + private static var lime_vk_destroy_render_pass = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_render_pass", "oiiiiiiv", false)); + private static var lime_vk_create_framebuffer = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_framebuffer", "oiiiiiioiiio", false)); + private static var lime_vk_destroy_framebuffer = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_framebuffer", "oiiiiiiv", false)); + private static var lime_vk_create_shader_module = new cpp.CallableInt->Int->Int->Int->cpp.Object->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_shader_module", "oiiiioiio", false)); + private static var lime_vk_destroy_shader_module = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_shader_module", "oiiiiiiv", false)); + private static var lime_vk_create_sampler = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Bool->Float->Int->Float->Float-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_sampler", "oiiiiiiibdiddo", false)); + private static var lime_vk_destroy_sampler = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_sampler", "oiiiiiiv", false)); + private static var lime_vk_create_descriptor_set_layout = new cpp.CallableInt->Int->Int->Int->cpp.Object-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_descriptor_set_layout", "oiiiioo", false)); + private static var lime_vk_destroy_descriptor_set_layout = new cpp.CallableInt->Int->Int->Int->Int->Int-> + cpp.Void>(cpp.Prime._loadPrime("lime", "lime_vk_destroy_descriptor_set_layout", "oiiiiiiv", false)); + private static var lime_vk_create_descriptor_pool = new cpp.CallableInt->Int->Int->Int->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vk_create_descriptor_pool", "oiiiioo", false)); + private static var lime_vk_destroy_descriptor_pool = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_descriptor_pool", "oiiiiiiv", false)); + private static var lime_vk_reset_descriptor_pool = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_reset_descriptor_pool", "oiiiiiiib", false)); + private static var lime_vk_allocate_descriptor_set = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_allocate_descriptor_set", "oiiiiiiiio", false)); + private static var lime_vk_update_descriptor_set_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_update_descriptor_set_image", "oiiiiiiiiiiiiib", false)); + private static var lime_vk_update_descriptor_set_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_update_descriptor_set_buffer", "oiiiiiiiiiiiib", false)); + private static var lime_vk_update_descriptor_sets = new cpp.CallableInt->Int->Int->Int->cpp.Object->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_update_descriptor_sets", "oiiiiob", false)); + private static var lime_vk_create_pipeline_layout = new cpp.CallableInt->Int->Int->Int->cpp.Object->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_pipeline_layout", "oiiiioiio", false)); + private static var lime_vk_destroy_pipeline_layout = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_pipeline_layout", "oiiiiiiv", false)); + private static var lime_vk_create_pipeline_cache = new cpp.CallableInt->Int->Int->Int->cpp.Object->Int->Int-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_pipeline_cache", "oiiiioiio", false)); + private static var lime_vk_destroy_pipeline_cache = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_pipeline_cache", "oiiiiiiv", false)); + private static var lime_vk_get_pipeline_cache_data = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_get_pipeline_cache_data", "oiiiiiiob", false)); + private static var lime_vk_create_graphics_pipeline = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + cpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_create_graphics_pipeline", "oiiiiiiiiiiiioo", false)); + private static var lime_vk_destroy_pipeline = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_vk_destroy_pipeline", "oiiiiiiv", false)); + private static var lime_vk_queue_submit_synced = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_queue_submit_synced", "oiiiiiiiiob", false)); + private static var lime_vk_cmd_begin_render_pass = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_begin_render_pass", "oiiiiiiiiiioob", false)); + private static var lime_vk_cmd_end_render_pass = new cpp.CallableInt->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_cmd_end_render_pass", "oiiiiiib", false)); + private static var lime_vk_cmd_bind_pipeline = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_cmd_bind_pipeline", "oiiiiiiiiib", false)); + private static var lime_vk_cmd_bind_descriptor_set = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_descriptor_set", "oiiiiiiiiiiiib", false)); + private static var lime_vk_cmd_bind_descriptor_set_ex = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_descriptor_set_ex", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_bind_descriptor_set_dynamic_offset = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Int->Int->Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_descriptor_set_dynamic_offset", "oiiiiiiiiiiiiib", false)); + private static var lime_vk_cmd_bind_vertex_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_vertex_buffer", "oiiiiiiiiiiib", false)); + private static var lime_vk_cmd_bind_index_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_bind_index_buffer", "oiiiiiiiiiiib", false)); + private static var lime_vk_cmd_set_viewport = new cpp.CallableInt->Int->Int->Int->Int->Int->Float->Float->Float->Float->Float->Float-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_set_viewport", "oiiiiiiddddddb", false)); + private static var lime_vk_cmd_set_scissor = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_set_scissor", "oiiiiiiiiiib", false)); + private static var lime_vk_cmd_draw = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vk_cmd_draw", "oiiiiiiiiiib", false)); + private static var lime_vk_cmd_draw_indexed = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_draw_indexed", "oiiiiiiiiiiib", false)); + private static var lime_vk_cmd_draw_indirect = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_draw_indirect", "oiiiiiiiiiiiib", false)); + private static var lime_vk_cmd_draw_indexed_indirect = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int->Int-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_draw_indexed_indirect", "oiiiiiiiiiiiib", false)); + private static var lime_vk_cmd_copy_buffer = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_buffer", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_copy_buffer_to_image_region = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_buffer_to_image_region", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_copy_image_to_buffer_region = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_copy_image_to_buffer_region", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_pipeline_barrier_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_pipeline_barrier_image", "oiiiiiiiiob", false)); + private static var lime_vk_cmd_clear_color_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_clear_color_image", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_clear_depth_stencil_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_clear_depth_stencil_image", "oiiiiiiiioob", false)); + private static var lime_vk_cmd_clear_attachments = new cpp.CallableInt->Int->Int->Int->Int->Int->cpp.Object->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_clear_attachments", "oiiiiiioob", false)); + private static var lime_vk_cmd_blit_image = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->Int->Int->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_blit_image", "oiiiiiiiiiiob", false)); + private static var lime_vk_cmd_push_constants = new cpp.CallableInt->Int->Int->Int->Int->Int->Int->Int->cpp.Object->cpp.Object-> + Bool>(cpp.Prime._loadPrime("lime", "lime_vk_cmd_push_constants", "oiiiiiiiioob", false)); + #end + private static var lime_vk_get_last_error = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_vk_get_last_error", "o", false)); + private static var lime_vulkan_renderer_create = new cpp.CallableString->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vulkan_renderer_create", "oso", false)); + private static var lime_vulkan_renderer_destroy = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_vulkan_renderer_destroy", + "ov", false)); + private static var lime_vulkan_renderer_get_info = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_vulkan_renderer_get_info", + "oo", false)); + private static var lime_vulkan_renderer_get_last_error = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", + "lime_vulkan_renderer_get_last_error", "o", false)); + private static var lime_vulkan_renderer_set_overlay = new cpp.Callablecpp.Object->Int->Int->Int->Int->Bool>(cpp.Prime._loadPrime("lime", + "lime_vulkan_renderer_set_overlay", "ooiiiib", false)); + private static var lime_vulkan_renderer_clear_overlay = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", + "lime_vulkan_renderer_clear_overlay", "ob", false)); + private static var lime_vulkan_renderer_render = new cpp.CallableFloat->Float->Float->Float->Bool>(cpp.Prime._loadPrime("lime", + "lime_vulkan_renderer_render", "oddddb", false)); + private static var lime_vulkan_renderer_resize = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_vulkan_renderer_resize", "ob", + false)); private static var lime_window_get_width = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_window_get_width", "oi", false)); private static var lime_window_get_x = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_window_get_x", "oi", false)); private static var lime_window_get_y = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_window_get_y", "oi", false)); private static var lime_window_move = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_move", "oiiv", false)); private static var lime_window_read_pixels = new cpp.Callablecpp.Object->cpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_window_read_pixels", "oooo", false)); - private static var lime_window_resize = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_resize", "oiiv", - false)); - private static var lime_window_set_minimum_size = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_set_minimum_size", "oiiv", - false)); - private static var lime_window_set_maximum_size = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_set_maximum_size", "oiiv", - false)); + private static var lime_window_resize = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_resize", "oiiv", false)); + private static var lime_window_set_minimum_size = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_window_set_minimum_size", "oiiv", false)); + private static var lime_window_set_maximum_size = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_window_set_maximum_size", "oiiv", false)); private static var lime_window_set_borderless = new cpp.CallableBool->Bool>(cpp.Prime._loadPrime("lime", "lime_window_set_borderless", "obb", false)); private static var lime_window_set_cursor = new cpp.CallableInt->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_window_set_cursor", "oiv", @@ -684,8 +1210,8 @@ class NativeCFFI false)); private static var lime_window_set_visible = new cpp.CallableBool->Bool>(cpp.Prime._loadPrime("lime", "lime_window_set_visible", "obb", false)); - private static var lime_window_set_always_on_top = new cpp.CallableBool->Bool>(cpp.Prime._loadPrime("lime", "lime_window_set_always_on_top", "obb", - false)); + private static var lime_window_set_always_on_top = new cpp.CallableBool->Bool>(cpp.Prime._loadPrime("lime", "lime_window_set_always_on_top", + "obb", false)); private static var lime_window_warp_mouse = new cpp.CallableInt->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_window_warp_mouse", "oiiv", false)); private static var lime_window_event_manager_register = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", @@ -831,6 +1357,7 @@ class NativeCFFI private static var lime_window_focus = CFFI.load("lime", "lime_window_focus", 1); private static var lime_window_get_context = CFFI.load("lime", "lime_window_get_context", 1); private static var lime_window_get_context_type = CFFI.load("lime", "lime_window_get_context_type", 1); + private static var lime_window_create_vulkan_surface = CFFI.load("lime", "lime_window_create_vulkan_surface", 3); private static var lime_window_get_display = CFFI.load("lime", "lime_window_get_display", 1); private static var lime_window_get_display_mode = CFFI.load("lime", "lime_window_get_display_mode", 1); private static var lime_window_get_height = CFFI.load("lime", "lime_window_get_height", 1); @@ -839,6 +1366,116 @@ class NativeCFFI private static var lime_window_get_opacity = CFFI.load("lime", "lime_window_get_opacity", 1); private static var lime_window_get_scale = CFFI.load("lime", "lime_window_get_scale", 1); private static var lime_window_get_text_input_enabled = CFFI.load("lime", "lime_window_get_text_input_enabled", 1); + private static var lime_window_get_vulkan_drawable_size = CFFI.load("lime", "lime_window_get_vulkan_drawable_size", 1); + private static var lime_window_get_vulkan_instance_extensions = CFFI.load("lime", "lime_window_get_vulkan_instance_extensions", 1); + private static var lime_window_get_vulkan_instance_proc_addr = CFFI.load("lime", "lime_window_get_vulkan_instance_proc_addr", 1); + private static var lime_vk_create_instance = CFFI.load("lime", "lime_vk_create_instance", 2); + private static var lime_vk_destroy_instance = CFFI.load("lime", "lime_vk_destroy_instance", 3); + private static var lime_vk_destroy_surface = CFFI.load("lime", "lime_vk_destroy_surface", 5); + private static var lime_vk_get_physical_devices = CFFI.load("lime", "lime_vk_get_physical_devices", 5); + #if lime_vulkan + private static var lime_vk_create_device = CFFI.load("lime", "lime_vk_create_device", -1); + private static var lime_vk_destroy_device = CFFI.load("lime", "lime_vk_destroy_device", 5); + private static var lime_vk_device_wait_idle = CFFI.load("lime", "lime_vk_device_wait_idle", 5); + private static var lime_vk_queue_wait_idle = CFFI.load("lime", "lime_vk_queue_wait_idle", -1); + private static var lime_vk_create_command_pool = CFFI.load("lime", "lime_vk_create_command_pool", -1); + private static var lime_vk_destroy_command_pool = CFFI.load("lime", "lime_vk_destroy_command_pool", -1); + private static var lime_vk_reset_command_pool = CFFI.load("lime", "lime_vk_reset_command_pool", -1); + private static var lime_vk_allocate_command_buffer = CFFI.load("lime", "lime_vk_allocate_command_buffer", -1); + private static var lime_vk_free_command_buffer = CFFI.load("lime", "lime_vk_free_command_buffer", -1); + private static var lime_vk_begin_command_buffer = CFFI.load("lime", "lime_vk_begin_command_buffer", -1); + private static var lime_vk_end_command_buffer = CFFI.load("lime", "lime_vk_end_command_buffer", -1); + private static var lime_vk_reset_command_buffer = CFFI.load("lime", "lime_vk_reset_command_buffer", -1); + private static var lime_vk_create_semaphore = CFFI.load("lime", "lime_vk_create_semaphore", 5); + private static var lime_vk_destroy_semaphore = CFFI.load("lime", "lime_vk_destroy_semaphore", -1); + private static var lime_vk_create_fence = CFFI.load("lime", "lime_vk_create_fence", -1); + private static var lime_vk_destroy_fence = CFFI.load("lime", "lime_vk_destroy_fence", -1); + private static var lime_vk_wait_for_fence = CFFI.load("lime", "lime_vk_wait_for_fence", -1); + private static var lime_vk_reset_fence = CFFI.load("lime", "lime_vk_reset_fence", -1); + private static var lime_vk_queue_submit = CFFI.load("lime", "lime_vk_queue_submit", -1); + private static var lime_vk_allocate_memory = CFFI.load("lime", "lime_vk_allocate_memory", -1); + private static var lime_vk_free_memory = CFFI.load("lime", "lime_vk_free_memory", -1); + private static var lime_vk_upload_memory = CFFI.load("lime", "lime_vk_upload_memory", -1); + private static var lime_vk_download_memory = CFFI.load("lime", "lime_vk_download_memory", -1); + private static var lime_vk_map_memory = CFFI.load("lime", "lime_vk_map_memory", -1); + private static var lime_vk_unmap_memory = CFFI.load("lime", "lime_vk_unmap_memory", -1); + private static var lime_vk_write_mapped_memory = CFFI.load("lime", "lime_vk_write_mapped_memory", -1); + private static var lime_vk_flush_mapped_memory = CFFI.load("lime", "lime_vk_flush_mapped_memory", -1); + private static var lime_vk_invalidate_mapped_memory = CFFI.load("lime", "lime_vk_invalidate_mapped_memory", -1); + private static var lime_vk_create_buffer = CFFI.load("lime", "lime_vk_create_buffer", -1); + private static var lime_vk_destroy_buffer = CFFI.load("lime", "lime_vk_destroy_buffer", -1); + private static var lime_vk_get_buffer_memory_requirements = CFFI.load("lime", "lime_vk_get_buffer_memory_requirements", -1); + private static var lime_vk_bind_buffer_memory = CFFI.load("lime", "lime_vk_bind_buffer_memory", -1); + private static var lime_vk_create_image = CFFI.load("lime", "lime_vk_create_image", -1); + private static var lime_vk_destroy_image = CFFI.load("lime", "lime_vk_destroy_image", -1); + private static var lime_vk_get_image_memory_requirements = CFFI.load("lime", "lime_vk_get_image_memory_requirements", -1); + private static var lime_vk_bind_image_memory = CFFI.load("lime", "lime_vk_bind_image_memory", -1); + private static var lime_vk_create_swapchain = CFFI.load("lime", "lime_vk_create_swapchain", -1); + private static var lime_vk_destroy_swapchain = CFFI.load("lime", "lime_vk_destroy_swapchain", -1); + private static var lime_vk_get_swapchain_images = CFFI.load("lime", "lime_vk_get_swapchain_images", -1); + private static var lime_vk_acquire_next_image = CFFI.load("lime", "lime_vk_acquire_next_image", -1); + private static var lime_vk_queue_present = CFFI.load("lime", "lime_vk_queue_present", -1); + private static var lime_vk_create_image_view = CFFI.load("lime", "lime_vk_create_image_view", -1); + private static var lime_vk_destroy_image_view = CFFI.load("lime", "lime_vk_destroy_image_view", -1); + private static var lime_vk_create_image_view_ex = CFFI.load("lime", "lime_vk_create_image_view_ex", -1); + private static var lime_vk_create_render_pass = CFFI.load("lime", "lime_vk_create_render_pass", -1); + private static var lime_vk_destroy_render_pass = CFFI.load("lime", "lime_vk_destroy_render_pass", -1); + private static var lime_vk_create_framebuffer = CFFI.load("lime", "lime_vk_create_framebuffer", -1); + private static var lime_vk_destroy_framebuffer = CFFI.load("lime", "lime_vk_destroy_framebuffer", -1); + private static var lime_vk_create_shader_module = CFFI.load("lime", "lime_vk_create_shader_module", -1); + private static var lime_vk_destroy_shader_module = CFFI.load("lime", "lime_vk_destroy_shader_module", -1); + private static var lime_vk_create_sampler = CFFI.load("lime", "lime_vk_create_sampler", -1); + private static var lime_vk_destroy_sampler = CFFI.load("lime", "lime_vk_destroy_sampler", -1); + private static var lime_vk_create_descriptor_set_layout = CFFI.load("lime", "lime_vk_create_descriptor_set_layout", -1); + private static var lime_vk_destroy_descriptor_set_layout = CFFI.load("lime", "lime_vk_destroy_descriptor_set_layout", -1); + private static var lime_vk_create_descriptor_pool = CFFI.load("lime", "lime_vk_create_descriptor_pool", -1); + private static var lime_vk_destroy_descriptor_pool = CFFI.load("lime", "lime_vk_destroy_descriptor_pool", -1); + private static var lime_vk_reset_descriptor_pool = CFFI.load("lime", "lime_vk_reset_descriptor_pool", -1); + private static var lime_vk_allocate_descriptor_set = CFFI.load("lime", "lime_vk_allocate_descriptor_set", -1); + private static var lime_vk_update_descriptor_set_image = CFFI.load("lime", "lime_vk_update_descriptor_set_image", -1); + private static var lime_vk_update_descriptor_set_buffer = CFFI.load("lime", "lime_vk_update_descriptor_set_buffer", -1); + private static var lime_vk_update_descriptor_sets = CFFI.load("lime", "lime_vk_update_descriptor_sets", -1); + private static var lime_vk_create_pipeline_layout = CFFI.load("lime", "lime_vk_create_pipeline_layout", -1); + private static var lime_vk_destroy_pipeline_layout = CFFI.load("lime", "lime_vk_destroy_pipeline_layout", -1); + private static var lime_vk_create_pipeline_cache = CFFI.load("lime", "lime_vk_create_pipeline_cache", -1); + private static var lime_vk_destroy_pipeline_cache = CFFI.load("lime", "lime_vk_destroy_pipeline_cache", -1); + private static var lime_vk_get_pipeline_cache_data = CFFI.load("lime", "lime_vk_get_pipeline_cache_data", -1); + private static var lime_vk_create_graphics_pipeline = CFFI.load("lime", "lime_vk_create_graphics_pipeline", -1); + private static var lime_vk_destroy_pipeline = CFFI.load("lime", "lime_vk_destroy_pipeline", -1); + private static var lime_vk_queue_submit_synced = CFFI.load("lime", "lime_vk_queue_submit_synced", -1); + private static var lime_vk_cmd_begin_render_pass = CFFI.load("lime", "lime_vk_cmd_begin_render_pass", -1); + private static var lime_vk_cmd_end_render_pass = CFFI.load("lime", "lime_vk_cmd_end_render_pass", -1); + private static var lime_vk_cmd_bind_pipeline = CFFI.load("lime", "lime_vk_cmd_bind_pipeline", -1); + private static var lime_vk_cmd_bind_descriptor_set = CFFI.load("lime", "lime_vk_cmd_bind_descriptor_set", -1); + private static var lime_vk_cmd_bind_descriptor_set_ex = CFFI.load("lime", "lime_vk_cmd_bind_descriptor_set_ex", -1); + private static var lime_vk_cmd_bind_descriptor_set_dynamic_offset = CFFI.load("lime", "lime_vk_cmd_bind_descriptor_set_dynamic_offset", -1); + private static var lime_vk_cmd_bind_vertex_buffer = CFFI.load("lime", "lime_vk_cmd_bind_vertex_buffer", -1); + private static var lime_vk_cmd_bind_index_buffer = CFFI.load("lime", "lime_vk_cmd_bind_index_buffer", -1); + private static var lime_vk_cmd_set_viewport = CFFI.load("lime", "lime_vk_cmd_set_viewport", -1); + private static var lime_vk_cmd_set_scissor = CFFI.load("lime", "lime_vk_cmd_set_scissor", -1); + private static var lime_vk_cmd_draw = CFFI.load("lime", "lime_vk_cmd_draw", -1); + private static var lime_vk_cmd_draw_indexed = CFFI.load("lime", "lime_vk_cmd_draw_indexed", -1); + private static var lime_vk_cmd_draw_indirect = CFFI.load("lime", "lime_vk_cmd_draw_indirect", -1); + private static var lime_vk_cmd_draw_indexed_indirect = CFFI.load("lime", "lime_vk_cmd_draw_indexed_indirect", -1); + private static var lime_vk_cmd_copy_buffer = CFFI.load("lime", "lime_vk_cmd_copy_buffer", -1); + private static var lime_vk_cmd_copy_buffer_to_image_region = CFFI.load("lime", "lime_vk_cmd_copy_buffer_to_image_region", -1); + private static var lime_vk_cmd_copy_image_to_buffer_region = CFFI.load("lime", "lime_vk_cmd_copy_image_to_buffer_region", -1); + private static var lime_vk_cmd_pipeline_barrier_image = CFFI.load("lime", "lime_vk_cmd_pipeline_barrier_image", -1); + private static var lime_vk_cmd_clear_color_image = CFFI.load("lime", "lime_vk_cmd_clear_color_image", -1); + private static var lime_vk_cmd_clear_depth_stencil_image = CFFI.load("lime", "lime_vk_cmd_clear_depth_stencil_image", -1); + private static var lime_vk_cmd_clear_attachments = CFFI.load("lime", "lime_vk_cmd_clear_attachments", -1); + private static var lime_vk_cmd_blit_image = CFFI.load("lime", "lime_vk_cmd_blit_image", -1); + private static var lime_vk_cmd_push_constants = CFFI.load("lime", "lime_vk_cmd_push_constants", -1); + #end + private static var lime_vk_get_last_error = CFFI.load("lime", "lime_vk_get_last_error", 0); + private static var lime_vulkan_renderer_create = CFFI.load("lime", "lime_vulkan_renderer_create", 2); + private static var lime_vulkan_renderer_destroy = CFFI.load("lime", "lime_vulkan_renderer_destroy", 1); + private static var lime_vulkan_renderer_get_info = CFFI.load("lime", "lime_vulkan_renderer_get_info", 1); + private static var lime_vulkan_renderer_get_last_error = CFFI.load("lime", "lime_vulkan_renderer_get_last_error", 0); + private static var lime_vulkan_renderer_set_overlay = CFFI.load("lime", "lime_vulkan_renderer_set_overlay", -1); + private static var lime_vulkan_renderer_clear_overlay = CFFI.load("lime", "lime_vulkan_renderer_clear_overlay", 1); + private static var lime_vulkan_renderer_render = CFFI.load("lime", "lime_vulkan_renderer_render", 5); + private static var lime_vulkan_renderer_resize = CFFI.load("lime", "lime_vulkan_renderer_resize", 1); private static var lime_window_get_width = CFFI.load("lime", "lime_window_get_width", 1); private static var lime_window_get_x = CFFI.load("lime", "lime_window_get_x", 1); private static var lime_window_get_y = CFFI.load("lime", "lime_window_get_y", 1); @@ -1008,8 +1645,7 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_file_dialog_open_file") private static function lime_file_dialog_open_file(title:String, filter:String, - defaultPath:String):hl.Bytes + @:hlNative("lime", "hl_file_dialog_open_file") private static function lime_file_dialog_open_file(title:String, filter:String, defaultPath:String):hl.Bytes { return null; } @@ -1020,8 +1656,7 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_file_dialog_save_file") private static function lime_file_dialog_save_file(title:String, filter:String, - defaultPath:String):hl.Bytes + @:hlNative("lime", "hl_file_dialog_save_file") private static function lime_file_dialog_save_file(title:String, filter:String, defaultPath:String):hl.Bytes { return null; } @@ -1037,8 +1672,7 @@ class NativeCFFI return 0; } - @:hlNative("lime", "hl_file_watcher_remove_directory") private static function lime_file_watcher_remove_directory(handle:CFFIPointer, - watchID:Int):Void {} + @:hlNative("lime", "hl_file_watcher_remove_directory") private static function lime_file_watcher_remove_directory(handle:CFFIPointer, watchID:Int):Void {} @:hlNative("lime", "hl_file_watcher_update") private static function lime_file_watcher_update(handle:CFFIPointer):Void {} @@ -1150,315 +1784,921 @@ class NativeCFFI @:hlNative("lime", "hl_gamepad_add_mappings") private static function lime_gamepad_add_mappings(mappings:hl.NativeArray):Void {} - @:hlNative("lime", "hl_gamepad_get_device_guid") private static function lime_gamepad_get_device_guid(id:Int):hl.Bytes + @:hlNative("lime", "hl_gamepad_get_device_guid") private static function lime_gamepad_get_device_guid(id:Int):hl.Bytes + { + return null; + } + + @:hlNative("lime", "hl_gamepad_get_device_name") private static function lime_gamepad_get_device_name(id:Int):hl.Bytes + { + return null; + } + + @:hlNative("lime", "hl_gamepad_rumble") private static function lime_gamepad_rumble(id:Int, lowFrequencyRumble:Float, highFrequencyRumble:Float, + duration:Int):Void {} + + @:hlNative("lime", "hl_gamepad_event_manager_register") private static function lime_gamepad_event_manager_register(callback:Void->Void, + eventObject:GamepadEventInfo):Void {} + + @:hlNative("lime", "hl_gzip_compress") private static function lime_gzip_compress(data:Bytes, bytes:Bytes):Bytes + { + return null; + } + + @:hlNative("lime", "hl_gzip_decompress") private static function lime_gzip_decompress(data:Bytes, bytes:Bytes):Bytes + { + return null; + } + + @:hlNative("lime", "hl_haptic_vibrate") private static function lime_haptic_vibrate(period:Int, duration:Int):Void {} + + @:hlNative("lime", "hl_image_encode") private static function lime_image_encode(data:ImageBuffer, type:Int, quality:Int, bytes:Bytes):Bytes + { + return null; + } + + // @:cffi private static function lime_image_load (data:Dynamic, buffer:Dynamic):Dynamic; + @:hlNative("lime", "hl_image_load_bytes") private static function lime_image_load_bytes(data:Bytes, buffer:ImageBuffer):ImageBuffer + { + return null; + } + + @:hlNative("lime", "hl_image_load_file") private static function lime_image_load_file(path:String, buffer:ImageBuffer):ImageBuffer + { + return null; + } + + @:hlNative("lime", "hl_image_data_util_color_transform") private static function lime_image_data_util_color_transform(image:Image, rect:Rectangle, + colorMatrix:ArrayBufferView):Void {} + + // @:cffi private static function lime_image_data_util_copy_channel (image:Dynamic, sourceImage:Dynamic, sourceRect:Dynamic, destPoint:Dynamic, srcChannel:Int, destChannel:Int):Void; + @:hlNative("lime", "hl_image_data_util_copy_channel") private static function lime_image_data_util_copy_channel(image:Image, sourceImage:Image, + sourceRect:Rectangle, destPoint:Vector2, srcChannel:Int, destChannel:Int):Void {} + + // @:cffi private static function lime_image_data_util_copy_pixels (image:Dynamic, sourceImage:Dynamic, sourceRect:Dynamic, destPoint:Dynamic, alphaImage:Dynamic, alphaPoint:Dynamic, mergeAlpha:Bool):Void; + @:hlNative("lime", "hl_image_data_util_copy_pixels") private static function lime_image_data_util_copy_pixels(image:Image, sourceImage:Image, + sourceRect:Rectangle, destPoint:Vector2, alphaImage:Image, alphaPoint:Vector2, mergeAlpha:Bool):Void {} + + @:hlNative("lime", "hl_image_data_util_fill_rect") private static function lime_image_data_util_fill_rect(image:Image, rect:Rectangle, rg:Int, + ba:Int):Void {} + + @:hlNative("lime", "hl_image_data_util_flood_fill") private static function lime_image_data_util_flood_fill(image:Image, x:Int, y:Int, rg:Int, + ba:Int):Void {} + + @:hlNative("lime", "hl_image_data_util_get_pixels") private static function lime_image_data_util_get_pixels(image:Image, rect:Rectangle, format:Int, + bytes:Bytes):Void {} + + // @:cffi private static function lime_image_data_util_merge (image:Dynamic, sourceImage:Dynamic, sourceRect:Dynamic, destPoint:Dynamic, redMultiplier:Int, greenMultiplier:Int, blueMultiplier:Int, alphaMultiplier:Int):Void; + @:hlNative("lime", "hl_image_data_util_merge") private static function lime_image_data_util_merge(image:Image, sourceImage:Image, sourceRect:Rectangle, + destPoint:Vector2, redMultiplier:Int, greenMultiplier:Int, blueMultiplier:Int, alphaMultiplier:Int):Void {} + + @:hlNative("lime", "hl_image_data_util_multiply_alpha") private static function lime_image_data_util_multiply_alpha(image:Image):Void {} + + @:hlNative("lime", "hl_image_data_util_resize") private static function lime_image_data_util_resize(image:Image, buffer:ImageBuffer, width:Int, + height:Int):Void {} + + @:hlNative("lime", "hl_image_data_util_set_format") private static function lime_image_data_util_set_format(image:Image, format:Int):Void {} + + // @:cffi private static function lime_image_data_util_set_pixels (image:Dynamic, rect:Dynamic, bytes:Dynamic, offset:Int, format:Int, endian:Int):Void; + @:hlNative("lime", "hl_image_data_util_set_pixels") private static function lime_image_data_util_set_pixels(image:Image, rect:Rectangle, bytes:Bytes, + offset:Int, format:Int, endian:Int):Void {} + + // @:cffi private static function lime_image_data_util_threshold (image:Dynamic, sourceImage:Dynamic, sourceRect:Dynamic, destPoint:Dynamic, operation:Int, thresholdRG:Int, thresholdBA:Int, colorRG:Int, colorBA:Int, maskRG:Int, maskBA:Int, copySource:Bool):Int; + @:hlNative("lime", "hl_image_data_util_threshold") private static function lime_image_data_util_threshold(image:Image, sourceImage:Image, + sourceRect:Rectangle, destPoint:Vector2, operation:Int, thresholdRG:Int, thresholdBA:Int, colorRG:Int, colorBA:Int, maskRG:Int, maskBA:Int, + copySource:Bool):Int + { + return 0; + } + + @:hlNative("lime", "hl_image_data_util_unmultiply_alpha") private static function lime_image_data_util_unmultiply_alpha(image:Image):Void {} + + @:hlNative("lime", "hl_joystick_get_device_guid") private static function lime_joystick_get_device_guid(id:Int):hl.Bytes + { + return null; + } + + @:hlNative("lime", "hl_joystick_get_device_name") private static function lime_joystick_get_device_name(id:Int):hl.Bytes + { + return null; + } + + @:hlNative("lime", "hl_joystick_get_num_axes") private static function lime_joystick_get_num_axes(id:Int):Int + { + return 0; + } + + @:hlNative("lime", "hl_joystick_get_num_buttons") private static function lime_joystick_get_num_buttons(id:Int):Int + { + return 0; + } + + @:hlNative("lime", "hl_joystick_get_num_hats") private static function lime_joystick_get_num_hats(id:Int):Int + { + return 0; + } + + @:hlNative("lime", "hl_joystick_event_manager_register") private static function lime_joystick_event_manager_register(callback:Void->Void, + eventObject:JoystickEventInfo):Void {} + + @:hlNative("lime", "hl_jpeg_decode_bytes") private static function lime_jpeg_decode_bytes(data:Bytes, decodeData:Bool, buffer:ImageBuffer):ImageBuffer + { + return null; + } + + @:hlNative("lime", "hl_jpeg_decode_file") private static function lime_jpeg_decode_file(path:String, decodeData:Bool, buffer:ImageBuffer):ImageBuffer + { + return null; + } + + @:hlNative("lime", "hl_key_code_from_scan_code") private static function lime_key_code_from_scan_code(scanCode:Int):Int + { + return 0; + } + + @:hlNative("lime", "hl_key_code_to_scan_code") private static function lime_key_code_to_scan_code(keyCode:Int):Int + { + return 0; + } + + @:hlNative("lime", "hl_key_event_manager_register") private static function lime_key_event_manager_register(callback:Void->Void, + eventObject:KeyEventInfo):Void {} + + @:hlNative("lime", "hl_lzma_compress") private static function lime_lzma_compress(data:Bytes, bytes:Bytes):Bytes + { + return null; + } + + @:hlNative("lime", "hl_lzma_decompress") private static function lime_lzma_decompress(data:Bytes, bytes:Bytes):Bytes + { + return null; + } + + @:hlNative("lime", "hl_mouse_event_manager_register") private static function lime_mouse_event_manager_register(callback:Void->Void, + eventObject:MouseEventInfo):Void {} + + // @:cffi private static function lime_neko_execute (module:String):Void; + + @:hlNative("lime", "hl_orientation_event_manager_register") private static function lime_orientation_event_manager_register(callback:Void->Void, + eventObject:OrientationEventInfo):Void {} + + @:hlNative("lime", "hl_png_decode_bytes") private static function lime_png_decode_bytes(data:Bytes, decodeData:Bool, buffer:ImageBuffer):ImageBuffer + { + return null; + } + + @:hlNative("lime", "hl_png_decode_file") private static function lime_png_decode_file(path:String, decodeData:Bool, buffer:ImageBuffer):ImageBuffer + { + return null; + } + + @:hlNative("lime", "hl_render_event_manager_register") private static function lime_render_event_manager_register(callback:Void->Void, + eventObject:RenderEventInfo):Void {} + + @:hlNative("lime", "hl_sensor_event_manager_register") private static function lime_sensor_event_manager_register(callback:Void->Void, + eventObject:SensorEventInfo):Void {} + + @:hlNative("lime", "hl_system_get_allow_screen_timeout") private static function lime_system_get_allow_screen_timeout():Bool + { + return false; + } + + @:hlNative("lime", "hl_system_set_allow_screen_timeout") private static function lime_system_set_allow_screen_timeout(value:Bool):Bool + { + return false; + } + + @:hlNative("lime", "hl_system_get_device_model") private static function lime_system_get_device_model():hl.Bytes + { + return null; + } + + @:hlNative("lime", "hl_system_get_device_vendor") private static function lime_system_get_device_vendor():hl.Bytes + { + return null; + } + + @:hlNative("lime", "hl_system_get_directory") private static function lime_system_get_directory(type:Int, company:String, title:String):hl.Bytes + { + return null; + } + + @:hlNative("lime", "hl_system_get_display") private static function lime_system_get_display(index:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_system_get_ios_tablet") private static function lime_system_get_ios_tablet():Bool + { + return false; + } + + @:hlNative("lime", "hl_system_get_num_displays") private static function lime_system_get_num_displays():Int + { + return 0; + } + + @:hlNative("lime", "hl_system_get_device_orientation") private static function lime_system_get_device_orientation():Int + { + return 0; + } + + @:hlNative("lime", "hl_system_get_platform_label") private static function lime_system_get_platform_label():hl.Bytes + { + return null; + } + + @:hlNative("lime", "hl_system_get_platform_name") private static function lime_system_get_platform_name():hl.Bytes + { + return null; + } + + @:hlNative("lime", "hl_system_get_platform_version") private static function lime_system_get_platform_version():hl.Bytes + { + return null; + } + + @:hlNative("lime", "hl_system_get_timer") private static function lime_system_get_timer():Float + { + return 0; + } + + @:hlNative("lime", "hl_system_open_file") private static function lime_system_open_file(path:String):Void {} + + @:hlNative("lime", "hl_system_open_url") private static function lime_system_open_url(url:String, target:String):Void {} + + @:hlNative("lime", "hl_text_event_manager_register") private static function lime_text_event_manager_register(callback:Void->Void, + eventObject:TextEventInfo):Void {} + + @:hlNative("lime", "hl_touch_event_manager_register") private static function lime_touch_event_manager_register(callback:Void->Void, + eventObject:TouchEventInfo):Void {} + + @:hlNative("lime", "hl_window_alert") private static function lime_window_alert(handle:CFFIPointer, message:String, title:String):Void {} + + @:hlNative("lime", "hl_window_close") private static function lime_window_close(handle:CFFIPointer):Void {} + + @:hlNative("lime", "hl_window_context_flip") private static function lime_window_context_flip(handle:CFFIPointer):Void {} + + @:hlNative("lime", "hl_window_context_lock") private static function lime_window_context_lock(handle:CFFIPointer):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_window_context_make_current") private static function lime_window_context_make_current(handle:CFFIPointer):Void {} + + @:hlNative("lime", "hl_window_context_unlock") private static function lime_window_context_unlock(handle:CFFIPointer):Void {} + + @:hlNative("lime", "hl_window_create") private static function lime_window_create(application:CFFIPointer, width:Int, height:Int, flags:Int, + title:String):CFFIPointer + { + return null; + } + + @:hlNative("lime", "hl_window_focus") private static function lime_window_focus(handle:CFFIPointer):Void {} + + @:hlNative("lime", "hl_window_get_context") private static function lime_window_get_context(handle:CFFIPointer):Float + { + return 0; + } + + @:hlNative("lime", "hl_window_get_context_type") private static function lime_window_get_context_type(handle:CFFIPointer):hl.Bytes + { + return null; + } + + @:hlNative("lime", "hl_window_create_vulkan_surface") private static function lime_window_create_vulkan_surface(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_window_get_display") private static function lime_window_get_display(handle:CFFIPointer):Int + { + return 0; + } + + @:hlNative("lime", "hl_window_get_display_mode") private static function lime_window_get_display_mode(handle:CFFIPointer, result:DisplayMode):Void {} + + @:hlNative("lime", "hl_window_get_height") private static function lime_window_get_height(handle:CFFIPointer):Int + { + return 0; + } + + @:hlNative("lime", "hl_window_get_id") private static function lime_window_get_id(handle:CFFIPointer):Int + { + return 0; + } + + @:hlNative("lime", "hl_window_get_mouse_lock") private static function lime_window_get_mouse_lock(handle:CFFIPointer):Bool + { + return false; + } + + @:hlNative("lime", "hl_window_get_scale") private static function lime_window_get_scale(handle:CFFIPointer):Float + { + return 0; + } + + @:hlNative("lime", "hl_window_get_text_input_enabled") private static function lime_window_get_text_input_enabled(handle:CFFIPointer):Bool + { + return false; + } + + @:hlNative("lime", "hl_window_get_vulkan_drawable_size") private static function lime_window_get_vulkan_drawable_size(handle:CFFIPointer):Dynamic + { + return null; + } + + @:hlNative("lime", + "hl_window_get_vulkan_instance_extensions") private static function lime_window_get_vulkan_instance_extensions(handle:CFFIPointer):hl.NativeArray + { + return null; + } + + @:hlNative("lime", "hl_window_get_vulkan_instance_proc_addr") private static function lime_window_get_vulkan_instance_proc_addr(handle:CFFIPointer):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_create_instance") private static function lime_vk_create_instance(handle:CFFIPointer, applicationName:String):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_instance") private static function lime_vk_destroy_instance(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int):Void {} + + @:hlNative("lime", "hl_vk_destroy_surface") private static function lime_vk_destroy_surface(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + surfaceHigh:Int, surfaceLow:Int):Void {} + + @:hlNative("lime", "hl_vk_get_physical_devices") private static function lime_vk_get_physical_devices(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, surfaceHigh:Int, surfaceLow:Int):hl.NativeArray + { + return null; + } + + #if lime_vulkan + @:hlNative("lime", "hl_vk_create_device") private static function lime_vk_create_device(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + physicalDeviceHigh:Int, physicalDeviceLow:Int, queueFamilyIndex:Int, extensions:hl.NativeArray):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_device") private static function lime_vk_destroy_device(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int):Void {} + + @:hlNative("lime", "hl_vk_device_wait_idle") private static function lime_vk_device_wait_idle(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_queue_wait_idle") private static function lime_vk_queue_wait_idle(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_create_command_pool") private static function lime_vk_create_command_pool(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, queueFamilyIndex:Int, flags:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_command_pool") private static function lime_vk_destroy_command_pool(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int):Void {} + + @:hlNative("lime", "hl_vk_reset_command_pool") private static function lime_vk_reset_command_pool(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int, flags:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_allocate_command_buffer") private static function lime_vk_allocate_command_buffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int, level:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_free_command_buffer") private static function lime_vk_free_command_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandPoolHigh:Int, commandPoolLow:Int, commandBufferHigh:Int, commandBufferLow:Int):Void {} + + @:hlNative("lime", "hl_vk_begin_command_buffer") private static function lime_vk_begin_command_buffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, flags:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_end_command_buffer") private static function lime_vk_end_command_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_reset_command_buffer") private static function lime_vk_reset_command_buffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, flags:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_create_semaphore") private static function lime_vk_create_semaphore(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_semaphore") private static function lime_vk_destroy_semaphore(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, semaphoreHigh:Int, semaphoreLow:Int):Void {} + + @:hlNative("lime", "hl_vk_create_fence") private static function lime_vk_create_fence(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, flags:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_fence") private static function lime_vk_destroy_fence(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, fenceHigh:Int, fenceLow:Int):Void {} + + @:hlNative("lime", "hl_vk_wait_for_fence") private static function lime_vk_wait_for_fence(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, fenceHigh:Int, fenceLow:Int, timeoutHigh:Int, timeoutLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_reset_fence") private static function lime_vk_reset_fence(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, fenceHigh:Int, fenceLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_queue_submit") private static function lime_vk_queue_submit(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int, commandBufferHigh:Int, commandBufferLow:Int, fenceHigh:Int, fenceLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_allocate_memory") private static function lime_vk_allocate_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + physicalDeviceHigh:Int, physicalDeviceLow:Int, deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, memoryTypeBits:Int, properties:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_free_memory") private static function lime_vk_free_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, memoryHigh:Int, memoryLow:Int):Void {} + + @:hlNative("lime", "hl_vk_upload_memory") private static function lime_vk_upload_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Bytes, byteOffset:Int, byteLength:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_download_memory") private static function lime_vk_download_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Bytes, byteOffset:Int, byteLength:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_map_memory") private static function lime_vk_map_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int, flags:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_unmap_memory") private static function lime_vk_unmap_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int):Void {} + + @:hlNative("lime", "hl_vk_write_mapped_memory") private static function lime_vk_write_mapped_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, bytes:Bytes, byteOffset:Int, byteLength:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_flush_mapped_memory") private static function lime_vk_flush_mapped_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_invalidate_mapped_memory") private static function lime_vk_invalidate_mapped_memory(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int, sizeHigh:Int, sizeLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_create_buffer") private static function lime_vk_create_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, sizeHigh:Int, sizeLow:Int, usage:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_buffer") private static function lime_vk_destroy_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, bufferHigh:Int, bufferLow:Int):Void {} + + @:hlNative("lime", "hl_vk_get_buffer_memory_requirements") private static function lime_vk_get_buffer_memory_requirements(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, bufferHigh:Int, bufferLow:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_bind_buffer_memory") private static function lime_vk_bind_buffer_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, bufferHigh:Int, bufferLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_create_image") private static function lime_vk_create_image(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, width:Int, height:Int, depth:Int, mipLevels:Int, arrayLayers:Int, format:Int, imageType:Int, tiling:Int, usage:Int, + samples:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_image") private static function lime_vk_destroy_image(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int):Void {} + + @:hlNative("lime", "hl_vk_get_image_memory_requirements") private static function lime_vk_get_image_memory_requirements(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_bind_image_memory") private static function lime_vk_bind_image_memory(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int, memoryHigh:Int, memoryLow:Int, offsetHigh:Int, offsetLow:Int):Bool + { + return false; + } + + @:hlNative("lime", "hl_vk_create_swapchain") private static function lime_vk_create_swapchain(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + physicalDeviceHigh:Int, physicalDeviceLow:Int, deviceHigh:Int, deviceLow:Int, surfaceHigh:Int, surfaceLow:Int, queueFamilyIndex:Int, width:Int, + height:Int, presentMode:Int, oldSwapchainHigh:Int, oldSwapchainLow:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_destroy_swapchain") private static function lime_vk_destroy_swapchain(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, swapchainHigh:Int, swapchainLow:Int):Void {} + + @:hlNative("lime", "hl_vk_get_swapchain_images") private static function lime_vk_get_swapchain_images(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, swapchainHigh:Int, swapchainLow:Int):hl.NativeArray + { + return null; + } + + @:hlNative("lime", "hl_vk_acquire_next_image") private static function lime_vk_acquire_next_image(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, swapchainHigh:Int, swapchainLow:Int, timeoutHigh:Int, timeoutLow:Int, semaphoreHigh:Int, semaphoreLow:Int, + fenceHigh:Int, fenceLow:Int):Dynamic + { + return null; + } + + @:hlNative("lime", "hl_vk_queue_present") private static function lime_vk_queue_present(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int, swapchainHigh:Int, swapchainLow:Int, imageIndex:Int, waitSemaphoreHigh:Int, + waitSemaphoreLow:Int):Int { - return null; + return -3; } - @:hlNative("lime", "hl_gamepad_get_device_name") private static function lime_gamepad_get_device_name(id:Int):hl.Bytes + @:hlNative("lime", "hl_vk_create_image_view") private static function lime_vk_create_image_view(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int, format:Int, aspectMask:Int, viewType:Int):Dynamic { return null; } - @:hlNative("lime", "hl_gamepad_rumble") private static function lime_gamepad_rumble(id:Int, lowFrequencyRumble:Float, highFrequencyRumble:Float, duration:Int):Void {} - - @:hlNative("lime", "hl_gamepad_event_manager_register") private static function lime_gamepad_event_manager_register(callback:Void->Void, - eventObject:GamepadEventInfo):Void {} + @:hlNative("lime", "hl_vk_destroy_image_view") private static function lime_vk_destroy_image_view(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, imageViewHigh:Int, imageViewLow:Int):Void {} - @:hlNative("lime", "hl_gzip_compress") private static function lime_gzip_compress(data:Bytes, bytes:Bytes):Bytes + @:hlNative("lime", "hl_vk_create_image_view_ex") private static function lime_vk_create_image_view_ex(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, imageHigh:Int, imageLow:Int, format:Int, aspectMask:Int, viewType:Int, baseMipLevel:Int, + levelCount:Int, baseArrayLayer:Int, layerCount:Int):Dynamic { return null; } - @:hlNative("lime", "hl_gzip_decompress") private static function lime_gzip_decompress(data:Bytes, bytes:Bytes):Bytes + @:hlNative("lime", "hl_vk_create_render_pass") private static function lime_vk_create_render_pass(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, state:hl.NativeArray):Dynamic { return null; } - @:hlNative("lime", "hl_haptic_vibrate") private static function lime_haptic_vibrate(period:Int, duration:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_render_pass") private static function lime_vk_destroy_render_pass(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, renderPassHigh:Int, renderPassLow:Int):Void {} - @:hlNative("lime", "hl_image_encode") private static function lime_image_encode(data:ImageBuffer, type:Int, quality:Int, bytes:Bytes):Bytes + @:hlNative("lime", "hl_vk_create_framebuffer") private static function lime_vk_create_framebuffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, renderPassHigh:Int, renderPassLow:Int, attachments:hl.NativeArray, width:Int, height:Int, layers:Int):Dynamic { return null; } - // @:cffi private static function lime_image_load (data:Dynamic, buffer:Dynamic):Dynamic; - @:hlNative("lime", "hl_image_load_bytes") private static function lime_image_load_bytes(data:Bytes, buffer:ImageBuffer):ImageBuffer + @:hlNative("lime", "hl_vk_destroy_framebuffer") private static function lime_vk_destroy_framebuffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, framebufferHigh:Int, framebufferLow:Int):Void {} + + @:hlNative("lime", "hl_vk_create_shader_module") private static function lime_vk_create_shader_module(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, bytes:Bytes, byteOffset:Int, byteLength:Int):Dynamic { return null; } - @:hlNative("lime", "hl_image_load_file") private static function lime_image_load_file(path:String, buffer:ImageBuffer):ImageBuffer + @:hlNative("lime", "hl_vk_destroy_shader_module") private static function lime_vk_destroy_shader_module(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, shaderModuleHigh:Int, shaderModuleLow:Int):Void {} + + @:hlNative("lime", "hl_vk_create_sampler") private static function lime_vk_create_sampler(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, filter:Int, addressMode:Int, mipmapMode:Int, anisotropyEnable:Bool, maxAnisotropy:Float, compareOp:Int, + minLod:Float, maxLod:Float):Dynamic { return null; } - @:hlNative("lime", "hl_image_data_util_color_transform") private static function lime_image_data_util_color_transform(image:Image, rect:Rectangle, - colorMatrix:ArrayBufferView):Void {} - - // @:cffi private static function lime_image_data_util_copy_channel (image:Dynamic, sourceImage:Dynamic, sourceRect:Dynamic, destPoint:Dynamic, srcChannel:Int, destChannel:Int):Void; - @:hlNative("lime", "hl_image_data_util_copy_channel") private static function lime_image_data_util_copy_channel(image:Image, sourceImage:Image, - sourceRect:Rectangle, destPoint:Vector2, srcChannel:Int, destChannel:Int):Void {} - - // @:cffi private static function lime_image_data_util_copy_pixels (image:Dynamic, sourceImage:Dynamic, sourceRect:Dynamic, destPoint:Dynamic, alphaImage:Dynamic, alphaPoint:Dynamic, mergeAlpha:Bool):Void; - @:hlNative("lime", "hl_image_data_util_copy_pixels") private static function lime_image_data_util_copy_pixels(image:Image, sourceImage:Image, - sourceRect:Rectangle, destPoint:Vector2, alphaImage:Image, alphaPoint:Vector2, mergeAlpha:Bool):Void {} - - @:hlNative("lime", "hl_image_data_util_fill_rect") private static function lime_image_data_util_fill_rect(image:Image, rect:Rectangle, rg:Int, - ba:Int):Void {} - - @:hlNative("lime", "hl_image_data_util_flood_fill") private static function lime_image_data_util_flood_fill(image:Image, x:Int, y:Int, rg:Int, - ba:Int):Void {} - - @:hlNative("lime", "hl_image_data_util_get_pixels") private static function lime_image_data_util_get_pixels(image:Image, rect:Rectangle, format:Int, - bytes:Bytes):Void {} - - // @:cffi private static function lime_image_data_util_merge (image:Dynamic, sourceImage:Dynamic, sourceRect:Dynamic, destPoint:Dynamic, redMultiplier:Int, greenMultiplier:Int, blueMultiplier:Int, alphaMultiplier:Int):Void; - @:hlNative("lime", "hl_image_data_util_merge") private static function lime_image_data_util_merge(image:Image, sourceImage:Image, sourceRect:Rectangle, - destPoint:Vector2, redMultiplier:Int, greenMultiplier:Int, blueMultiplier:Int, alphaMultiplier:Int):Void {} - - @:hlNative("lime", "hl_image_data_util_multiply_alpha") private static function lime_image_data_util_multiply_alpha(image:Image):Void {} + @:hlNative("lime", "hl_vk_destroy_sampler") private static function lime_vk_destroy_sampler(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, samplerHigh:Int, samplerLow:Int):Void {} - @:hlNative("lime", "hl_image_data_util_resize") private static function lime_image_data_util_resize(image:Image, buffer:ImageBuffer, width:Int, - height:Int):Void {} - - @:hlNative("lime", "hl_image_data_util_set_format") private static function lime_image_data_util_set_format(image:Image, format:Int):Void {} + @:hlNative("lime", "hl_vk_create_descriptor_set_layout") private static function lime_vk_create_descriptor_set_layout(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, bindings:hl.NativeArray):Dynamic + { + return null; + } - // @:cffi private static function lime_image_data_util_set_pixels (image:Dynamic, rect:Dynamic, bytes:Dynamic, offset:Int, format:Int, endian:Int):Void; - @:hlNative("lime", "hl_image_data_util_set_pixels") private static function lime_image_data_util_set_pixels(image:Image, rect:Rectangle, bytes:Bytes, - offset:Int, format:Int, endian:Int):Void {} + @:hlNative("lime", "hl_vk_destroy_descriptor_set_layout") private static function lime_vk_destroy_descriptor_set_layout(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, layoutHigh:Int, layoutLow:Int):Void {} - // @:cffi private static function lime_image_data_util_threshold (image:Dynamic, sourceImage:Dynamic, sourceRect:Dynamic, destPoint:Dynamic, operation:Int, thresholdRG:Int, thresholdBA:Int, colorRG:Int, colorBA:Int, maskRG:Int, maskBA:Int, copySource:Bool):Int; - @:hlNative("lime", "hl_image_data_util_threshold") private static function lime_image_data_util_threshold(image:Image, sourceImage:Image, - sourceRect:Rectangle, destPoint:Vector2, operation:Int, thresholdRG:Int, thresholdBA:Int, colorRG:Int, colorBA:Int, maskRG:Int, maskBA:Int, - copySource:Bool):Int + @:hlNative("lime", "hl_vk_create_descriptor_pool") private static function lime_vk_create_descriptor_pool(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolSizes:hl.NativeArray):Dynamic { - return 0; + return null; } - @:hlNative("lime", "hl_image_data_util_unmultiply_alpha") private static function lime_image_data_util_unmultiply_alpha(image:Image):Void {} + @:hlNative("lime", "hl_vk_destroy_descriptor_pool") private static function lime_vk_destroy_descriptor_pool(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int):Void {} - @:hlNative("lime", "hl_joystick_get_device_guid") private static function lime_joystick_get_device_guid(id:Int):hl.Bytes + @:hlNative("lime", "hl_vk_reset_descriptor_pool") private static function lime_vk_reset_descriptor_pool(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int, flags:Int):Bool { - return null; + return false; } - @:hlNative("lime", "hl_joystick_get_device_name") private static function lime_joystick_get_device_name(id:Int):hl.Bytes + @:hlNative("lime", "hl_vk_allocate_descriptor_set") private static function lime_vk_allocate_descriptor_set(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, poolHigh:Int, poolLow:Int, layoutHigh:Int, layoutLow:Int):Dynamic { return null; } - @:hlNative("lime", "hl_joystick_get_num_axes") private static function lime_joystick_get_num_axes(id:Int):Int + @:hlNative("lime", "hl_vk_update_descriptor_set_image") private static function lime_vk_update_descriptor_set_image(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, imageViewHigh:Int, imageViewLow:Int, + samplerHigh:Int, samplerLow:Int, imageLayout:Int):Bool { - return 0; + return false; } - @:hlNative("lime", "hl_joystick_get_num_buttons") private static function lime_joystick_get_num_buttons(id:Int):Int + @:hlNative("lime", "hl_vk_update_descriptor_set_buffer") private static function lime_vk_update_descriptor_set_buffer(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, setHigh:Int, setLow:Int, binding:Int, descriptorType:Int, bufferHigh:Int, + bufferLow:Int, offset:Int, range:Int):Bool { - return 0; + return false; } - @:hlNative("lime", "hl_joystick_get_num_hats") private static function lime_joystick_get_num_hats(id:Int):Int + @:hlNative("lime", "hl_vk_update_descriptor_sets") private static function lime_vk_update_descriptor_sets(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, writes:hl.NativeArray):Bool { - return 0; + return false; } - @:hlNative("lime", "hl_joystick_event_manager_register") private static function lime_joystick_event_manager_register(callback:Void->Void, - eventObject:JoystickEventInfo):Void {} - - @:hlNative("lime", "hl_jpeg_decode_bytes") private static function lime_jpeg_decode_bytes(data:Bytes, decodeData:Bool, buffer:ImageBuffer):ImageBuffer + @:hlNative("lime", "hl_vk_create_pipeline_layout") private static function lime_vk_create_pipeline_layout(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, setLayouts:hl.NativeArray, pushConstantStages:Int, pushConstantSize:Int):Dynamic { return null; } - @:hlNative("lime", "hl_jpeg_decode_file") private static function lime_jpeg_decode_file(path:String, decodeData:Bool, buffer:ImageBuffer):ImageBuffer + @:hlNative("lime", "hl_vk_destroy_pipeline_layout") private static function lime_vk_destroy_pipeline_layout(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, layoutHigh:Int, layoutLow:Int):Void {} + + @:hlNative("lime", "hl_vk_create_pipeline_cache") private static function lime_vk_create_pipeline_cache(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, bytes:Bytes, byteOffset:Int, byteLength:Int):Dynamic { return null; } - @:hlNative("lime", "hl_key_code_from_scan_code") private static function lime_key_code_from_scan_code(scanCode:Int):Int + @:hlNative("lime", "hl_vk_destroy_pipeline_cache") private static function lime_vk_destroy_pipeline_cache(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, cacheHigh:Int, cacheLow:Int):Void {} + + @:hlNative("lime", "hl_vk_get_pipeline_cache_data") private static function lime_vk_get_pipeline_cache_data(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, cacheHigh:Int, cacheLow:Int, bytes:Bytes):Bool { - return 0; + return false; } - @:hlNative("lime", "hl_key_code_to_scan_code") private static function lime_key_code_to_scan_code(keyCode:Int):Int + @:hlNative("lime", "hl_vk_create_graphics_pipeline") private static function lime_vk_create_graphics_pipeline(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, renderPassHigh:Int, renderPassLow:Int, layoutHigh:Int, layoutLow:Int, vertexShaderHigh:Int, + vertexShaderLow:Int, fragmentShaderHigh:Int, fragmentShaderLow:Int, state:hl.NativeArray):Dynamic { - return 0; + return null; } - @:hlNative("lime", "hl_key_event_manager_register") private static function lime_key_event_manager_register(callback:Void->Void, - eventObject:KeyEventInfo):Void {} + @:hlNative("lime", "hl_vk_destroy_pipeline") private static function lime_vk_destroy_pipeline(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, pipelineHigh:Int, pipelineLow:Int):Void {} - @:hlNative("lime", "hl_lzma_compress") private static function lime_lzma_compress(data:Bytes, bytes:Bytes):Bytes + @:hlNative("lime", "hl_vk_queue_submit_synced") private static function lime_vk_queue_submit_synced(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, queueHigh:Int, queueLow:Int, commandBufferHigh:Int, commandBufferLow:Int, state:hl.NativeArray):Bool { - return null; + return false; } - @:hlNative("lime", "hl_lzma_decompress") private static function lime_lzma_decompress(data:Bytes, bytes:Bytes):Bytes + @:hlNative("lime", "hl_vk_cmd_begin_render_pass") private static function lime_vk_cmd_begin_render_pass(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, renderPassHigh:Int, renderPassLow:Int, + framebufferHigh:Int, framebufferLow:Int, state:hl.NativeArray, clear:hl.NativeArray):Bool { - return null; + return false; } - @:hlNative("lime", "hl_mouse_event_manager_register") private static function lime_mouse_event_manager_register(callback:Void->Void, - eventObject:MouseEventInfo):Void {} - - // @:cffi private static function lime_neko_execute (module:String):Void; - - @:hlNative("lime", "hl_orientation_event_manager_register") private static function lime_orientation_event_manager_register(callback:Void->Void, - eventObject:OrientationEventInfo):Void {} - - @:hlNative("lime", "hl_png_decode_bytes") private static function lime_png_decode_bytes(data:Bytes, decodeData:Bool, buffer:ImageBuffer):ImageBuffer + @:hlNative("lime", "hl_vk_cmd_end_render_pass") private static function lime_vk_cmd_end_render_pass(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int):Bool { - return null; + return false; } - @:hlNative("lime", "hl_png_decode_file") private static function lime_png_decode_file(path:String, decodeData:Bool, buffer:ImageBuffer):ImageBuffer + @:hlNative("lime", "hl_vk_cmd_bind_pipeline") private static function lime_vk_cmd_bind_pipeline(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, pipelineHigh:Int, pipelineLow:Int, bindPoint:Int):Bool { - return null; + return false; } - @:hlNative("lime", "hl_render_event_manager_register") private static function lime_render_event_manager_register(callback:Void->Void, - eventObject:RenderEventInfo):Void {} - - @:hlNative("lime", "hl_sensor_event_manager_register") private static function lime_sensor_event_manager_register(callback:Void->Void, - eventObject:SensorEventInfo):Void {} - - @:hlNative("lime", "hl_system_get_allow_screen_timeout") private static function lime_system_get_allow_screen_timeout():Bool + @:hlNative("lime", "hl_vk_cmd_bind_descriptor_set") private static function lime_vk_cmd_bind_descriptor_set(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, + setLow:Int, bindPoint:Int, firstSet:Int):Bool { return false; } - @:hlNative("lime", "hl_system_set_allow_screen_timeout") private static function lime_system_set_allow_screen_timeout(value:Bool):Bool + @:hlNative("lime", "hl_vk_cmd_bind_descriptor_set_ex") private static function lime_vk_cmd_bind_descriptor_set_ex(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, setHigh:Int, + setLow:Int, state:hl.NativeArray):Bool { return false; } - @:hlNative("lime", "hl_system_get_device_model") private static function lime_system_get_device_model():hl.Bytes + @:hlNative("lime", + "hl_vk_cmd_bind_descriptor_set_dynamic_offset") private static function lime_vk_cmd_bind_descriptor_set_dynamic_offset(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, + layoutLow:Int, setHigh:Int, setLow:Int, dynamicOffset:Int, firstSet:Int, bindPoint:Int):Bool { - return null; + return false; } - @:hlNative("lime", "hl_system_get_device_vendor") private static function lime_system_get_device_vendor():hl.Bytes + @:hlNative("lime", "hl_vk_cmd_bind_vertex_buffer") private static function lime_vk_cmd_bind_vertex_buffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, binding:Int, + offsetHigh:Int, offsetLow:Int):Bool { - return null; + return false; } - @:hlNative("lime", "hl_system_get_directory") private static function lime_system_get_directory(type:Int, company:String, title:String):hl.Bytes + @:hlNative("lime", "hl_vk_cmd_bind_index_buffer") private static function lime_vk_cmd_bind_index_buffer(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, offsetHigh:Int, + offsetLow:Int, indexType:Int):Bool { - return null; + return false; } - @:hlNative("lime", "hl_system_get_display") private static function lime_system_get_display(index:Int):Dynamic + @:hlNative("lime", "hl_vk_cmd_set_viewport") private static function lime_vk_cmd_set_viewport(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, x:Float, y:Float, width:Float, height:Float, minDepth:Float, + maxDepth:Float):Bool { - return null; + return false; } - @:hlNative("lime", "hl_system_get_ios_tablet") private static function lime_system_get_ios_tablet():Bool + @:hlNative("lime", "hl_vk_cmd_set_scissor") private static function lime_vk_cmd_set_scissor(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, x:Int, y:Int, width:Int, height:Int):Bool { return false; } - @:hlNative("lime", "hl_system_get_num_displays") private static function lime_system_get_num_displays():Int + @:hlNative("lime", "hl_vk_cmd_draw") private static function lime_vk_cmd_draw(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, deviceHigh:Int, + deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, vertexCount:Int, instanceCount:Int, firstVertex:Int, firstInstance:Int):Bool { - return 0; + return false; } - @:hlNative("lime", "hl_system_get_device_orientation") private static function lime_system_get_device_orientation():Int + @:hlNative("lime", "hl_vk_cmd_draw_indexed") private static function lime_vk_cmd_draw_indexed(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, indexCount:Int, instanceCount:Int, firstIndex:Int, vertexOffset:Int, + firstInstance:Int):Bool { - return 0; + return false; } - @:hlNative("lime", "hl_system_get_platform_label") private static function lime_system_get_platform_label():hl.Bytes + @:hlNative("lime", "hl_vk_cmd_draw_indirect") private static function lime_vk_cmd_draw_indirect(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, offsetHigh:Int, offsetLow:Int, + drawCount:Int, stride:Int):Bool { - return null; + return false; } - @:hlNative("lime", "hl_system_get_platform_name") private static function lime_system_get_platform_name():hl.Bytes + @:hlNative("lime", "hl_vk_cmd_draw_indexed_indirect") private static function lime_vk_cmd_draw_indexed_indirect(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, offsetHigh:Int, + offsetLow:Int, drawCount:Int, stride:Int):Bool { - return null; + return false; } - @:hlNative("lime", "hl_system_get_platform_version") private static function lime_system_get_platform_version():hl.Bytes + @:hlNative("lime", "hl_vk_cmd_copy_buffer") private static function lime_vk_cmd_copy_buffer(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, + destinationLow:Int, state:hl.NativeArray):Bool { - return null; + return false; } - @:hlNative("lime", "hl_system_get_timer") private static function lime_system_get_timer():Float + @:hlNative("lime", "hl_vk_cmd_copy_buffer_to_image_region") private static function lime_vk_cmd_copy_buffer_to_image_region(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, bufferHigh:Int, bufferLow:Int, + imageHigh:Int, imageLow:Int, state:hl.NativeArray):Bool { - return 0; + return false; } - @:hlNative("lime", "hl_system_open_file") private static function lime_system_open_file(path:String):Void {} - - @:hlNative("lime", "hl_system_open_url") private static function lime_system_open_url(url:String, target:String):Void {} - - @:hlNative("lime", "hl_text_event_manager_register") private static function lime_text_event_manager_register(callback:Void->Void, - eventObject:TextEventInfo):Void {} - - @:hlNative("lime", "hl_touch_event_manager_register") private static function lime_touch_event_manager_register(callback:Void->Void, - eventObject:TouchEventInfo):Void {} - - @:hlNative("lime", "hl_window_alert") private static function lime_window_alert(handle:CFFIPointer, message:String, title:String):Void {} - - @:hlNative("lime", "hl_window_close") private static function lime_window_close(handle:CFFIPointer):Void {} - - @:hlNative("lime", "hl_window_context_flip") private static function lime_window_context_flip(handle:CFFIPointer):Void {} + @:hlNative("lime", "hl_vk_cmd_copy_image_to_buffer_region") private static function lime_vk_cmd_copy_image_to_buffer_region(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, + bufferHigh:Int, bufferLow:Int, state:hl.NativeArray):Bool + { + return false; + } - @:hlNative("lime", "hl_window_context_lock") private static function lime_window_context_lock(handle:CFFIPointer):Dynamic + @:hlNative("lime", "hl_vk_cmd_pipeline_barrier_image") private static function lime_vk_cmd_pipeline_barrier_image(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, + state:hl.NativeArray):Bool { - return null; + return false; } - @:hlNative("lime", "hl_window_context_make_current") private static function lime_window_context_make_current(handle:CFFIPointer):Void {} + @:hlNative("lime", "hl_vk_cmd_clear_color_image") private static function lime_vk_cmd_clear_color_image(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, layout:Int, + aspectMask:Int, clear:hl.NativeArray):Bool + { + return false; + } - @:hlNative("lime", "hl_window_context_unlock") private static function lime_window_context_unlock(handle:CFFIPointer):Void {} + @:hlNative("lime", "hl_vk_cmd_clear_depth_stencil_image") private static function lime_vk_cmd_clear_depth_stencil_image(handle:CFFIPointer, + instanceHigh:Int, instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, imageHigh:Int, imageLow:Int, + state:hl.NativeArray, clear:hl.NativeArray):Bool + { + return false; + } - @:hlNative("lime", "hl_window_create") private static function lime_window_create(application:CFFIPointer, width:Int, height:Int, flags:Int, - title:String):CFFIPointer + @:hlNative("lime", "hl_vk_cmd_clear_attachments") private static function lime_vk_cmd_clear_attachments(handle:CFFIPointer, instanceHigh:Int, + instanceLow:Int, deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, state:hl.NativeArray, + clear:hl.NativeArray):Bool { - return null; + return false; } - @:hlNative("lime", "hl_window_focus") private static function lime_window_focus(handle:CFFIPointer):Void {} + @:hlNative("lime", "hl_vk_cmd_blit_image") private static function lime_vk_cmd_blit_image(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, sourceHigh:Int, sourceLow:Int, destinationHigh:Int, + destinationLow:Int, state:hl.NativeArray):Bool + { + return false; + } - @:hlNative("lime", "hl_window_get_context") private static function lime_window_get_context(handle:CFFIPointer):Float + @:hlNative("lime", "hl_vk_cmd_push_constants") private static function lime_vk_cmd_push_constants(handle:CFFIPointer, instanceHigh:Int, instanceLow:Int, + deviceHigh:Int, deviceLow:Int, commandBufferHigh:Int, commandBufferLow:Int, layoutHigh:Int, layoutLow:Int, state:hl.NativeArray, + bytes:Bytes):Bool { - return 0; + return false; } + #end - @:hlNative("lime", "hl_window_get_context_type") private static function lime_window_get_context_type(handle:CFFIPointer):hl.Bytes + @:hlNative("lime", "hl_vk_get_last_error") private static function lime_vk_get_last_error():hl.Bytes { return null; } - @:hlNative("lime", "hl_window_get_display") private static function lime_window_get_display(handle:CFFIPointer):Int + @:hlNative("lime", "hl_vulkan_renderer_create") private static function lime_vulkan_renderer_create(handle:CFFIPointer, applicationName:String):CFFIPointer { - return 0; + return null; } - @:hlNative("lime", "hl_window_get_display_mode") private static function lime_window_get_display_mode(handle:CFFIPointer, result:DisplayMode):Void {} + @:hlNative("lime", "hl_vulkan_renderer_destroy") private static function lime_vulkan_renderer_destroy(handle:CFFIPointer):Void {} - @:hlNative("lime", "hl_window_get_height") private static function lime_window_get_height(handle:CFFIPointer):Int + @:hlNative("lime", "hl_vulkan_renderer_get_info") private static function lime_vulkan_renderer_get_info(handle:CFFIPointer):hl.Bytes { - return 0; + return null; } - @:hlNative("lime", "hl_window_get_id") private static function lime_window_get_id(handle:CFFIPointer):Int + @:hlNative("lime", "hl_vulkan_renderer_get_last_error") private static function lime_vulkan_renderer_get_last_error():hl.Bytes { - return 0; + return null; } - @:hlNative("lime", "hl_window_get_mouse_lock") private static function lime_window_get_mouse_lock(handle:CFFIPointer):Bool + @:hlNative("lime", "hl_vulkan_renderer_set_overlay") private static function lime_vulkan_renderer_set_overlay(handle:CFFIPointer, bytes:Bytes, width:Int, + height:Int, x:Int, y:Int):Bool { return false; } - @:hlNative("lime", "hl_window_get_scale") private static function lime_window_get_scale(handle:CFFIPointer):Float + @:hlNative("lime", "hl_vulkan_renderer_clear_overlay") private static function lime_vulkan_renderer_clear_overlay(handle:CFFIPointer):Bool { - return 0; + return false; } - @:hlNative("lime", "hl_window_get_text_input_enabled") private static function lime_window_get_text_input_enabled(handle:CFFIPointer):Bool + @:hlNative("lime", "hl_vulkan_renderer_render") private static function lime_vulkan_renderer_render(handle:CFFIPointer, red:Float, green:Float, + blue:Float, alpha:Float):Bool + { + return false; + } + + @:hlNative("lime", "hl_vulkan_renderer_resize") private static function lime_vulkan_renderer_resize(handle:CFFIPointer):Bool { return false; } @@ -1526,11 +2766,9 @@ class NativeCFFI return false; } - @:hlNative("lime", "hl_window_set_text_input_enabled") private static function lime_window_set_text_input_enabled(handle:CFFIPointer, - enabled:Bool):Void {} + @:hlNative("lime", "hl_window_set_text_input_enabled") private static function lime_window_set_text_input_enabled(handle:CFFIPointer, enabled:Bool):Void {} - @:hlNative("lime", "hl_window_set_text_input_rect") private static function lime_window_set_text_input_rect(handle:CFFIPointer, - rect:Rectangle):Void {} + @:hlNative("lime", "hl_window_set_text_input_rect") private static function lime_window_set_text_input_rect(handle:CFFIPointer, rect:Rectangle):Void {} @:hlNative("lime", "hl_window_set_title") private static function lime_window_set_title(handle:CFFIPointer, title:String):String { @@ -1549,7 +2787,10 @@ class NativeCFFI @:hlNative("lime", "hl_window_warp_mouse") private static function lime_window_warp_mouse(handle:CFFIPointer, x:Int, y:Int):Void {} - @:hlNative("lime", "hl_window_get_opacity") private static function lime_window_get_opacity(handle:CFFIPointer):Float { return 0.0; } + @:hlNative("lime", "hl_window_get_opacity") private static function lime_window_get_opacity(handle:CFFIPointer):Float + { + return 0.0; + } @:hlNative("lime", "hl_window_set_opacity") private static function lime_window_set_opacity(handle:CFFIPointer, value:Float):Void {} @@ -1743,6 +2984,8 @@ class NativeCFFI @:cffi private static function lime_al_is_extension_present(extname:String):Bool; + @:cffi private static function lime_alc_is_extension_present(device:CFFIPointer, extname:String):Bool; + @:cffi private static function lime_al_is_source(source:CFFIPointer):Bool; @:cffi private static function lime_al_listener3f(param:Int, value1:Float32, value2:Float32, value3:Float32):Void; @@ -1819,6 +3062,16 @@ class NativeCFFI @:cffi private static function lime_alc_suspend_context(context:CFFIPointer):Void; + @:cffi private static function lime_alc_capture_open_device(devicename:String, frequency:Int, format:Int, buffersize:Int):CFFIPointer; + + @:cffi private static function lime_alc_capture_close_device(device:CFFIPointer):Bool; + + @:cffi private static function lime_alc_capture_start(device:CFFIPointer):Void; + + @:cffi private static function lime_alc_capture_stop(device:CFFIPointer):Void; + + @:cffi private static function lime_alc_capture_samples(device:CFFIPointer, buffer:Dynamic, samples:Int):Void; + @:cffi private static function lime_al_gen_filter():CFFIPointer; @:cffi private static function lime_al_filteri(filter:CFFIPointer, param:Int, value:Dynamic):Void; @@ -1889,10 +3142,8 @@ class NativeCFFI private static var lime_al_get_booleanv = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_booleanv", "iio", false)); private static var lime_al_gen_buffer = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_gen_buffer", "o", false)); private static var lime_al_gen_buffers = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_gen_buffers", "io", false)); - private static var lime_al_get_buffer3f = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_buffer3f", "oio", - false)); - private static var lime_al_get_buffer3i = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_buffer3i", "oio", - false)); + private static var lime_al_get_buffer3f = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_buffer3f", "oio", false)); + private static var lime_al_get_buffer3i = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_buffer3i", "oio", false)); private static var lime_al_get_bufferf = new cpp.CallableInt->cpp.Float32>(cpp.Prime._loadPrime("lime", "lime_al_get_bufferf", "oif", false)); private static var lime_al_get_bufferfv = new cpp.CallableInt->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_bufferfv", "oiio", false)); @@ -1914,10 +3165,8 @@ class NativeCFFI private static var lime_al_get_listeneri = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_al_get_listeneri", "ii", false)); private static var lime_al_get_listeneriv = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_listeneriv", "iio", false)); private static var lime_al_get_proc_address = new cpp.CallableFloat>(cpp.Prime._loadPrime("lime", "lime_al_get_proc_address", "sd", false)); - private static var lime_al_get_source3f = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_source3f", "oio", - false)); - private static var lime_al_get_source3i = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_source3i", "oio", - false)); + private static var lime_al_get_source3f = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_source3f", "oio", false)); + private static var lime_al_get_source3i = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_source3i", "oio", false)); private static var lime_al_get_sourcef = new cpp.CallableInt->cpp.Float32>(cpp.Prime._loadPrime("lime", "lime_al_get_sourcef", "oif", false)); private static var lime_al_get_sourcefv = new cpp.CallableInt->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_sourcefv", "oiio", false)); @@ -1927,8 +3176,9 @@ class NativeCFFI private static var lime_al_get_string = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_string", "io", false)); private static var lime_al_is_buffer = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_al_is_buffer", "ob", false)); private static var lime_al_is_enabled = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_al_is_enabled", "ib", false)); - private static var lime_al_is_extension_present = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_al_is_extension_present", "sb", - false)); + private static var lime_al_is_extension_present = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_al_is_extension_present", "sb", false)); + private static var lime_alc_is_extension_present = new cpp.CallableString->Bool>(cpp.Prime._loadPrime("lime", + "lime_alc_is_extension_present", "osb", false)); private static var lime_al_is_source = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_al_is_source", "ob", false)); private static var lime_al_listener3f = new cpp.Callablecpp.Float32->cpp.Float32->cpp.Float32->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_listener3f", "ifffv", false)); @@ -1938,8 +3188,7 @@ class NativeCFFI private static var lime_al_listeneri = new cpp.CallableInt->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_listeneri", "iiv", false)); private static var lime_al_listeneriv = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_listeneriv", "iov", false)); private static var lime_al_source_pause = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_source_pause", "ov", false)); - private static var lime_al_source_pausev = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_source_pausev", "iov", - false)); + private static var lime_al_source_pausev = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_source_pausev", "iov", false)); private static var lime_al_source_play = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_source_play", "ov", false)); private static var lime_al_source_playv = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_source_playv", "iov", false)); private static var lime_al_source_queue_buffers = new cpp.CallableInt->cpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", @@ -1967,8 +3216,7 @@ class NativeCFFI private static var lime_alc_close_device = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_alc_close_device", "ob", false)); private static var lime_alc_create_context = new cpp.Callablecpp.Object->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_alc_create_context", "ooo", false)); - private static var lime_alc_destroy_context = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_destroy_context", "ov", - false)); + private static var lime_alc_destroy_context = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_destroy_context", "ov", false)); private static var lime_alc_get_contexts_device = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_alc_get_contexts_device", "oo", false)); private static var lime_alc_get_current_context = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_alc_get_current_context", "o", @@ -1981,11 +3229,17 @@ class NativeCFFI false)); private static var lime_alc_open_device = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_alc_open_device", "so", false)); private static var lime_alc_pause_device = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_pause_device", "ov", false)); - private static var lime_alc_process_context = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_process_context", "ov", - false)); + private static var lime_alc_process_context = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_process_context", "ov", false)); private static var lime_alc_resume_device = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_resume_device", "ov", false)); - private static var lime_alc_suspend_context = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_suspend_context", "ov", - false)); + private static var lime_alc_suspend_context = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_suspend_context", "ov", false)); + private static var lime_alc_capture_open_device = new cpp.CallableInt->Int->Int->cpp.Object>(cpp.Prime._loadPrime("lime", + "lime_alc_capture_open_device", "siiio", false)); + private static var lime_alc_capture_close_device = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_alc_capture_close_device", "ob", + false)); + private static var lime_alc_capture_start = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_capture_start", "ov", false)); + private static var lime_alc_capture_stop = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_alc_capture_stop", "ov", false)); + private static var lime_alc_capture_samples = new cpp.Callablecpp.Object->Int->cpp.Void>(cpp.Prime._loadPrime("lime", + "lime_alc_capture_samples", "ooiv", false)); private static var lime_al_gen_filter = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_gen_filter", "o", false)); private static var lime_al_filteri = new cpp.CallableInt->cpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_al_filteri", "oiov", false)); @@ -2068,6 +3322,7 @@ class NativeCFFI private static var lime_al_is_buffer = CFFI.load("lime", "lime_al_is_buffer", 1); private static var lime_al_is_enabled = CFFI.load("lime", "lime_al_is_enabled", 1); private static var lime_al_is_extension_present = CFFI.load("lime", "lime_al_is_extension_present", 1); + private static var lime_alc_is_extension_present = CFFI.load("lime", "lime_alc_is_extension_present", 2); private static var lime_al_is_source = CFFI.load("lime", "lime_al_is_source", 1); private static var lime_al_listener3f = CFFI.load("lime", "lime_al_listener3f", 4); private static var lime_al_listener3i = CFFI.load("lime", "lime_al_listener3i", 4); @@ -2106,6 +3361,11 @@ class NativeCFFI private static var lime_alc_process_context = CFFI.load("lime", "lime_alc_process_context", 1); private static var lime_alc_resume_device = CFFI.load("lime", "lime_alc_resume_device", 1); private static var lime_alc_suspend_context = CFFI.load("lime", "lime_alc_suspend_context", 1); + private static var lime_alc_capture_open_device = CFFI.load("lime", "lime_alc_capture_open_device", 4); + private static var lime_alc_capture_close_device = CFFI.load("lime", "lime_alc_capture_close_device", 1); + private static var lime_alc_capture_start = CFFI.load("lime", "lime_alc_capture_start", 1); + private static var lime_alc_capture_stop = CFFI.load("lime", "lime_alc_capture_stop", 1); + private static var lime_alc_capture_samples = CFFI.load("lime", "lime_alc_capture_samples", 3); private static var lime_al_gen_filter = CFFI.load("lime", "lime_al_gen_filter", 0); private static var lime_al_filteri = CFFI.load("lime", "lime_al_filteri", 3); private static var lime_al_filterf = CFFI.load("lime", "lime_al_filterf", 3); @@ -2349,6 +3609,11 @@ class NativeCFFI return false; } + @:hlNative("lime", "hl_alc_is_extension_present") private static function lime_alc_is_extension_present(device:CFFIPointer, extname:String):Bool + { + return false; + } + @:hlNative("lime", "hl_al_is_source") private static function lime_al_is_source(source:CFFIPointer):Bool { return false; @@ -2394,8 +3659,7 @@ class NativeCFFI @:hlNative("lime", "hl_al_source3f") private static function lime_al_source3f(source:CFFIPointer, param:Int, value1:hl.F32, value2:hl.F32, value3:hl.F32):Void {} - @:hlNative("lime", "hl_al_source3i") private static function lime_al_source3i(source:CFFIPointer, param:Int, value1:Dynamic, value2:Int, - value3:Int):Void {} + @:hlNative("lime", "hl_al_source3i") private static function lime_al_source3i(source:CFFIPointer, param:Int, value1:Dynamic, value2:Int, value3:Int):Void {} @:hlNative("lime", "hl_al_sourcef") private static function lime_al_sourcef(source:CFFIPointer, param:Int, value:hl.F32):Void {} @@ -2462,6 +3726,23 @@ class NativeCFFI @:hlNative("lime", "hl_alc_suspend_context") private static function lime_alc_suspend_context(context:ALContext):Void {} + @:hlNative("lime", "hl_alc_capture_open_device") private static function lime_alc_capture_open_device(devicename:String, frequency:Int, format:Int, + buffersize:Int):CFFIPointer + { + return null; + } + + @:hlNative("lime", "hl_alc_capture_close_device") private static function lime_alc_capture_close_device(device:ALDevice):Bool + { + return false; + } + + @:hlNative("lime", "hl_alc_capture_start") private static function lime_alc_capture_start(device:ALDevice):Void {} + + @:hlNative("lime", "hl_alc_capture_stop") private static function lime_alc_capture_stop(device:ALDevice):Void {} + + @:hlNative("lime", "hl_alc_capture_samples") private static function lime_alc_capture_samples(device:ALDevice, buffer:Bytes, samples:Int):Void {} + @:hlNative("lime", "hl_al_gen_filter") private static function lime_al_gen_filter():CFFIPointer { return null; @@ -2764,8 +4045,7 @@ class NativeCFFI private static var lime_cairo_arc_negative = new cpp.CallableFloat->Float->Float->Float->Float->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_arc_negative", "odddddv", false)); private static var lime_cairo_clip = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_clip", "ov", false)); - private static var lime_cairo_clip_preserve = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_clip_preserve", "ov", - false)); + private static var lime_cairo_clip_preserve = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_clip_preserve", "ov", false)); private static var lime_cairo_clip_extents = new cpp.CallableFloat->Float->Float->Float->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_clip_extents", "oddddv", false)); private static var lime_cairo_close_path = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_close_path", "ov", false)); @@ -2776,8 +4056,7 @@ class NativeCFFI private static var lime_cairo_fill = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_fill", "ov", false)); private static var lime_cairo_fill_extents = new cpp.CallableFloat->Float->Float->Float->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_fill_extents", "oddddv", false)); - private static var lime_cairo_fill_preserve = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_fill_preserve", "ov", - false)); + private static var lime_cairo_fill_preserve = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_fill_preserve", "ov", false)); private static var lime_cairo_get_antialias = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_cairo_get_antialias", "oi", false)); private static var lime_cairo_get_current_point = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_cairo_get_current_point", "oo", false)); @@ -2804,10 +4083,8 @@ class NativeCFFI false)); private static var lime_cairo_identity_matrix = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_identity_matrix", "ov", false)); - private static var lime_cairo_in_clip = new cpp.CallableFloat->Float->Bool>(cpp.Prime._loadPrime("lime", "lime_cairo_in_clip", "oddb", - false)); - private static var lime_cairo_in_fill = new cpp.CallableFloat->Float->Bool>(cpp.Prime._loadPrime("lime", "lime_cairo_in_fill", "oddb", - false)); + private static var lime_cairo_in_clip = new cpp.CallableFloat->Float->Bool>(cpp.Prime._loadPrime("lime", "lime_cairo_in_clip", "oddb", false)); + private static var lime_cairo_in_fill = new cpp.CallableFloat->Float->Bool>(cpp.Prime._loadPrime("lime", "lime_cairo_in_fill", "oddb", false)); private static var lime_cairo_in_stroke = new cpp.CallableFloat->Float->Bool>(cpp.Prime._loadPrime("lime", "lime_cairo_in_stroke", "oddb", false)); private static var lime_cairo_line_to = new cpp.CallableFloat->Float->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_line_to", "oddv", @@ -2839,8 +4116,7 @@ class NativeCFFI private static var lime_cairo_restore = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_restore", "ov", false)); private static var lime_cairo_rotate = new cpp.CallableFloat->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_rotate", "odv", false)); private static var lime_cairo_save = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_save", "ov", false)); - private static var lime_cairo_scale = new cpp.CallableFloat->Float->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_scale", "oddv", - false)); + private static var lime_cairo_scale = new cpp.CallableFloat->Float->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_scale", "oddv", false)); private static var lime_cairo_set_antialias = new cpp.CallableInt->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_set_antialias", "oiv", false)); private static var lime_cairo_set_dash = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_set_dash", "oov", @@ -2958,8 +4234,7 @@ class NativeCFFI "lime_cairo_pattern_set_filter", "oiv", false)); private static var lime_cairo_pattern_set_matrix = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_pattern_set_matrix", "oov", false)); - private static var lime_cairo_surface_flush = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_surface_flush", "ov", - false)); + private static var lime_cairo_surface_flush = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_cairo_surface_flush", "ov", false)); #end #end #if (neko || cppia) @@ -3104,8 +4379,8 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_cairo_curve_to") private static function lime_cairo_curve_to(handle:CFFIPointer, x1:Float, y1:Float, x2:Float, y2:Float, - x3:Float, y3:Float):Void {} + @:hlNative("lime", "hl_cairo_curve_to") private static function lime_cairo_curve_to(handle:CFFIPointer, x1:Float, y1:Float, x2:Float, y2:Float, x3:Float, + y3:Float):Void {} @:hlNative("lime", "hl_cairo_fill") private static function lime_cairo_fill(handle:CFFIPointer):Void {} @@ -3245,8 +4520,7 @@ class NativeCFFI @:hlNative("lime", "hl_cairo_push_group") private static function lime_cairo_push_group(handle:CFFIPointer):Void {} - @:hlNative("lime", "hl_cairo_push_group_with_content") private static function lime_cairo_push_group_with_content(handle:CFFIPointer, - content:Int):Void {} + @:hlNative("lime", "hl_cairo_push_group_with_content") private static function lime_cairo_push_group_with_content(handle:CFFIPointer, content:Int):Void {} @:hlNative("lime", "hl_cairo_rectangle") private static function lime_cairo_rectangle(handle:CFFIPointer, x:Float, y:Float, width:Float, height:Float):Void {} @@ -3299,8 +4573,8 @@ class NativeCFFI @:hlNative("lime", "hl_cairo_set_source_rgba") private static function lime_cairo_set_source_rgba(handle:CFFIPointer, r:Float, g:Float, b:Float, a:Float):Void {} - @:hlNative("lime", "hl_cairo_set_source_surface") private static function lime_cairo_set_source_surface(handle:CFFIPointer, surface:CFFIPointer, - x:Float, y:Float):Void {} + @:hlNative("lime", "hl_cairo_set_source_surface") private static function lime_cairo_set_source_surface(handle:CFFIPointer, surface:CFFIPointer, x:Float, + y:Float):Void {} @:hlNative("lime", "hl_cairo_set_tolerance") private static function lime_cairo_set_tolerance(handle:CFFIPointer, tolerance:Float):Void {} @@ -3368,14 +4642,12 @@ class NativeCFFI return 0; } - @:hlNative("lime", "hl_cairo_font_options_set_antialias") private static function lime_cairo_font_options_set_antialias(handle:CFFIPointer, - v:Int):Void {} + @:hlNative("lime", "hl_cairo_font_options_set_antialias") private static function lime_cairo_font_options_set_antialias(handle:CFFIPointer, v:Int):Void {} @:hlNative("lime", "hl_cairo_font_options_set_hint_metrics") private static function lime_cairo_font_options_set_hint_metrics(handle:CFFIPointer, v:Int):Void {} - @:hlNative("lime", "hl_cairo_font_options_set_hint_style") private static function lime_cairo_font_options_set_hint_style(handle:CFFIPointer, - v:Int):Void {} + @:hlNative("lime", "hl_cairo_font_options_set_hint_style") private static function lime_cairo_font_options_set_hint_style(handle:CFFIPointer, v:Int):Void {} @:hlNative("lime", "hl_cairo_font_options_set_subpixel_order") private static function lime_cairo_font_options_set_subpixel_order(handle:CFFIPointer, v:Int):Void {} @@ -3385,8 +4657,7 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_cairo_image_surface_create") private static function lime_cairo_image_surface_create(format:Int, width:Int, - height:Int):CFFIPointer + @:hlNative("lime", "hl_cairo_image_surface_create") private static function lime_cairo_image_surface_create(format:Int, width:Int, height:Int):CFFIPointer { return null; } @@ -3422,8 +4693,8 @@ class NativeCFFI return 0; } - @:hlNative("lime", "hl_cairo_pattern_add_color_stop_rgb") private static function lime_cairo_pattern_add_color_stop_rgb(handle:CFFIPointer, - offset:Float, red:Float, green:Float, blue:Float):Void {} + @:hlNative("lime", "hl_cairo_pattern_add_color_stop_rgb") private static function lime_cairo_pattern_add_color_stop_rgb(handle:CFFIPointer, offset:Float, + red:Float, green:Float, blue:Float):Void {} @:hlNative("lime", "hl_cairo_pattern_add_color_stop_rgba") private static function lime_cairo_pattern_add_color_stop_rgba(handle:CFFIPointer, offset:Float, red:Float, green:Float, blue:Float, alpha:Float):Void {} @@ -4543,8 +5814,7 @@ class NativeCFFI private static var lime_gl_get_vertex_attribi = new cpp.CallableInt->Int>(cpp.Prime._loadPrime("lime", "lime_gl_get_vertex_attribi", "iii", false)); private static var lime_gl_get_vertex_attribiv = new cpp.CallableInt->lime.utils.DataPointer->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_gl_get_vertex_attribiv", "iidv", false)); - private static var lime_gl_get_vertex_attribii = new cpp.CallableInt->Int>(cpp.Prime._loadPrime("lime", "lime_gl_get_vertex_attribii", "iii", - false)); + private static var lime_gl_get_vertex_attribii = new cpp.CallableInt->Int>(cpp.Prime._loadPrime("lime", "lime_gl_get_vertex_attribii", "iii", false)); private static var lime_gl_get_vertex_attribiiv = new cpp.CallableInt->lime.utils.DataPointer->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_gl_get_vertex_attribiiv", "iidv", false)); private static var lime_gl_get_vertex_attribiui = new cpp.CallableInt->Int>(cpp.Prime._loadPrime("lime", "lime_gl_get_vertex_attribiui", "iii", @@ -5053,8 +6323,7 @@ class NativeCFFI @:hlNative("lime", "hl_gl_buffer_data") private static function lime_gl_buffer_data(target:Int, size:Int, srcData:DataPointer, usage:Int):Void {} - @:hlNative("lime", "hl_gl_buffer_sub_data") private static function lime_gl_buffer_sub_data(target:Int, offset:Int, size:Int, - srcData:DataPointer):Void {} + @:hlNative("lime", "hl_gl_buffer_sub_data") private static function lime_gl_buffer_sub_data(target:Int, offset:Int, size:Int, srcData:DataPointer):Void {} @:hlNative("lime", "hl_gl_check_framebuffer_status") private static function lime_gl_check_framebuffer_status(target:Int):Int { @@ -5071,8 +6340,7 @@ class NativeCFFI @:hlNative("lime", "hl_gl_clear_bufferuiv") private static function lime_gl_clear_bufferuiv(buffer:Int, drawBuffer:Int, data:DataPointer):Void {} - @:hlNative("lime", "hl_gl_client_wait_sync") private static function lime_gl_client_wait_sync(sync:CFFIPointer, flags:Int, timeoutA:Int, - timeoutB:Int):Int + @:hlNative("lime", "hl_gl_client_wait_sync") private static function lime_gl_client_wait_sync(sync:CFFIPointer, flags:Int, timeoutA:Int, timeoutB:Int):Int { return 0; } @@ -5295,8 +6563,7 @@ class NativeCFFI @:hlNative("lime", "hl_gl_get_buffer_parameteri64v") private static function lime_gl_get_buffer_parameteri64v(target:Int, index:Int, params:DataPointer):Void {} - @:hlNative("lime", "hl_gl_get_buffer_parameteriv") private static function lime_gl_get_buffer_parameteriv(target:Int, pname:Int, - params:DataPointer):Void {} + @:hlNative("lime", "hl_gl_get_buffer_parameteriv") private static function lime_gl_get_buffer_parameteriv(target:Int, pname:Int, params:DataPointer):Void {} @:hlNative("lime", "hl_gl_get_buffer_pointerv") private static function lime_gl_get_buffer_pointerv(target:Int, pname:Int):DataPointer { @@ -5658,8 +6925,8 @@ class NativeCFFI @:hlNative("lime", "hl_gl_scissor") private static function lime_gl_scissor(x:Int, y:Int, width:Int, height:Int):Void {} - @:hlNative("lime", "hl_gl_shader_binary") private static function lime_gl_shader_binary(shaders:hl.NativeArray, binaryformat:Int, - binary:DataPointer, length:Int):Void {} + @:hlNative("lime", "hl_gl_shader_binary") private static function lime_gl_shader_binary(shaders:hl.NativeArray, binaryformat:Int, binary:DataPointer, + length:Int):Void {} @:hlNative("lime", "hl_gl_shader_source") private static function lime_gl_shader_source(shader:Int, source:String):Void {} @@ -5691,8 +6958,8 @@ class NativeCFFI @:hlNative("lime", "hl_gl_tex_storage_3d") private static function lime_gl_tex_storage_3d(target:Int, level:Int, internalformat:Int, width:Int, height:Int, depth:Int):Void {} - @:hlNative("lime", "hl_gl_tex_sub_image_2d") private static function lime_gl_tex_sub_image_2d(target:Int, level:Int, xoffset:Int, yoffset:Int, - width:Int, height:Int, format:Int, type:Int, data:DataPointer):Void {} + @:hlNative("lime", "hl_gl_tex_sub_image_2d") private static function lime_gl_tex_sub_image_2d(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, + height:Int, format:Int, type:Int, data:DataPointer):Void {} @:hlNative("lime", "hl_gl_tex_sub_image_3d") private static function lime_gl_tex_sub_image_3d(target:Int, level:Int, xoffset:Int, yoffset:Int, zoffset:Int, width:Int, height:Int, depth:Int, format:Int, type:Int, data:DataPointer):Void {} @@ -6063,8 +7330,7 @@ class NativeCFFI private static var lime_hb_blob_is_immutable = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", "lime_hb_blob_is_immutable", "ob", false)); private static var lime_hb_blob_make_immutable = new cpp.Callablecpp.Void>(cpp.Prime._loadPrime("lime", "lime_hb_blob_make_immutable", "ov", false)); - private static var lime_hb_buffer_add = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_hb_buffer_add", "oiiv", - false)); + private static var lime_hb_buffer_add = new cpp.CallableInt->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_hb_buffer_add", "oiiv", false)); private static var lime_hb_buffer_add_hxstring = new cpp.CallableString->Int->Int->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_hb_buffer_add_hxstring", "osiiv", false)); private static var lime_hb_buffer_add_codepoints = new cpp.Callablelime.utils.DataPointer->Int->Int->Int-> @@ -6151,8 +7417,7 @@ class NativeCFFI "oiv", false)); private static var lime_hb_face_set_index = new cpp.CallableInt->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_hb_face_set_index", "oiv", false)); - private static var lime_hb_face_set_upem = new cpp.CallableInt->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_hb_face_set_upem", "oiv", - false)); + private static var lime_hb_face_set_upem = new cpp.CallableInt->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_hb_face_set_upem", "oiv", false)); private static var lime_hb_feature_from_string = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_hb_feature_from_string", "so", false)); private static var lime_hb_feature_to_string = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_hb_feature_to_string", "oo", @@ -6170,8 +7435,7 @@ class NativeCFFI "lime_hb_font_get_glyph_kerning_for_direction", "oiiio", false)); private static var lime_hb_font_get_glyph_origin_for_direction = new cpp.CallableInt->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_hb_font_get_glyph_origin_for_direction", "oiio", false)); - private static var lime_hb_font_get_parent = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_hb_font_get_parent", "oo", - false)); + private static var lime_hb_font_get_parent = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_hb_font_get_parent", "oo", false)); private static var lime_hb_font_get_ppem = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_hb_font_get_ppem", "oo", false)); private static var lime_hb_font_get_scale = new cpp.Callablecpp.Object>(cpp.Prime._loadPrime("lime", "lime_hb_font_get_scale", "oo", false)); private static var lime_hb_font_glyph_from_string = new cpp.CallableString->Int>(cpp.Prime._loadPrime("lime", @@ -6515,8 +7779,7 @@ class NativeCFFI return null; } - @:hlNative("lime", "hl_hb_buffer_set_cluster_level") private static function lime_hb_buffer_set_cluster_level(buffer:CFFIPointer, - clusterLevel:Int):Void {} + @:hlNative("lime", "hl_hb_buffer_set_cluster_level") private static function lime_hb_buffer_set_cluster_level(buffer:CFFIPointer, clusterLevel:Int):Void {} @:hlNative("lime", "hl_hb_buffer_set_content_type") private static function lime_hb_buffer_set_content_type(buffer:CFFIPointer, contentType:Int):Void {} @@ -6675,8 +7938,8 @@ class NativeCFFI @:hlNative("lime", "hl_hb_font_set_scale") private static function lime_hb_font_set_scale(font:CFFIPointer, xScale:Int, yScale:Int):Void {} @:hlNative("lime", - "hl_hb_font_subtract_glyph_origin_for_direction") private static function lime_hb_font_subtract_glyph_origin_for_direction(font:CFFIPointer, - glyph:Int, direction:Int, x:Int, y:Int):Void {} + "hl_hb_font_subtract_glyph_origin_for_direction") private static function lime_hb_font_subtract_glyph_origin_for_direction(font:CFFIPointer, glyph:Int, + direction:Int, x:Int, y:Int):Void {} @:hlNative("lime", "hl_hb_ft_font_create") private static function lime_hb_ft_font_create(font:CFFIPointer):CFFIPointer { @@ -6799,8 +8062,7 @@ class NativeCFFI @:hlNative("lime", "hl_hb_set_union") private static function lime_hb_set_union(set:CFFIPointer, other:CFFIPointer):Void {} - @:hlNative("lime", "hl_hb_shape") private static function lime_hb_shape(font:CFFIPointer, buffer:CFFIPointer, - features:hl.NativeArray):Void {} + @:hlNative("lime", "hl_hb_shape") private static function lime_hb_shape(font:CFFIPointer, buffer:CFFIPointer, features:hl.NativeArray):Void {} #end #end #if (lime_cffi && !macro && lime_vorbis) @@ -6997,8 +8259,7 @@ class NativeCFFI return 0; } - @:hlNative("lime", "hl_vorbis_file_pcm_seek_lap") private static function lime_vorbis_file_pcm_seek_lap(vorbisFile:CFFIPointer, posLow:Int, - posHigh:Int):Int + @:hlNative("lime", "hl_vorbis_file_pcm_seek_lap") private static function lime_vorbis_file_pcm_seek_lap(vorbisFile:CFFIPointer, posLow:Int, posHigh:Int):Int { return 0; } @@ -7020,8 +8281,7 @@ class NativeCFFI return 0; } - @:hlNative("lime", "hl_vorbis_file_raw_seek_lap") private static function lime_vorbis_file_raw_seek_lap(vorbisFile:CFFIPointer, posLow:Int, - posHigh:Int):Int + @:hlNative("lime", "hl_vorbis_file_raw_seek_lap") private static function lime_vorbis_file_raw_seek_lap(vorbisFile:CFFIPointer, posLow:Int, posHigh:Int):Int { return 0; } @@ -7105,4 +8365,3 @@ class NativeCFFI #end #end } - diff --git a/src/lime/_internal/backend/native/NativeHTTPRequest.hx b/src/lime/_internal/backend/native/NativeHTTPRequest.hx index 026d23f963..c09d041288 100644 --- a/src/lime/_internal/backend/native/NativeHTTPRequest.hx +++ b/src/lime/_internal/backend/native/NativeHTTPRequest.hx @@ -361,7 +361,8 @@ class NativeHTTPRequest return promise.future; } - private function buildBuffer() { + private function buildBuffer() + { bytes = buffer.getBytes(); return bytes; } diff --git a/src/lime/_internal/backend/native/NativeWindow.hx b/src/lime/_internal/backend/native/NativeWindow.hx index 0f6028a296..6fc4344a59 100644 --- a/src/lime/_internal/backend/native/NativeWindow.hx +++ b/src/lime/_internal/backend/native/NativeWindow.hx @@ -14,6 +14,7 @@ import lime.graphics.Image; import lime.graphics.ImageBuffer; import lime.graphics.OpenGLRenderContext; import lime.graphics.RenderContext; +import lime.graphics.VulkanRenderContext; import lime.math.Rectangle; import lime.math.Vector2; import lime.system.CFFI; @@ -67,9 +68,12 @@ class NativeWindow var resolvedVSyncMode = parent.application.__resolveVSyncMode(attributes); var title = Reflect.hasField(attributes, "title") ? attributes.title : "Lime Application"; var flags = 0; + var transparent = Reflect.hasField(attributes, "transparent") && attributes.transparent; if (!Reflect.hasField(contextAttributes, "antialiasing")) contextAttributes.antialiasing = 0; - if (!Reflect.hasField(contextAttributes, "background")) contextAttributes.background = 0; - if (!Reflect.hasField(contextAttributes, "colorDepth")) contextAttributes.colorDepth = 24; + if (transparent) contextAttributes.background = null; + else if (!Reflect.hasField(contextAttributes, "background")) contextAttributes.background = 0; + if (!Reflect.hasField(contextAttributes, "colorDepth")) contextAttributes.colorDepth = transparent ? 32 : 24; + else if (transparent && contextAttributes.colorDepth < 32) contextAttributes.colorDepth = 32; if (!Reflect.hasField(contextAttributes, "depth")) contextAttributes.depth = true; if (!Reflect.hasField(contextAttributes, "hardware")) contextAttributes.hardware = true; if (!Reflect.hasField(contextAttributes, "stencil")) contextAttributes.stencil = true; @@ -79,14 +83,19 @@ class NativeWindow contextAttributes.vsync = (resolvedVSyncMode != VSyncMode.Off); #if (cairo || (!lime_opengl && !lime_opengles)) - contextAttributes.type = CAIRO; + if (!Reflect.hasField(contextAttributes, "type") || contextAttributes.type != VULKAN) + { + contextAttributes.type = CAIRO; + } #end if (Reflect.hasField(contextAttributes, "type") && contextAttributes.type == CAIRO) contextAttributes.hardware = false; + if (Reflect.hasField(contextAttributes, "type") && contextAttributes.type == VULKAN) contextAttributes.hardware = true; if (Reflect.hasField(attributes, "allowHighDPI") && attributes.allowHighDPI) flags |= cast WindowFlags.WINDOW_FLAG_ALLOW_HIGHDPI; if (Reflect.hasField(attributes, "alwaysOnTop") && attributes.alwaysOnTop) flags |= cast WindowFlags.WINDOW_FLAG_ALWAYS_ON_TOP; if (Reflect.hasField(attributes, "borderless") && attributes.borderless) flags |= cast WindowFlags.WINDOW_FLAG_BORDERLESS; if (Reflect.hasField(attributes, "fullscreen") && attributes.fullscreen) flags |= cast WindowFlags.WINDOW_FLAG_FULLSCREEN; + if (transparent) flags |= cast WindowFlags.WINDOW_FLAG_TRANSPARENT; if (Reflect.hasField(attributes, "hidden") && attributes.hidden) flags |= cast WindowFlags.WINDOW_FLAG_HIDDEN; if (Reflect.hasField(attributes, "maximized") && attributes.maximized) flags |= cast WindowFlags.WINDOW_FLAG_MAXIMIZED; @@ -106,6 +115,7 @@ class NativeWindow if (contextAttributes.depth) flags |= cast WindowFlags.WINDOW_FLAG_DEPTH_BUFFER; if (contextAttributes.hardware) flags |= cast WindowFlags.WINDOW_FLAG_HARDWARE; + if (Reflect.hasField(contextAttributes, "type") && contextAttributes.type == VULKAN) flags |= cast WindowFlags.WINDOW_FLAG_VULKAN; if (contextAttributes.stencil) flags |= cast WindowFlags.WINDOW_FLAG_STENCIL_BUFFER; if (contextAttributes.vsync) flags |= cast WindowFlags.WINDOW_FLAG_VSYNC; @@ -115,17 +125,19 @@ class NativeWindow #if (!macro && lime_cffi) handle = NativeCFFI.lime_window_create(parent.application.__backend.handle, width, height, flags, title); - if (handle != null) + if (handle == null) { - parent.__width = NativeCFFI.lime_window_get_width(handle); + return; + } - parent.__height = NativeCFFI.lime_window_get_height(handle); - parent.__x = NativeCFFI.lime_window_get_x(handle); - parent.__y = NativeCFFI.lime_window_get_y(handle); - parent.__hidden = (Reflect.hasField(attributes, "hidden") && attributes.hidden); + parent.__width = NativeCFFI.lime_window_get_width(handle); - parent.id = NativeCFFI.lime_window_get_id(handle); - } + parent.__height = NativeCFFI.lime_window_get_height(handle); + parent.__x = NativeCFFI.lime_window_get_x(handle); + parent.__y = NativeCFFI.lime_window_get_y(handle); + parent.__hidden = (Reflect.hasField(attributes, "hidden") && attributes.hidden); + + parent.id = NativeCFFI.lime_window_get_id(handle); parent.__scale = NativeCFFI.lime_window_get_scale(handle); var context = new RenderContext(); @@ -156,6 +168,13 @@ class NativeWindow { GL.context = gl; } + case "vulkan": + useHardware = true; + contextAttributes.hardware = true; + context.vulkan = new VulkanRenderContext(handle); + context.type = VULKAN; + context.version = Reflect.hasField(contextAttributes, "version") + && contextAttributes.version != null ? contextAttributes.version : ""; default: useHardware = false; @@ -742,4 +761,6 @@ class NativeWindow var WINDOW_FLAG_MAXIMIZED = 0x00004000; var WINDOW_FLAG_ALWAYS_ON_TOP = 0x00008000; var WINDOW_FLAG_COLOR_DEPTH_32_BIT = 0x00010000; + var WINDOW_FLAG_VULKAN = 0x00020000; + var WINDOW_FLAG_TRANSPARENT = 0x00040000; } diff --git a/src/lime/_internal/graphics/ImageDataUtil.hx b/src/lime/_internal/graphics/ImageDataUtil.hx index 5837151cc5..6cf41a857f 100644 --- a/src/lime/_internal/graphics/ImageDataUtil.hx +++ b/src/lime/_internal/graphics/ImageDataUtil.hx @@ -238,11 +238,7 @@ class ImageDataUtil var srcPremultiplied = sourceImage.buffer.premultiplied; var destPremultiplied = image.buffer.premultiplied; - var srcPosition, - destPosition, - srcPixel:RGBA = 0, - destPixel:RGBA = 0, - value = 0; + var srcPosition, destPosition, srcPixel:RGBA = 0, destPixel:RGBA = 0, value = 0; for (y in 0...destView.height) { @@ -601,12 +597,7 @@ class ImageDataUtil queue.push(x); queue.push(y); - var curPointX, - curPointY, - nextPointX, - nextPointY, - nextPointOffset, - readColor:RGBA = 0; + var curPointX, curPointY, nextPointX, nextPointY, nextPointOffset, readColor:RGBA = 0; while (queue.length > 0) { @@ -1000,18 +991,9 @@ class ImageDataUtil var data = image.data; var newData = newBuffer.data; - var sourceIndex:Int, - sourceIndexX:Int, - sourceIndexY:Int, - sourceIndexXY:Int, - index:Int; + var sourceIndex:Int, sourceIndexX:Int, sourceIndexY:Int, sourceIndexXY:Int, index:Int; var sourceX:Int, sourceY:Int; - var u:Float, - v:Float, - uRatio:Float, - vRatio:Float, - uOpposite:Float, - vOpposite:Float; + var u:Float, v:Float, uRatio:Float, vRatio:Float, uOpposite:Float, vOpposite:Float; for (y in 0...newHeight) { @@ -1361,13 +1343,7 @@ class ImageDataUtil var srcPremultiplied = sourceImage.buffer.premultiplied; var destPremultiplied = image.buffer.premultiplied; - var srcPosition, - destPosition, - srcPixel:RGBA = 0, - destPixel:RGBA = 0, - pixelMask:UInt, - test:Bool, - value:Int; + var srcPosition, destPosition, srcPixel:RGBA = 0, destPixel:RGBA = 0, pixelMask:UInt, test:Bool, value:Int; for (y in 0...destView.height) { @@ -1774,8 +1750,7 @@ private class ImageDataView } } -@:noCompletion @:dox(hide) -#if (haxe_ver >= 4.0) private enum #else @:enum private #end abstract ThresholdOperation(Int) from Int to Int +@:noCompletion @:dox(hide) #if (haxe_ver >= 4.0) private enum #else @:enum private #end abstract ThresholdOperation(Int) from Int to Int { var NOT_EQUALS = 0; var EQUALS = 1; diff --git a/src/lime/_internal/macros/AssetsMacro.hx b/src/lime/_internal/macros/AssetsMacro.hx index a5b403ee86..390cc4c209 100644 --- a/src/lime/_internal/macros/AssetsMacro.hx +++ b/src/lime/_internal/macros/AssetsMacro.hx @@ -41,18 +41,17 @@ class AssetsMacro } } - var superCall = Context.defined("html5") ? macro super(bytes.b.buffer) - : Context.defined("hl") ? macro super(bytes.b, bytes.length) - : macro super(bytes.length, bytes.b); + var superCall = Context.defined("html5") ? macro super(bytes.b.buffer) : Context.defined("hl") ? macro super(bytes.b, + bytes.length) : macro super(bytes.length, bytes.b); var definition = macro class Temp - { - public function new(?length:Int, ?bytesData:haxe.io.BytesData) { - var bytes = haxe.Resource.getBytes(resourceName); - $superCall; - } - }; + public function new(?length:Int, ?bytesData:haxe.io.BytesData) + { + var bytes = haxe.Resource.getBytes(resourceName); + $superCall; + } + }; fields.push(definition.fields[0]); @@ -65,15 +64,15 @@ class AssetsMacro if (fields == null) return null; var definition = macro class Temp - { - public function new(?length:Int = 0) { - super(); + public function new(?length:Int = 0) + { + super(); - var bytes = haxe.Resource.getBytes(resourceName); - __fromBytes(bytes); - } - }; + var bytes = haxe.Resource.getBytes(resourceName); + __fromBytes(bytes); + } + }; fields.push(definition.fields[0]); @@ -112,11 +111,7 @@ class AssetsMacro } var bytes = File.getBytes(path); - var resourceName = "__ASSET__" - + metaName - + "_" - + (classType.pack.length > 0 ? classType.pack.join("_") + "_" : "") - + classType.name; + var resourceName = "__ASSET__" + metaName + "_" + (classType.pack.length > 0 ? classType.pack.join("_") + "_" : "") + classType.name; if (Context.getResources().exists(resourceName)) { @@ -137,9 +132,9 @@ class AssetsMacro } var definition = macro class Temp - { - private static inline var resourceType:String = $v{ resourceType }; - }; + { + private static inline var resourceType:String = $v{resourceType}; + }; fields.push(definition.fields[0]); @@ -152,9 +147,9 @@ class AssetsMacro } var definition = macro class Temp - { - private static inline var resourceName:String = $v{ resourceName }; - }; + { + private static inline var resourceName:String = $v{resourceName}; + }; fields.push(definition.fields[0]); @@ -226,16 +221,16 @@ class AssetsMacro } var definition = macro class Temp - { - private static var resourceName:String = $v{ resourceName }; - - public function new() { - super(); + private static var resourceName:String = $v{resourceName}; - __fromBytes(haxe.Resource.getBytes(resourceName)); - } - }; + public function new() + { + super(); + + __fromBytes(haxe.Resource.getBytes(resourceName)); + } + }; fields.push(definition.fields[0]); fields.push(definition.fields[1]); @@ -255,56 +250,53 @@ class AssetsMacro if (Context.defined("html5")) { definition = macro class Temp - { - public static var preload:js.html.Image; - - public function new(?buffer:lime.graphics.ImageBuffer, - ?offsetX:Int, ?offsetY:Int, ?width:Int, ?height:Int, - ?color:Null, ?type:lime.graphics.ImageType, - ?onload:Dynamic = true) { - super(); + public static var preload:js.html.Image; - if (preload != null) + public function new(?buffer:lime.graphics.ImageBuffer, ?offsetX:Int, ?offsetY:Int, ?width:Int, ?height:Int, ?color:Null, + ?type:lime.graphics.ImageType, ?onload:Dynamic = true) { - var buffer = new lime.graphics.ImageBuffer(); - buffer.__srcImage = preload; - buffer.width = preload.width; - buffer.width = preload.height; + super(); - __fromImageBuffer(buffer); - } - else - { - __fromBase64(haxe.Resource.getString(resourceName), resourceType, function(image) + if (preload != null) { - if (preload == null) - { - preload = image.buffer.__srcImage; - } + var buffer = new lime.graphics.ImageBuffer(); + buffer.__srcImage = preload; + buffer.width = preload.width; + buffer.width = preload.height; - if (onload != null) + __fromImageBuffer(buffer); + } + else + { + __fromBase64(haxe.Resource.getString(resourceName), resourceType, function(image) { - onload(image); - } - }); + if (preload == null) + { + preload = image.buffer.__srcImage; + } + + if (onload != null) + { + onload(image); + } + }); + } } - } - }; + }; } else { definition = macro class Temp - { - public function new(?buffer:lime.graphics.ImageBuffer, - ?offsetX:Int, ?offsetY:Int, ?width:Int, ?height:Int, - ?color:Null, ?type:lime.graphics.ImageType) { - super(); + public function new(?buffer:lime.graphics.ImageBuffer, ?offsetX:Int, ?offsetY:Int, ?width:Int, ?height:Int, ?color:Null, + ?type:lime.graphics.ImageType) + { + super(); - __fromBytes(haxe.Resource.getBytes(resourceName), null); - } - }; + __fromBytes(haxe.Resource.getBytes(resourceName), null); + } + }; } for (field in definition.fields) @@ -319,21 +311,18 @@ class AssetsMacro { var fields = embedData(":sound"); // CFFILoader.h(248) : NOT Implemented:api_buffer_data - if (fields == null || Context.defined("html5") || !Context.defined("openfl")) - return null; + if (fields == null || Context.defined("html5") || !Context.defined("openfl")) return null; var definition = macro class Temp - { - public function new(?stream:openfl.net.URLRequest, - ?context:openfl.media.SoundLoaderContext, - ?forcePlayAsMusic:Bool = false) { - super(); + public function new(?stream:openfl.net.URLRequest, ?context:openfl.media.SoundLoaderContext, ?forcePlayAsMusic:Bool = false) + { + super(); - var byteArray = openfl.utils.ByteArray.fromBytes(haxe.Resource.getBytes(resourceName)); - loadCompressedDataFromByteArray(byteArray, byteArray.length, forcePlayAsMusic); - } - }; + var byteArray = openfl.utils.ByteArray.fromBytes(haxe.Resource.getBytes(resourceName)); + loadCompressedDataFromByteArray(byteArray, byteArray.length, forcePlayAsMusic); + } + }; fields.push(definition.fields[0]); diff --git a/src/lime/_internal/macros/CFFIMacro.hx b/src/lime/_internal/macros/CFFIMacro.hx index 5b65675863..51430f550d 100644 --- a/src/lime/_internal/macros/CFFIMacro.hx +++ b/src/lime/_internal/macros/CFFIMacro.hx @@ -183,7 +183,7 @@ class CFFIMacro case "cpp.Float32": if (useCPPTypes) { - typeArgs.push({name: arg.name, opt: false, t: (macro:cpp.Float32).toType()}); + typeArgs.push({name: arg.name, opt: false, t: (macro :cpp.Float32).toType()}); } else { @@ -207,7 +207,7 @@ class CFFIMacro case "Void", "cpp.Void": if (useCPPTypes) { - typeArgs.push({name: arg.name, opt: false, t: (macro:cpp.Void).toType()}); + typeArgs.push({name: arg.name, opt: false, t: (macro :cpp.Void).toType()}); } else { @@ -219,11 +219,11 @@ class CFFIMacro default: if (useCPPTypes) { - typeArgs.push({name: arg.name, opt: false, t: (macro:cpp.Object).toType()}); + typeArgs.push({name: arg.name, opt: false, t: (macro :cpp.Object).toType()}); } else { - typeArgs.push({name: arg.name, opt: false, t: (macro:Dynamic).toType()}); + typeArgs.push({name: arg.name, opt: false, t: (macro :Dynamic).toType()}); } typeSignature += "o"; @@ -243,7 +243,7 @@ class CFFIMacro case "cpp.Float32": if (useCPPTypes) { - typeResult = (macro:cpp.Float32).toType(); + typeResult = (macro :cpp.Float32).toType(); } else { @@ -267,7 +267,7 @@ class CFFIMacro case "Void", "cpp.Void": if (useCPPTypes) { - typeResult = (macro:cpp.Void).toType(); + typeResult = (macro :cpp.Void).toType(); } else { @@ -279,11 +279,11 @@ class CFFIMacro default: if (useCPPTypes) { - typeResult = (macro:cpp.Object).toType(); + typeResult = (macro :cpp.Object).toType(); } else { - typeResult = (macro:Dynamic).toType(); + typeResult = (macro :Dynamic).toType(); } typeSignature += "o"; diff --git a/src/lime/_internal/macros/EventMacro.hx b/src/lime/_internal/macros/EventMacro.hx index ba42ce3b6c..b02ee73f43 100644 --- a/src/lime/_internal/macros/EventMacro.hx +++ b/src/lime/_internal/macros/EventMacro.hx @@ -29,8 +29,8 @@ class EventMacro return null; case TInst(_, paramTypes): - Context.fatalError("Expected only one type parameter. Did you mean Event<" - + paramTypes.map(haxe.macro.TypeTools.toString).join(" -> ") + ">?", Context.currentPos()); + Context.fatalError("Expected only one type parameter. Did you mean Event<" + paramTypes.map(haxe.macro.TypeTools.toString).join(" -> ") + ">?", + Context.currentPos()); return null; default: @@ -87,32 +87,105 @@ class EventMacro args.push({name: argName, type: typeArgs[i].t.toComplexType()}); } + var rethrow = if (Context.defined("cpp")) + { + macro cpp.Lib.rethrow(e); + } + else if (Context.defined("neko")) + { + macro neko.Lib.rethrow(e); + } + else if (Context.defined("hl")) + { + macro hl.Api.rethrow(e); + } + else if (Context.defined("js")) + { + macro js.Lib.rethrow(); + } + else + { + macro throw e; + } + var dispatch = macro { + var previousTimestamp = __timestamp; + __timestamp = lime.system.System.getTimer(); canceled = false; - var listeners = __listeners; - var repeat = __repeat; - var i = 0; - - while (i < listeners.length) + try { - listeners[i]($a{argNames}); + var listeners = __listeners; + var repeat = __repeat; + var i = 0; - if (!repeat[i]) + while (i < listeners.length) { - this.remove(cast listeners[i]); - } - else - { - i++; + listeners[i]($a{argNames}); + + if (!repeat[i]) + { + this.remove(cast listeners[i]); + } + else + { + i++; + } + + if (canceled) + { + break; + } } + } + catch (e:Dynamic) + { + __timestamp = previousTimestamp; + $rethrow; + } + + __timestamp = previousTimestamp; + } + + var timestampDispatch = macro + { + var previousTimestamp = __timestamp; + __timestamp = timestamp; + canceled = false; + + try + { + var listeners = __listeners; + var repeat = __repeat; + var i = 0; - if (canceled) + while (i < listeners.length) { - break; + listeners[i]($a{argNames}); + + if (!repeat[i]) + { + this.remove(cast listeners[i]); + } + else + { + i++; + } + + if (canceled) + { + break; + } } } + catch (e:Dynamic) + { + __timestamp = previousTimestamp; + $rethrow; + } + + __timestamp = previousTimestamp; } var i = 0; @@ -122,7 +195,7 @@ class EventMacro { field = fields[i]; - if (field.name == "__listeners" || field.name == "dispatch") + if (field.name == "__listeners" || field.name == "dispatch" || field.name == "__dispatchWithTimestamp") { fields.remove(field); } @@ -148,8 +221,26 @@ class EventMacro args: args, expr: dispatch, params: [], - ret: macro:Void + ret: macro :Void + }), + pos: pos + }); + fields.push( + { + name: "__dispatchWithTimestamp", + access: [APublic], + kind: FFun( + { + args: [ + {name: "timestamp", type: macro :Int}].concat(args), + expr: timestampDispatch, + params: [], + ret: macro :Void }), + meta: [ + {name: ":dox", params: [macro hide], pos: pos}, + {name: ":noCompletion", pos: pos} + ], pos: pos }); diff --git a/src/lime/_internal/macros/HTTPRequestMacro.hx b/src/lime/_internal/macros/HTTPRequestMacro.hx index f862fe6ead..e4532738e7 100644 --- a/src/lime/_internal/macros/HTTPRequestMacro.hx +++ b/src/lime/_internal/macros/HTTPRequestMacro.hx @@ -129,11 +129,11 @@ class HTTPRequestMacro kind: FFun( { args: [ - {name: "uri", type: macro:String, opt: true}], + {name: "uri", type: macro :String, opt: true}], expr: macro {super(uri);}, params: [], - ret: macro:Void + ret: macro :Void }), pos: Context.currentPos() }, @@ -143,7 +143,7 @@ class HTTPRequestMacro kind: FFun( { args: [ - {name: "bytes", type: macro:haxe.io.Bytes}], + {name: "bytes", type: macro :haxe.io.Bytes}], expr: Context.parse("return " + typeString + ".fromBytes (bytes)", pos), params: [], ret: paramType.toComplexType() diff --git a/src/lime/app/Application.hx b/src/lime/app/Application.hx index 10d128991e..7c617d01d1 100644 --- a/src/lime/app/Application.hx +++ b/src/lime/app/Application.hx @@ -868,6 +868,7 @@ class Application extends Module return __vsyncMode; } + @:allow(lime.ui.Window) @:noCompletion private function __seedFrameConfiguration(attributes:WindowAttributes):Void { if (__frameConfigured) diff --git a/src/lime/app/Event.hx b/src/lime/app/Event.hx index ed4a799279..bdca9898f0 100644 --- a/src/lime/app/Event.hx +++ b/src/lime/app/Event.hx @@ -30,10 +30,17 @@ class Event **/ public var canceled(default, null):Bool; + /** + The timestamp for the current dispatch, in milliseconds. + When read outside of a dispatch, this returns the current timer value. + **/ + public var timestamp(get, never):Int; + @:noCompletion @:dox(hide) public var __listeners:Array; @:noCompletion @:dox(hide) public var __repeat:Array; @:noCompletion private var __priorities:Array; + @:noCompletion private var __timestamp:Int; /** Creates a new Event instance @@ -45,6 +52,7 @@ class Event __listeners = new Array(); __priorities = new Array(); __repeat = new Array(); + __timestamp = -1; #end } @@ -90,6 +98,8 @@ class Event **/ public var dispatch:Dynamic; + @:noCompletion @:dox(hide) public var __dispatchWithTimestamp:Dynamic; + // macro public function dispatch (ethis:Expr, args:Array):Void { // // return macro { @@ -169,4 +179,13 @@ class Event __repeat.splice(0, len); #end } + + private function get_timestamp():Int + { + #if (lime_doc_gen || macro) + return (__timestamp != -1) ? __timestamp : 0; + #else + return (__timestamp != -1) ? __timestamp : lime.system.System.getTimer(); + #end + } } diff --git a/src/lime/graphics/Image.hx b/src/lime/graphics/Image.hx index 79c79ac326..5bfd568619 100644 --- a/src/lime/graphics/Image.hx +++ b/src/lime/graphics/Image.hx @@ -59,7 +59,6 @@ import format.tools.Deflate; import sys.io.File; #end #end - /** `Image` is a convenience class for working with bitmap images in Lime. @@ -395,8 +394,7 @@ class Image sourceRect.offset(sourceImage.offsetX, sourceImage.offsetY); destPoint.offset(offsetX, offsetY); - buffer.__srcBitmapData.copyChannel(sourceImage.buffer.src, sourceRect.__toFlashRectangle(), destPoint.__toFlashPoint(), srcChannel, - dstChannel); + buffer.__srcBitmapData.copyChannel(sourceImage.buffer.src, sourceRect.__toFlashRectangle(), destPoint.__toFlashPoint(), srcChannel, dstChannel); default: } diff --git a/src/lime/graphics/OpenGLES3RenderContext.hx b/src/lime/graphics/OpenGLES3RenderContext.hx index 8c0c21ae7d..2ab458e81c 100644 --- a/src/lime/graphics/OpenGLES3RenderContext.hx +++ b/src/lime/graphics/OpenGLES3RenderContext.hx @@ -9,7 +9,6 @@ import lime.graphics.opengl.*; import lime.utils.DataPointer; import lime.utils.Float32Array; import lime.utils.Int32Array; - /** The `OpenGLES3RenderContext` allows access to OpenGL ES 3.0 features when OpenGL or OpenGL ES is the render context type of the `Window`, and the current context supports diff --git a/src/lime/graphics/RenderContext.hx b/src/lime/graphics/RenderContext.hx index 4443ffee9b..d269542e76 100644 --- a/src/lime/graphics/RenderContext.hx +++ b/src/lime/graphics/RenderContext.hx @@ -86,6 +86,13 @@ class RenderContext #if (!lime_doc_gen || native || (js && html5)) public var webgl2(default, null):WebGL2RenderContext; #end + + /** + Access to the current Vulkan render API bootstrap helpers, if available + **/ + #if (!lime_doc_gen || native) + public var vulkan(default, null):VulkanRenderContext; + #end public var window(default, null):Window; @:noCompletion private function new() {} diff --git a/src/lime/graphics/RenderContextType.hx b/src/lime/graphics/RenderContextType.hx index 8dddd1aa48..6b0fa93ff7 100644 --- a/src/lime/graphics/RenderContextType.hx +++ b/src/lime/graphics/RenderContextType.hx @@ -40,6 +40,11 @@ package lime.graphics; **/ var WEBGL = "webgl"; + /** + Describes a Vulkan render context + **/ + var VULKAN = "vulkan"; + /** Describes a custom render context **/ diff --git a/src/lime/graphics/VulkanRenderContext.hx b/src/lime/graphics/VulkanRenderContext.hx new file mode 100644 index 0000000000..b9b6412056 --- /dev/null +++ b/src/lime/graphics/VulkanRenderContext.hx @@ -0,0 +1,194 @@ +package lime.graphics; + +import haxe.Int64; +import lime.graphics.vulkan.VKRenderer; +import lime.math.Vector2; +#if (!lime_doc_gen || lime_cffi) +import lime.system.CFFI; +#end +#if (!lime_doc_gen || lime_cffi) +import lime.system.CFFIPointer; +#end +#if hl +import hl.Bytes as HLBytes; +import hl.NativeArray; +#end +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +/** + The `VulkanRenderContext` exposes native Vulkan window bootstrap helpers when + Vulkan is the render context type of the current `Window`. + + This context owns the window-specific pieces of Lime's Vulkan API: + + - required instance extensions for the current window + - the current drawable size in pixels + - Vulkan surface creation for an existing `VkInstance` + - access to `vkGetInstanceProcAddr` + + Use `lime.graphics.vulkan.VK` and related classes for the broader Vulkan API + surface as it grows. +**/ +@:access(lime._internal.backend.native.NativeCFFI) +class VulkanRenderContext +{ + public var type(default, null):RenderContextType; + public var version(default, null):String; + + private var __windowHandle:#if (!lime_doc_gen || lime_cffi) CFFIPointer #else Dynamic #end; + + @:allow(lime._internal.backend.native.NativeWindow) + private function new(windowHandle:#if (!lime_doc_gen || lime_cffi) CFFIPointer #else Dynamic #end) + { + __windowHandle = windowHandle; + type = VULKAN; + version = ""; + } + + /** + Creates a Vulkan surface for the current window using an existing + `VkInstance` handle, or an object that exposes a `get()` method returning + that handle. + **/ + public function createSurface(instance:Dynamic):Int64 + { + var surfaceData:Dynamic = null; + + #if (!macro && lime_cffi) + var instanceHandle = __resolveHandle(instance); + if (instanceHandle.high != 0 || instanceHandle.low != 0) + { + surfaceData = NativeCFFI.lime_window_create_vulkan_surface(__windowHandle, instanceHandle.high, instanceHandle.low); + } + #end + + if (surfaceData != null) + { + return Int64.make(surfaceData.high, surfaceData.low); + } + + return Int64.ofInt(0); + } + + /** + Gets the current drawable size in pixels for the Vulkan surface. + **/ + public function getDrawableSize(result:Vector2 = null):Vector2 + { + if (result == null) result = new Vector2(); + + #if (!macro && lime_cffi) + var size:Dynamic = NativeCFFI.lime_window_get_vulkan_drawable_size(__windowHandle); + if (size != null) + { + result.x = size.width; + result.y = size.height; + return result; + } + #end + + result.x = 0; + result.y = 0; + return result; + } + + /** + Returns the list of Vulkan instance extensions required to create a + surface for this window. + **/ + public function getInstanceExtensions():Array + { + #if (!macro && lime_cffi) + #if hl + var bytes:NativeArray = cast NativeCFFI.lime_window_get_vulkan_instance_extensions(__windowHandle); + if (bytes != null) + { + var extensions = new Array(); + for (i in 0...bytes.length) + { + extensions[i] = CFFI.stringValue(bytes[i]); + } + return extensions; + } + #else + var extensions:Array = cast NativeCFFI.lime_window_get_vulkan_instance_extensions(__windowHandle); + if (extensions != null) + { + return extensions; + } + #end + #end + + return []; + } + + /** + Returns the native address of SDL's `vkGetInstanceProcAddr` function. + **/ + public function getInstanceProcAddr():Int64 + { + #if (!macro && lime_cffi) + var handleData:Dynamic = NativeCFFI.lime_window_get_vulkan_instance_proc_addr(__windowHandle); + if (handleData != null) + { + return Int64.make(handleData.high, handleData.low); + } + #end + + return Int64.ofInt(0); + } + + /** + Creates Lime's validation Vulkan swapchain renderer for the current window. + + This renderer exists for smoke tests and samples while the public `VK` + surface grows into the full rendering API. + The renderer respects the current Lime `vsyncMode` preference when it + chooses a swapchain present mode. + **/ + public function createRenderer(applicationName:String = "Lime"):VKRenderer + { + #if (!macro && lime_cffi) + var handle = NativeCFFI.lime_vulkan_renderer_create(__windowHandle, applicationName); + if (handle != null) + { + return new VKRenderer(handle); + } + #end + + return null; + } + + private static function __resolveHandle(value:Dynamic):Int64 + { + if (value == null) return Int64.ofInt(0); + + var high:Dynamic = Reflect.field(value, "high"); + var low:Dynamic = Reflect.field(value, "low"); + if (high != null && low != null) + { + return Int64.make(high, low); + } + + switch (Type.typeof(value)) + { + case TInt: + return Int64.ofInt(cast value); + default: + } + + var getField = Reflect.field(value, "get"); + if (getField != null) + { + try + { + return __resolveHandle(Reflect.callMethod(value, getField, [])); + } + catch (e:Dynamic) {} + } + + return Int64.ofInt(0); + } +} diff --git a/src/lime/graphics/WebGL2RenderContext.hx b/src/lime/graphics/WebGL2RenderContext.hx index 3fdc913647..802b3fa5f0 100644 --- a/src/lime/graphics/WebGL2RenderContext.hx +++ b/src/lime/graphics/WebGL2RenderContext.hx @@ -301,15 +301,14 @@ import lime.utils.UInt32Array; **/ @:access(lime.graphics.RenderContext) #if !doc_gen -@:transitive -abstract WebGL2RenderContext(OpenGLRenderContext) from OpenGLRenderContext to OpenGLRenderContext +@:transitive abstract WebGL2RenderContext(OpenGLRenderContext) from OpenGLRenderContext to OpenGLRenderContext { #else abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic { #end - private static var __tempPointer = new BytePointer(); + public var DEPTH_BUFFER_BIT(get, never):Int; public var STENCIL_BUFFER_BIT(get, never):Int; public var COLOR_BUFFER_BIT(get, never):Int; @@ -3766,10 +3765,9 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic #end { var size = (srcData != null) ? srcData.byteLength : 0; - __tempPointer.set(srcData, srcOffset); this.bufferData(target, size, __tempPointer, usage); - } + } #if !lime_webgl public inline function bufferSubData(target:Int, offset:Int, srcData:ArrayBufferView, srcOffset:Int = 0, ?length:Int):Void @@ -3778,7 +3776,6 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic #end { var size = (length != null) ? length : (srcData != null) ? srcData.byteLength : 0; - __tempPointer.set(srcData, srcOffset); this.bufferSubData(target, offset, size, __tempPointer); } @@ -3849,21 +3846,18 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic #if !lime_webgl public function compressedTexImage2D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, border:Int, srcData:ArrayBufferView, srcOffset:Int = 0, - ?srcLengthOverride:Int):Void + ?srcLengthOverride:Int):Void #else - public inline function compressedTexImage2D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, border:Int, srcData:Dynamic, - ?srcOffset:Int, - ?srcLengthOverride:Int):Void + public inline function compressedTexImage2D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, border:Int, srcData:Dynamic, ?srcOffset:Int, + ?srcLengthOverride:Int):Void #end { var imageSize = (srcLengthOverride != null) ? srcLengthOverride : (srcData != null) ? srcData.byteLength : 0; - __tempPointer.set(srcData, srcOffset); this.compressedTexImage2D(target, level, internalformat, width, height, border, imageSize, __tempPointer); } - public function compressedTexImage3D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, depth:Int, border:Int, - srcData:ArrayBufferView, + public function compressedTexImage3D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, depth:Int, border:Int, srcData:ArrayBufferView, srcOffset:Int = 0, ?srcLengthOverride:Int):Void { var imageSize = (srcLengthOverride != null) ? srcLengthOverride : (srcData != null) ? srcData.byteLength : 0; @@ -3872,23 +3866,19 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public inline function compressedTexSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Int, - srcData:ArrayBufferView, - srcOffset:Int = 0, ?srcLengthOverride:Int):Void + public inline function compressedTexSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Int, srcData:ArrayBufferView, + srcOffset:Int = 0, ?srcLengthOverride:Int):Void #else - public inline function compressedTexSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Int, - srcData:Dynamic, - ?srcOffset:Int, ?srcLengthOverride:Int):Void + public inline function compressedTexSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Int, srcData:Dynamic, + ?srcOffset:Int, ?srcLengthOverride:Int):Void #end { var imageSize = (srcLengthOverride != null) ? srcLengthOverride : (srcData != null) ? srcData.byteLength : 0; - __tempPointer.set(srcData, srcOffset); this.compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, __tempPointer); } - public inline function compressedTexSubImage3D(target:Int, level:Int, xoffset:Int, yoffset:Int, zoffset:Int, width:Int, height:Int, - depth:Int, format:Int, + public inline function compressedTexSubImage3D(target:Int, level:Int, xoffset:Int, yoffset:Int, zoffset:Int, width:Int, height:Int, depth:Int, format:Int, srcData:ArrayBufferView, srcOffset:Int = 0, ?srcLengthOverride:Int):Void { var imageSize = (srcLengthOverride != null) ? srcLengthOverride : (srcData != null) ? srcData.byteLength : 0; @@ -3911,8 +3901,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); } - public inline function copyTexSubImage3D(target:Int, level:Int, xoffset:Int, yoffset:Int, zoffset:Int, x:Int, y:Int, width:Int, - height:Int):Void + public inline function copyTexSubImage3D(target:Int, level:Int, xoffset:Int, yoffset:Int, zoffset:Int, x:Int, y:Int, width:Int, height:Int):Void { this.copyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height); } @@ -4195,7 +4184,6 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic { #if !js var size = (length != null) ? length : (dstData != null) ? dstData.length : 0; - this.getBufferSubData(target, srcByteOffset + srcOffset, size, dstData); #end } @@ -4451,8 +4439,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public inline function readPixels(x:Int, y:Int, width:Int, height:Int, format:Int, type:Int, pixels:ArrayBufferView, - dstOffset:Int = 0):Void + public inline function readPixels(x:Int, y:Int, width:Int, height:Int, format:Int, type:Int, pixels:ArrayBufferView, dstOffset:Int = 0):Void #else public inline function readPixels(x:Int, y:Int, width:Int, height:Int, format:Int, type:Int, pixels:Dynamic, ?dstOffset:Int):Void #end @@ -4532,13 +4519,13 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public inline function texImage2D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, border:Int, format:Int, - type:Int, srcData:ArrayBufferView, - srcOffset:Int = 0):Void + public inline function texImage2D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, border:Int, format:Int, type:Int, + srcData:ArrayBufferView, + srcOffset:Int = 0):Void #else - public inline function texImage2D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, border:Dynamic, ?format:Int, - ?type:Int, ?srcData:Dynamic, - ?srcOffset:Int):Void + public inline function texImage2D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, border:Dynamic, ?format:Int, ?type:Int, + ?srcData:Dynamic, + ?srcOffset:Int):Void #end { #if !lime_webgl @@ -4547,8 +4534,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic #end } - public inline function texImage3D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, depth:Int, border:Int, - format:Int, type:Int, + public inline function texImage3D(target:Int, level:Int, internalformat:Int, width:Int, height:Int, depth:Int, border:Int, format:Int, type:Int, srcData:ArrayBufferView, srcOffset:Int = 0):Void { __tempPointer.set(srcData, srcOffset); @@ -4576,21 +4562,18 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public inline function texSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Int, - type:Int, srcData:ArrayBufferView, - srcOffset:Int = 0):Void + public inline function texSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Int, type:Int, srcData:ArrayBufferView, + srcOffset:Int = 0):Void #else - public inline function texSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Dynamic, - ?type:Int, ?srcData:Dynamic, - ?srcOffset:Int):Void + public inline function texSubImage2D(target:Int, level:Int, xoffset:Int, yoffset:Int, width:Int, height:Int, format:Dynamic, ?type:Int, ?srcData:Dynamic, + ?srcOffset:Int):Void #end { __tempPointer.set(srcData, srcOffset); this.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, __tempPointer); } - public inline function texSubImage3D(target:Int, level:Int, xoffset:Int, yoffset:Int, zoffset:Int, width:Int, height:Int, - depth:Int, format:Int, type:Int, + public inline function texSubImage3D(target:Int, level:Int, xoffset:Int, yoffset:Int, zoffset:Int, width:Int, height:Int, depth:Int, format:Int, type:Int, srcData:ArrayBufferView, srcOffset:Int = 0):Void { __tempPointer.set(srcData, srcOffset); @@ -4673,8 +4656,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.uniform2ui(location, v0, v1); } - public inline function uniform2uiv(location:GLUniformLocation, v:UInt32Array, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform2uiv(location:GLUniformLocation, v:UInt32Array, ?srcOffset:Int, ?srcLength:Int):Void { this.uniform2uiv(location, v != null ? v.length >> 1 : 0, v); } @@ -4685,11 +4667,9 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public inline function uniform3fv(location:GLUniformLocation, v:Float32Array, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform3fv(location:GLUniformLocation, v:Float32Array, ?srcOffset:Int, ?srcLength:Int):Void #else - public inline function uniform3fv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform3fv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void #end { this.uniform3fv(location, v != null ? Std.int(v.length / 3) : 0, v); @@ -4701,11 +4681,9 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public inline function uniform3iv(location:GLUniformLocation, v:Int32Array, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform3iv(location:GLUniformLocation, v:Int32Array, ?srcOffset:Int, ?srcLength:Int):Void #else - public inline function uniform3iv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform3iv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void #end { this.uniform3iv(location, v != null ? Std.int(v.length / 3) : 0, v); @@ -4716,82 +4694,68 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.uniform3ui(location, v0, v1, v2); } - public inline function uniform3uiv(location:GLUniformLocation, v:UInt32Array, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform3uiv(location:GLUniformLocation, v:UInt32Array, ?srcOffset:Int, ?srcLength:Int):Void { this.uniform3uiv(location, v != null ? Std.int(v.length / 3) : 0, v); } - public inline function uniform4f(location:GLUniformLocation, v0:Float, v1:Float, v2:Float, - v3:Float):Void + public inline function uniform4f(location:GLUniformLocation, v0:Float, v1:Float, v2:Float, v3:Float):Void { this.uniform4f(location, v0, v1, v2, v3); } #if !lime_webgl - public inline function uniform4fv(location:GLUniformLocation, v:Float32Array, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform4fv(location:GLUniformLocation, v:Float32Array, ?srcOffset:Int, ?srcLength:Int):Void #else - public inline function uniform4fv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform4fv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void #end { this.uniform4fv(location, v != null ? v.length >> 2 : 0, v); } - public inline function uniform4i(location:GLUniformLocation, v0:Int, v1:Int, v2:Int, - v3:Int):Void + public inline function uniform4i(location:GLUniformLocation, v0:Int, v1:Int, v2:Int, v3:Int):Void { this.uniform4i(location, v0, v1, v2, v3); } #if !lime_webgl - public inline function uniform4iv(location:GLUniformLocation, v:Int32Array, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform4iv(location:GLUniformLocation, v:Int32Array, ?srcOffset:Int, ?srcLength:Int):Void #else - public inline function uniform4iv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, - ?srcLength:Int):Void + public inline function uniform4iv(location:GLUniformLocation, v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void #end { this.uniform4iv(location, v != null ? v.length >> 2 : 0, v); } - public inline function uniform4ui(location:GLUniformLocation, v0:Int, v1:Int, v2:Int, - v3:Int):Void + public inline function uniform4ui(location:GLUniformLocation, v0:Int, v1:Int, v2:Int, v3:Int):Void { this.uniform4ui(location, v0, v1, v2, v3); } - public inline function uniform4uiv(location:GLUniformLocation, v:UInt32Array, - ?srcOffset:Int, ?srcLength:Int):Void + public inline function uniform4uiv(location:GLUniformLocation, v:UInt32Array, ?srcOffset:Int, ?srcLength:Int):Void { this.uniform4uiv(location, v != null ? v.length >> 2 : 0, v); } - public inline function uniformBlockBinding(program:GLProgram, uniformBlockIndex:Int, - uniformBlockBinding:Int):Void + public inline function uniformBlockBinding(program:GLProgram, uniformBlockIndex:Int, uniformBlockBinding:Int):Void { this.uniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding); } #if !lime_webgl - public function uniformMatrix2fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix2fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void #else - public inline function uniformMatrix2fv(location:GLUniformLocation, transpose:Bool, - v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void + public inline function uniformMatrix2fv(location:GLUniformLocation, transpose:Bool, v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void #end { var count = 0; - if (srcLength != null) count = srcLength; else if (v != null) count = v.length >> 2; __tempPointer.set(v, srcOffset); this.uniformMatrix2fv(location, count, transpose, __tempPointer); } - public function uniformMatrix2x3fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix2x3fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void { var count = 0; if (srcLength != null) count = srcLength; @@ -4802,8 +4766,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.uniformMatrix2x3fv(location, count, transpose, __tempPointer); } - public function uniformMatrix2x4fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix2x4fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void { var count = 0; if (srcLength != null) count = srcLength; @@ -4815,23 +4778,19 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public function uniformMatrix3fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix3fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void #else - public inline function uniformMatrix3fv(location:GLUniformLocation, transpose:Bool, - v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void + public inline function uniformMatrix3fv(location:GLUniformLocation, transpose:Bool, v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void #end { var count = 0; - if (srcLength != null) count = srcLength; else if (v != null) count = Std.int(v.length / 9); __tempPointer.set(v, srcOffset); this.uniformMatrix3fv(location, count, transpose, __tempPointer); } - public function uniformMatrix3x2fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix3x2fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void { var count = 0; if (srcLength != null) count = srcLength; @@ -4842,8 +4801,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.uniformMatrix3x2fv(location, count, transpose, __tempPointer); } - public function uniformMatrix3x4fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix3x4fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void { var count = 0; if (srcLength != null) count = srcLength; @@ -4855,23 +4813,19 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic } #if !lime_webgl - public function uniformMatrix4fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix4fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void #else - public inline function uniformMatrix4fv(location:GLUniformLocation, transpose:Bool, - v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void + public inline function uniformMatrix4fv(location:GLUniformLocation, transpose:Bool, v:Dynamic, ?srcOffset:Int, ?srcLength:Int):Void #end { var count = 0; - if (srcLength != null) count = srcLength; else if (v != null) count = v.length >> 4; __tempPointer.set(v, srcOffset); this.uniformMatrix4fv(location, count, transpose, __tempPointer); } - public function uniformMatrix4x2fv(location:GLUniformLocation, - transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix4x2fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void { var count = 0; if (srcLength != null) count = srcLength; @@ -4882,8 +4836,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.uniformMatrix4x2fv(location, count, transpose, __tempPointer); } - public function uniformMatrix4x3fv(location:GLUniformLocation, transpose:Bool, - v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void + public function uniformMatrix4x3fv(location:GLUniformLocation, transpose:Bool, v:Float32Array, srcOffset:Int = 0, ?srcLength:Int):Void { var count = 0; if (srcLength != null) count = srcLength; @@ -4909,8 +4862,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.vertexAttrib1f(indx, x); } - public inline function vertexAttrib1fv(indx:Int, - values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void + public inline function vertexAttrib1fv(indx:Int, values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void { this.vertexAttrib1fv(indx, values); } @@ -4920,8 +4872,7 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.vertexAttrib2f(indx, x, y); } - public inline function vertexAttrib2fv(indx:Int, - values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void + public inline function vertexAttrib2fv(indx:Int, values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void { this.vertexAttrib2fv(indx, values); } @@ -4931,20 +4882,17 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.vertexAttrib3f(indx, x, y, z); } - public inline function vertexAttrib3fv(indx:Int, - values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void + public inline function vertexAttrib3fv(indx:Int, values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void { this.vertexAttrib3fv(indx, values); } - public inline function vertexAttrib4f(indx:Int, x:Float, y:Float, z:Float, - w:Float):Void + public inline function vertexAttrib4f(indx:Int, x:Float, y:Float, z:Float, w:Float):Void { this.vertexAttrib4f(indx, x, y, z, w); } - public inline function vertexAttrib4fv(indx:Int, - values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void + public inline function vertexAttrib4fv(indx:Int, values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void { this.vertexAttrib4fv(indx, values); } @@ -4954,38 +4902,32 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic this.vertexAttribDivisor(index, divisor); } - public inline function vertexAttribI4i(indx:Int, x:Int, y:Int, z:Int, - w:Int):Void + public inline function vertexAttribI4i(indx:Int, x:Int, y:Int, z:Int, w:Int):Void { this.vertexAttribI4i(indx, x, y, z, w); } - public inline function vertexAttribI4iv(indx:Int, - values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void + public inline function vertexAttribI4iv(indx:Int, values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void { this.vertexAttribI4iv(indx, values); } - public inline function vertexAttribI4ui(indx:Int, x:Int, y:Int, z:Int, - w:Int):Void + public inline function vertexAttribI4ui(indx:Int, x:Int, y:Int, z:Int, w:Int):Void { this.vertexAttribI4ui(indx, x, y, z, w); } - public inline function vertexAttribI4uiv(indx:Int, - values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void + public inline function vertexAttribI4uiv(indx:Int, values:#if (!lime_webgl && !doc_gen) DataPointer #else Float32Array #end):Void { this.vertexAttribI4uiv(indx, values); } - public inline function vertexAttribIPointer(index:Int, size:Int, type:Int, - stride:Int, offset:DataPointer):Void + public inline function vertexAttribIPointer(index:Int, size:Int, type:Int, stride:Int, offset:DataPointer):Void { this.vertexAttribIPointer(index, size, type, stride, offset); } - public inline function vertexAttribPointer(indx:Int, size:Int, type:Int, - normalized:Bool, stride:Int, offset:DataPointer):Void + public inline function vertexAttribPointer(indx:Int, size:Int, type:Int, normalized:Bool, stride:Int, offset:DataPointer):Void { this.vertexAttribPointer(indx, size, type, normalized, stride, offset); } @@ -5016,5 +4958,5 @@ abstract WebGL2RenderContext(Dynamic) from Dynamic to Dynamic { return cast GL.context; } -} + } #end diff --git a/src/lime/graphics/vulkan/VK.hx b/src/lime/graphics/vulkan/VK.hx new file mode 100644 index 0000000000..35f47c8f1d --- /dev/null +++ b/src/lime/graphics/vulkan/VK.hx @@ -0,0 +1,483 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +import lime.graphics.VulkanRenderContext; +#if (!lime_doc_gen || lime_cffi) +import lime.system.CFFI; +#end +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + Entry point for Lime's Vulkan API surface. + + Like `lime.graphics.opengl.GL`, this class is the public place for low-level + graphics API access. Vulkan is explicit by design, so the API is organized + around handles and lifecycle objects instead of GL-style global state. +**/ +class VK +{ + public static inline var SUCCESS = 0; + public static inline var NOT_READY = 1; + public static inline var TIMEOUT = 2; + public static inline var EVENT_SET = 3; + public static inline var EVENT_RESET = 4; + public static inline var INCOMPLETE = 5; + public static inline var SUBOPTIMAL_KHR = 1000001003; + public static inline var ERROR_INITIALIZATION_FAILED = -3; + public static inline var ERROR_OUT_OF_DATE_KHR = -1000001004; + + public static inline var KHR_SWAPCHAIN_EXTENSION_NAME = "VK_KHR_swapchain"; + + public static inline var PHYSICAL_DEVICE_TYPE_OTHER = 0; + public static inline var PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1; + public static inline var PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2; + public static inline var PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3; + public static inline var PHYSICAL_DEVICE_TYPE_CPU = 4; + + public static inline var QUEUE_GRAPHICS_BIT = 0x00000001; + public static inline var QUEUE_COMPUTE_BIT = 0x00000002; + public static inline var QUEUE_TRANSFER_BIT = 0x00000004; + public static inline var QUEUE_SPARSE_BINDING_BIT = 0x00000008; + + public static inline var COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001; + public static inline var COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002; + public static inline var COMMAND_POOL_CREATE_PROTECTED_BIT = 0x00000004; + + public static inline var COMMAND_BUFFER_LEVEL_PRIMARY = 0; + public static inline var COMMAND_BUFFER_LEVEL_SECONDARY = 1; + + public static inline var COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0x00000001; + public static inline var COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0x00000002; + public static inline var COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0x00000004; + + public static inline var COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0x00000001; + + public static inline var FENCE_CREATE_SIGNALED_BIT = 0x00000001; + + public static inline var DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001; + + public static inline var FORMAT_UNDEFINED = 0; + public static inline var FORMAT_R8_UNORM = 9; + public static inline var FORMAT_R8G8_UNORM = 16; + public static inline var FORMAT_R8G8B8A8_UNORM = 37; + public static inline var FORMAT_R8G8B8A8_SRGB = 43; + public static inline var FORMAT_B8G8R8A8_UNORM = 44; + public static inline var FORMAT_B8G8R8A8_SRGB = 50; + public static inline var FORMAT_R16G16B16A16_SFLOAT = 97; + public static inline var FORMAT_R32_SFLOAT = 100; + public static inline var FORMAT_R32G32_SFLOAT = 103; + public static inline var FORMAT_R32G32B32_SFLOAT = 106; + public static inline var FORMAT_R32G32B32A32_SFLOAT = 109; + public static inline var FORMAT_D16_UNORM = 124; + public static inline var FORMAT_X8_D24_UNORM_PACK32 = 125; + public static inline var FORMAT_D32_SFLOAT = 126; + public static inline var FORMAT_S8_UINT = 127; + public static inline var FORMAT_D24_UNORM_S8_UINT = 129; + public static inline var FORMAT_D32_SFLOAT_S8_UINT = 130; + + public static inline var COLOR_SPACE_SRGB_NONLINEAR_KHR = 0; + + public static inline var PRESENT_MODE_IMMEDIATE_KHR = 0; + public static inline var PRESENT_MODE_MAILBOX_KHR = 1; + public static inline var PRESENT_MODE_FIFO_KHR = 2; + public static inline var PRESENT_MODE_FIFO_RELAXED_KHR = 3; + + public static inline var BUFFER_USAGE_TRANSFER_SRC_BIT = 0x00000001; + public static inline var BUFFER_USAGE_TRANSFER_DST_BIT = 0x00000002; + public static inline var BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000004; + public static inline var BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT = 0x00000008; + public static inline var BUFFER_USAGE_UNIFORM_BUFFER_BIT = 0x00000010; + public static inline var BUFFER_USAGE_STORAGE_BUFFER_BIT = 0x00000020; + public static inline var BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040; + public static inline var BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080; + public static inline var BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100; + + public static inline var MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001; + public static inline var MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002; + public static inline var MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004; + public static inline var MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008; + public static inline var MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010; + + public static inline var IMAGE_TYPE_1D = 0; + public static inline var IMAGE_TYPE_2D = 1; + public static inline var IMAGE_TYPE_3D = 2; + + public static inline var IMAGE_TILING_OPTIMAL = 0; + public static inline var IMAGE_TILING_LINEAR = 1; + + public static inline var IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001; + public static inline var IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002; + public static inline var IMAGE_USAGE_SAMPLED_BIT = 0x00000004; + public static inline var IMAGE_USAGE_STORAGE_BIT = 0x00000008; + public static inline var IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010; + public static inline var IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020; + public static inline var IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040; + public static inline var IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080; + + public static inline var IMAGE_ASPECT_COLOR_BIT = 0x00000001; + public static inline var IMAGE_ASPECT_DEPTH_BIT = 0x00000002; + public static inline var IMAGE_ASPECT_STENCIL_BIT = 0x00000004; + public static inline var IMAGE_ASPECT_METADATA_BIT = 0x00000008; + + public static inline var COLOR_COMPONENT_R_BIT = 0x00000001; + public static inline var COLOR_COMPONENT_G_BIT = 0x00000002; + public static inline var COLOR_COMPONENT_B_BIT = 0x00000004; + public static inline var COLOR_COMPONENT_A_BIT = 0x00000008; + public static inline var COLOR_COMPONENT_RGBA_BITS = COLOR_COMPONENT_R_BIT | COLOR_COMPONENT_G_BIT | COLOR_COMPONENT_B_BIT | COLOR_COMPONENT_A_BIT; + + public static inline var IMAGE_LAYOUT_UNDEFINED = 0; + public static inline var IMAGE_LAYOUT_GENERAL = 1; + public static inline var IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2; + public static inline var IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3; + public static inline var IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4; + public static inline var IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5; + public static inline var IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6; + public static inline var IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7; + public static inline var IMAGE_LAYOUT_PREINITIALIZED = 8; + public static inline var IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002; + + public static inline var IMAGE_VIEW_TYPE_1D = 0; + public static inline var IMAGE_VIEW_TYPE_2D = 1; + public static inline var IMAGE_VIEW_TYPE_3D = 2; + public static inline var IMAGE_VIEW_TYPE_CUBE = 3; + public static inline var IMAGE_VIEW_TYPE_1D_ARRAY = 4; + public static inline var IMAGE_VIEW_TYPE_2D_ARRAY = 5; + public static inline var IMAGE_VIEW_TYPE_CUBE_ARRAY = 6; + + public static inline var PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x00000001; + public static inline var PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0x00000002; + public static inline var PIPELINE_STAGE_VERTEX_INPUT_BIT = 0x00000004; + public static inline var PIPELINE_STAGE_VERTEX_SHADER_BIT = 0x00000008; + public static inline var PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0x00000080; + public static inline var PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0x00000100; + public static inline var PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0x00000200; + public static inline var PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400; + public static inline var PIPELINE_STAGE_TRANSFER_BIT = 0x00001000; + public static inline var PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = 0x00002000; + public static inline var PIPELINE_STAGE_HOST_BIT = 0x00004000; + public static inline var PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000; + public static inline var PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000; + + public static inline var ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001; + public static inline var ACCESS_INDEX_READ_BIT = 0x00000002; + public static inline var ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004; + public static inline var ACCESS_UNIFORM_READ_BIT = 0x00000008; + public static inline var ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010; + public static inline var ACCESS_SHADER_READ_BIT = 0x00000020; + public static inline var ACCESS_SHADER_WRITE_BIT = 0x00000040; + public static inline var ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080; + public static inline var ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100; + public static inline var ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200; + public static inline var ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400; + public static inline var ACCESS_TRANSFER_READ_BIT = 0x00000800; + public static inline var ACCESS_TRANSFER_WRITE_BIT = 0x00001000; + public static inline var ACCESS_HOST_READ_BIT = 0x00002000; + public static inline var ACCESS_HOST_WRITE_BIT = 0x00004000; + public static inline var ACCESS_MEMORY_READ_BIT = 0x00008000; + public static inline var ACCESS_MEMORY_WRITE_BIT = 0x00010000; + + public static inline var SHADER_STAGE_VERTEX_BIT = 0x00000001; + public static inline var SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0x00000002; + public static inline var SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004; + public static inline var SHADER_STAGE_GEOMETRY_BIT = 0x00000008; + public static inline var SHADER_STAGE_FRAGMENT_BIT = 0x00000010; + public static inline var SHADER_STAGE_COMPUTE_BIT = 0x00000020; + public static inline var SHADER_STAGE_ALL_GRAPHICS = 0x0000001F; + public static inline var SHADER_STAGE_ALL = 0x7FFFFFFF; + + public static inline var DESCRIPTOR_TYPE_SAMPLER = 0; + public static inline var DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1; + public static inline var DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2; + public static inline var DESCRIPTOR_TYPE_STORAGE_IMAGE = 3; + public static inline var DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4; + public static inline var DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5; + public static inline var DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6; + public static inline var DESCRIPTOR_TYPE_STORAGE_BUFFER = 7; + public static inline var DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8; + public static inline var DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9; + public static inline var DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10; + + public static inline var PRIMITIVE_TOPOLOGY_POINT_LIST = 0; + public static inline var PRIMITIVE_TOPOLOGY_LINE_LIST = 1; + public static inline var PRIMITIVE_TOPOLOGY_LINE_STRIP = 2; + public static inline var PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3; + public static inline var PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4; + public static inline var PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5; + + public static inline var POLYGON_MODE_FILL = 0; + public static inline var POLYGON_MODE_LINE = 1; + public static inline var POLYGON_MODE_POINT = 2; + + public static inline var CULL_MODE_NONE = 0; + public static inline var CULL_MODE_FRONT_BIT = 0x00000001; + public static inline var CULL_MODE_BACK_BIT = 0x00000002; + public static inline var CULL_MODE_FRONT_AND_BACK = 0x00000003; + + public static inline var FRONT_FACE_COUNTER_CLOCKWISE = 0; + public static inline var FRONT_FACE_CLOCKWISE = 1; + + public static inline var COMPARE_OP_NEVER = 0; + public static inline var COMPARE_OP_LESS = 1; + public static inline var COMPARE_OP_EQUAL = 2; + public static inline var COMPARE_OP_LESS_OR_EQUAL = 3; + public static inline var COMPARE_OP_GREATER = 4; + public static inline var COMPARE_OP_NOT_EQUAL = 5; + public static inline var COMPARE_OP_GREATER_OR_EQUAL = 6; + public static inline var COMPARE_OP_ALWAYS = 7; + + public static inline var STENCIL_OP_KEEP = 0; + public static inline var STENCIL_OP_ZERO = 1; + public static inline var STENCIL_OP_REPLACE = 2; + public static inline var STENCIL_OP_INCREMENT_AND_CLAMP = 3; + public static inline var STENCIL_OP_DECREMENT_AND_CLAMP = 4; + public static inline var STENCIL_OP_INVERT = 5; + public static inline var STENCIL_OP_INCREMENT_AND_WRAP = 6; + public static inline var STENCIL_OP_DECREMENT_AND_WRAP = 7; + + public static inline var BLEND_FACTOR_ZERO = 0; + public static inline var BLEND_FACTOR_ONE = 1; + public static inline var BLEND_FACTOR_SRC_COLOR = 2; + public static inline var BLEND_FACTOR_ONE_MINUS_SRC_COLOR = 3; + public static inline var BLEND_FACTOR_DST_COLOR = 4; + public static inline var BLEND_FACTOR_ONE_MINUS_DST_COLOR = 5; + public static inline var BLEND_FACTOR_SRC_ALPHA = 6; + public static inline var BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = 7; + public static inline var BLEND_FACTOR_DST_ALPHA = 8; + public static inline var BLEND_FACTOR_ONE_MINUS_DST_ALPHA = 9; + public static inline var BLEND_FACTOR_CONSTANT_COLOR = 10; + public static inline var BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR = 11; + public static inline var BLEND_FACTOR_CONSTANT_ALPHA = 12; + public static inline var BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA = 13; + public static inline var BLEND_FACTOR_SRC_ALPHA_SATURATE = 14; + + public static inline var BLEND_OP_ADD = 0; + public static inline var BLEND_OP_SUBTRACT = 1; + public static inline var BLEND_OP_REVERSE_SUBTRACT = 2; + public static inline var BLEND_OP_MIN = 3; + public static inline var BLEND_OP_MAX = 4; + + public static inline var DYNAMIC_STATE_VIEWPORT = 0; + public static inline var DYNAMIC_STATE_SCISSOR = 1; + public static inline var DYNAMIC_STATE_LINE_WIDTH = 2; + public static inline var DYNAMIC_STATE_DEPTH_BIAS = 3; + public static inline var DYNAMIC_STATE_BLEND_CONSTANTS = 4; + public static inline var DYNAMIC_STATE_DEPTH_BOUNDS = 5; + public static inline var DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6; + public static inline var DYNAMIC_STATE_STENCIL_WRITE_MASK = 7; + public static inline var DYNAMIC_STATE_STENCIL_REFERENCE = 8; + public static inline var DYNAMIC_STATE_VIEWPORT_BIT = 0x00000001; + public static inline var DYNAMIC_STATE_SCISSOR_BIT = 0x00000002; + + public static inline var SAMPLE_COUNT_1_BIT = 0x00000001; + public static inline var SAMPLE_COUNT_2_BIT = 0x00000002; + public static inline var SAMPLE_COUNT_4_BIT = 0x00000004; + public static inline var SAMPLE_COUNT_8_BIT = 0x00000008; + public static inline var SAMPLE_COUNT_16_BIT = 0x00000010; + public static inline var SAMPLE_COUNT_32_BIT = 0x00000020; + public static inline var SAMPLE_COUNT_64_BIT = 0x00000040; + + public static inline var INDEX_TYPE_UINT16 = 0; + public static inline var INDEX_TYPE_UINT32 = 1; + public static inline var INDEX_TYPE_UINT8_KHR = 1000265000; + + public static inline var ATTACHMENT_LOAD_OP_LOAD = 0; + public static inline var ATTACHMENT_LOAD_OP_CLEAR = 1; + public static inline var ATTACHMENT_LOAD_OP_DONT_CARE = 2; + public static inline var ATTACHMENT_STORE_OP_STORE = 0; + public static inline var ATTACHMENT_STORE_OP_DONT_CARE = 1; + + public static inline var FILTER_NEAREST = 0; + public static inline var FILTER_LINEAR = 1; + public static inline var SAMPLER_MIPMAP_MODE_NEAREST = 0; + public static inline var SAMPLER_MIPMAP_MODE_LINEAR = 1; + public static inline var SAMPLER_ADDRESS_MODE_REPEAT = 0; + public static inline var SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1; + public static inline var SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2; + public static inline var SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3; + + public static inline var PIPELINE_BIND_POINT_GRAPHICS = 0; + public static inline var SUBPASS_CONTENTS_INLINE = 0; + public static inline var SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1; + public static inline var VERTEX_INPUT_RATE_VERTEX = 0; + public static inline var VERTEX_INPUT_RATE_INSTANCE = 1; + + /** + Creates a managed `VkInstance` for the current Lime Vulkan window. + **/ + public static function createInstance(context:VulkanRenderContext, applicationName:String = "Lime"):VKInstance + { + if (context == null) + { + return null; + } + + #if (!macro && lime_cffi) + var handleData:Dynamic = NativeCFFI.lime_vk_create_instance(context.__windowHandle, applicationName); + if (handleData != null) + { + var handle = __makeHandle(handleData); + if (!__isZero(handle)) + { + return new VKInstance(context, handle); + } + } + #end + + return null; + } + + /** + Returns the last bootstrap-layer Vulkan error surfaced by Lime. + **/ + public static function getLastError():String + { + #if (!macro && lime_cffi) + var value:Dynamic = NativeCFFI.lime_vk_get_last_error(); + if (value != null) + { + return CFFI.stringValue(value); + } + #end + + return ""; + } + + /** + Picks a preferred physical device from an enumerated device list. + This currently prefers graphics-capable devices, optionally requiring + present support, and favors discrete GPUs by default. + **/ + public static function pickPhysicalDevice(devices:Array, requirePresent:Bool = false, preferDiscrete:Bool = true):VKPhysicalDevice + { + if (devices == null || devices.length == 0) + { + return null; + } + + var bestDevice:VKPhysicalDevice = null; + var bestScore = -1; + + for (device in devices) + { + var score = __scorePhysicalDevice(device, requirePresent, preferDiscrete); + if (score > bestScore) + { + bestScore = score; + bestDevice = device; + } + } + + return bestDevice; + } + + public static inline function versionString(version:Int):String + { + var major = version >>> 22; + var minor = (version >>> 12) & 0x3FF; + var patch = version & 0xFFF; + return major + "." + minor + "." + patch; + } + + @:allow(lime.graphics.VulkanRenderContext) + @:allow(lime.graphics.vulkan.VKBuffer) + @:allow(lime.graphics.vulkan.VKCommandBuffer) + @:allow(lime.graphics.vulkan.VKCommandPool) + @:allow(lime.graphics.vulkan.VKDescriptorPool) + @:allow(lime.graphics.vulkan.VKDescriptorSet) + @:allow(lime.graphics.vulkan.VKDescriptorSetLayout) + @:allow(lime.graphics.vulkan.VKDevice) + @:allow(lime.graphics.vulkan.VKDeviceMemory) + @:allow(lime.graphics.vulkan.VKFence) + @:allow(lime.graphics.vulkan.VKFramebuffer) + @:allow(lime.graphics.vulkan.VKImage) + @:allow(lime.graphics.vulkan.VKImageView) + @:allow(lime.graphics.vulkan.VKInstance) + @:allow(lime.graphics.vulkan.VKMemoryRequirements) + @:allow(lime.graphics.vulkan.VKPhysicalDevice) + @:allow(lime.graphics.vulkan.VKPipeline) + @:allow(lime.graphics.vulkan.VKPipelineCache) + @:allow(lime.graphics.vulkan.VKPipelineLayout) + @:allow(lime.graphics.vulkan.VKQueue) + @:allow(lime.graphics.vulkan.VKRenderPass) + @:allow(lime.graphics.vulkan.VKSampler) + @:allow(lime.graphics.vulkan.VKSemaphore) + @:allow(lime.graphics.vulkan.VKShaderModule) + @:allow(lime.graphics.vulkan.VKSwapchain) + private static function __makeHandle(value:Dynamic):Int64 + { + if (value == null) + { + return Int64.ofInt(0); + } + + return Int64.make(value.high, value.low); + } + + @:allow(lime.graphics.VulkanRenderContext) + @:allow(lime.graphics.vulkan.VKBuffer) + @:allow(lime.graphics.vulkan.VKCommandBuffer) + @:allow(lime.graphics.vulkan.VKCommandPool) + @:allow(lime.graphics.vulkan.VKDescriptorPool) + @:allow(lime.graphics.vulkan.VKDescriptorSet) + @:allow(lime.graphics.vulkan.VKDescriptorSetLayout) + @:allow(lime.graphics.vulkan.VKDevice) + @:allow(lime.graphics.vulkan.VKDeviceMemory) + @:allow(lime.graphics.vulkan.VKFence) + @:allow(lime.graphics.vulkan.VKFramebuffer) + @:allow(lime.graphics.vulkan.VKImage) + @:allow(lime.graphics.vulkan.VKImageView) + @:allow(lime.graphics.vulkan.VKInstance) + @:allow(lime.graphics.vulkan.VKMemoryRequirements) + @:allow(lime.graphics.vulkan.VKQueue) + @:allow(lime.graphics.vulkan.VKPipeline) + @:allow(lime.graphics.vulkan.VKPipelineCache) + @:allow(lime.graphics.vulkan.VKPipelineLayout) + @:allow(lime.graphics.vulkan.VKRenderPass) + @:allow(lime.graphics.vulkan.VKSampler) + @:allow(lime.graphics.vulkan.VKSemaphore) + @:allow(lime.graphics.vulkan.VKShaderModule) + @:allow(lime.graphics.vulkan.VKSwapchain) + private static inline function __isZero(handle:Int64):Bool + { + return handle.high == 0 && handle.low == 0; + } + + private static function __scorePhysicalDevice(device:VKPhysicalDevice, requirePresent:Bool, preferDiscrete:Bool):Int + { + if (device == null || !device.hasQueueFamily(true, requirePresent)) + { + return -1; + } + + var score = 0; + + switch (device.deviceType) + { + case PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: + score += preferDiscrete ? 400 : 250; + case PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: + score += preferDiscrete ? 300 : 400; + case PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: + score += 150; + case PHYSICAL_DEVICE_TYPE_CPU: + score += 100; + default: + score += 50; + } + + var primaryQueue = device.getQueueFamily(true, requirePresent); + if (primaryQueue != null) + { + score += primaryQueue.queueCount * 2; + if (primaryQueue.supportsTransfer) score += 4; + if (primaryQueue.supportsCompute) score += 2; + } + + score += device.queueFamilies.length; + return score; + } +} diff --git a/src/lime/graphics/vulkan/VKAcquireResult.hx b/src/lime/graphics/vulkan/VKAcquireResult.hx new file mode 100644 index 0000000000..60b269426d --- /dev/null +++ b/src/lime/graphics/vulkan/VKAcquireResult.hx @@ -0,0 +1,22 @@ +package lime.graphics.vulkan; + +/** + Result metadata from `vkAcquireNextImageKHR`. +**/ +class VKAcquireResult +{ + public var imageIndex(default, null):Int; + public var result(default, null):Int; + + @:allow(lime.graphics.vulkan.VKSwapchain) + private function new(result:Int, imageIndex:Int) + { + this.result = result; + this.imageIndex = imageIndex; + } + + public inline function isSuccess():Bool + { + return result == VK.SUCCESS || result == VK.SUBOPTIMAL_KHR; + } +} diff --git a/src/lime/graphics/vulkan/VKBuffer.hx b/src/lime/graphics/vulkan/VKBuffer.hx new file mode 100644 index 0000000000..c87157323e --- /dev/null +++ b/src/lime/graphics/vulkan/VKBuffer.hx @@ -0,0 +1,155 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +import haxe.io.Bytes; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan buffer usable for vertex, index, uniform, staging, or storage data. +**/ +class VKBuffer +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + public var memory(default, null):VKDeviceMemory; + public var size(default, null):Int64; + public var usage(default, null):Int; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64, size:Int64, usage:Int) + { + this.device = device; + this.handle = handle; + this.size = size; + this.usage = usage; + } + + public function allocateMemory(properties:Int):VKDeviceMemory + { + if (device == null) + { + return null; + } + + var allocated = device.allocateMemory(getMemoryRequirements(), properties); + if (allocated != null && bindMemory(allocated)) + { + memory = allocated; + return allocated; + } + + if (allocated != null) + { + allocated.dispose(); + } + return null; + } + + public function bindMemory(memory:VKDeviceMemory, offset:Int64 = null):Bool + { + if (offset == null) + { + offset = Int64.ofInt(0); + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && memory != null && memory.isValid()) + { + var result = NativeCFFI.lime_vk_bind_buffer_memory(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, memory.handle.high, memory.handle.low, + offset.high, offset.low); + if (result) + { + this.memory = memory; + } + return result; + } + #end + + return false; + } + + public function dispose(destroyMemory:Bool = false):Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_buffer(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + + if (destroyMemory && memory != null) + { + memory.dispose(); + memory = null; + } + } + + public inline function get():Int64 + { + return handle; + } + + public function getMemoryRequirements():VKMemoryRequirements + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_get_buffer_memory_requirements(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low); + return VKMemoryRequirements.fromDynamic(data); + } + #end + + return null; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + public function map(offset:Int64 = null, size:Int64 = null, flags:Int = 0):Bool + { + return memory != null && memory.map(offset, size, flags); + } + + public function unmap():Void + { + if (memory != null) + { + memory.unmap(); + } + } + + public function writeBytes(bytes:Bytes, srcOffset:Int = 0, length:Int = -1, dstOffset:Int64 = null):Bool + { + return memory != null && memory.writeBytes(bytes, srcOffset, length, dstOffset); + } + + public function flush(offset:Int64 = null, size:Int64 = null):Bool + { + return memory != null && memory.flush(offset, size); + } + + public function invalidate(offset:Int64 = null, size:Int64 = null):Bool + { + return memory != null && memory.invalidate(offset, size); + } + + public function upload(bytes:Bytes, memoryOffset:Int64 = null, byteOffset:Int = 0, byteLength:Int = -1):Bool + { + return memory != null && memory.upload(bytes, memoryOffset, byteOffset, byteLength); + } + + public function download(bytes:Bytes, memoryOffset:Int64 = null, byteOffset:Int = 0, byteLength:Int = -1):Bool + { + return memory != null && memory.download(bytes, memoryOffset, byteOffset, byteLength); + } +} diff --git a/src/lime/graphics/vulkan/VKCommandBuffer.hx b/src/lime/graphics/vulkan/VKCommandBuffer.hx new file mode 100644 index 0000000000..01ba3250ca --- /dev/null +++ b/src/lime/graphics/vulkan/VKCommandBuffer.hx @@ -0,0 +1,569 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan command buffer allocated from a `VKCommandPool`. +**/ +class VKCommandBuffer +{ + public var device(get, never):VKDevice; + public var handle(default, null):Int64; + public var level(default, null):Int; + public var pool(default, null):VKCommandPool; + + @:allow(lime.graphics.vulkan.VKCommandPool) + private function new(pool:VKCommandPool, handle:Int64, level:Int) + { + this.pool = pool; + this.handle = handle; + this.level = level; + } + + public function begin(flags:Int = 0):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && pool != null && pool.device != null && pool.device.isValid()) + { + return NativeCFFI.lime_vk_begin_command_buffer(pool.device.instance.context.__windowHandle, pool.device.instance.handle.high, + pool.device.instance.handle.low, pool.device.handle.high, pool.device.handle.low, handle.high, handle.low, flags); + } + #end + + return false; + } + + public function dispose():Void + { + if (pool != null) + { + pool.free(this); + } + } + + public function beginRenderPass(renderPass:VKRenderPass, framebuffer:VKFramebuffer, width:Int, height:Int, clearRed:Float = 0, clearGreen:Float = 0, + clearBlue:Float = 0, clearAlpha:Float = 1, clearDepth:Float = 1, clearStencil:Int = 0, x:Int = 0, y:Int = 0):Bool + { + var clearValueCount = renderPass != null && renderPass.depthStencilFormat != VK.FORMAT_UNDEFINED ? 2 : 1; + var state = [x, y, width, height, clearStencil, clearValueCount]; + var clear = [clearRed, clearGreen, clearBlue, clearAlpha, clearDepth]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && renderPass != null && renderPass.isValid() && framebuffer != null && framebuffer.isValid()) + { + return NativeCFFI.lime_vk_cmd_begin_render_pass(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, renderPass.handle.high, renderPass.handle.low, framebuffer.handle.high, + framebuffer.handle.low, state, clear); + } + #end + + return false; + } + + public function bindDescriptorSet(layout:VKPipelineLayout, descriptorSet:VKDescriptorSet, firstSet:Int = 0, + bindPoint:Int = VK.PIPELINE_BIND_POINT_GRAPHICS, dynamicOffsets:Array = null):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && layout != null && layout.isValid() && descriptorSet != null && descriptorSet.isValid()) + { + if (dynamicOffsets != null && dynamicOffsets.length > 0) + { + var state = [bindPoint, firstSet, dynamicOffsets.length]; + for (offset in dynamicOffsets) + { + state.push(offset); + } + return NativeCFFI.lime_vk_cmd_bind_descriptor_set_ex(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, layout.handle.high, layout.handle.low, + descriptorSet.handle.high, descriptorSet.handle.low, state); + } + + return NativeCFFI.lime_vk_cmd_bind_descriptor_set(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, layout.handle.high, layout.handle.low, descriptorSet.handle.high, + descriptorSet.handle.low, bindPoint, firstSet); + } + #end + + return false; + } + + public function bindDescriptorSetDynamicOffset(layout:VKPipelineLayout, descriptorSet:VKDescriptorSet, dynamicOffset:Int, firstSet:Int = 0, + bindPoint:Int = VK.PIPELINE_BIND_POINT_GRAPHICS):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && layout != null && layout.isValid() && descriptorSet != null && descriptorSet.isValid()) + { + return NativeCFFI.lime_vk_cmd_bind_descriptor_set_dynamic_offset(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, layout.handle.high, layout.handle.low, + descriptorSet.handle.high, descriptorSet.handle.low, dynamicOffset, firstSet, bindPoint); + } + #end + + return false; + } + + public function bindIndexBuffer(buffer:VKBuffer, offset:Int64 = null, indexType:Int = VK.INDEX_TYPE_UINT16):Bool + { + if (offset == null) + { + offset = Int64.ofInt(0); + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid()) + { + return NativeCFFI.lime_vk_cmd_bind_index_buffer(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, offset.high, offset.low, indexType); + } + #end + + return false; + } + + public function bindPipeline(pipeline:VKPipeline, bindPoint:Int = VK.PIPELINE_BIND_POINT_GRAPHICS):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && pipeline != null && pipeline.isValid()) + { + return NativeCFFI.lime_vk_cmd_bind_pipeline(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, pipeline.handle.high, pipeline.handle.low, bindPoint); + } + #end + + return false; + } + + public function bindVertexBuffer(buffer:VKBuffer, binding:Int = 0, offset:Int64 = null):Bool + { + if (offset == null) + { + offset = Int64.ofInt(0); + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid()) + { + return NativeCFFI.lime_vk_cmd_bind_vertex_buffer(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, binding, offset.high, offset.low); + } + #end + + return false; + } + + public function blitImage(source:VKImage, destination:VKImage, width:Int, height:Int, sourceLayout:Int = VK.IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + destinationLayout:Int = VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, filter:Int = VK.FILTER_LINEAR):Bool + { + return blitImageRegion(source, destination, width, height, sourceLayout, destinationLayout, filter); + } + + public function blitImageRegion(source:VKImage, destination:VKImage, sourceWidth:Int, sourceHeight:Int, + sourceLayout:Int = VK.IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, destinationLayout:Int = VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + filter:Int = VK.FILTER_LINEAR, destinationWidth:Int = -1, destinationHeight:Int = -1, sourceX:Int = 0, sourceY:Int = 0, sourceZ:Int = 0, + destinationX:Int = 0, destinationY:Int = 0, destinationZ:Int = 0, sourceDepth:Int = 1, destinationDepth:Int = 1, sourceMipLevel:Int = 0, + destinationMipLevel:Int = 0, sourceBaseArrayLayer:Int = 0, destinationBaseArrayLayer:Int = 0, layerCount:Int = 1, + aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT):Bool + { + if (destinationWidth < 0) destinationWidth = sourceWidth; + if (destinationHeight < 0) destinationHeight = sourceHeight; + var state = [ + sourceX, + sourceY, + sourceZ, + sourceX + sourceWidth, + sourceY + sourceHeight, + sourceZ + sourceDepth, + destinationX, + destinationY, + destinationZ, + destinationX + destinationWidth, + destinationY + destinationHeight, + destinationZ + destinationDepth, + sourceLayout, + destinationLayout, + filter, + sourceMipLevel, + destinationMipLevel, + sourceBaseArrayLayer, + destinationBaseArrayLayer, + layerCount, + aspectMask + ]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && source != null && source.isValid() && destination != null && destination.isValid()) + { + return NativeCFFI.lime_vk_cmd_blit_image(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, source.handle.high, source.handle.low, destination.handle.high, + destination.handle.low, state); + } + #end + + return false; + } + + public function clearColorImage(image:VKImage, layout:Int, red:Float, green:Float, blue:Float, alpha:Float, aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && image != null && image.isValid()) + { + return NativeCFFI.lime_vk_cmd_clear_color_image(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, image.handle.high, image.handle.low, layout, aspectMask, + [red, green, blue, alpha]); + } + #end + + return false; + } + + public function clearDepthStencilImage(image:VKImage, layout:Int, depth:Float = 1, stencil:Int = 0, + aspectMask:Int = VK.IMAGE_ASPECT_DEPTH_BIT | VK.IMAGE_ASPECT_STENCIL_BIT, baseMipLevel:Int = 0, levelCount:Int = 1, baseArrayLayer:Int = 0, + layerCount:Int = 1):Bool + { + var state = [ + layout, + stencil, + aspectMask, + baseMipLevel, + levelCount, + baseArrayLayer, + layerCount + ]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && image != null && image.isValid()) + { + return NativeCFFI.lime_vk_cmd_clear_depth_stencil_image(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, image.handle.high, image.handle.low, state, + [depth]); + } + #end + + return false; + } + + public function clearAttachments(color:Bool, depth:Bool, stencil:Bool, x:Int, y:Int, width:Int, height:Int, red:Float = 0, green:Float = 0, + blue:Float = 0, alpha:Float = 0, depthValue:Float = 1, stencilValue:Int = 0):Bool + { + var state = [color ? 1 : 0, depth ? 1 : 0, stencil ? 1 : 0, x, y, width, height, stencilValue]; + var clear = [red, green, blue, alpha, depthValue]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_cmd_clear_attachments(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, state, clear); + } + #end + + return false; + } + + public function copyBuffer(source:VKBuffer, destination:VKBuffer, size:Int64, sourceOffset:Int64 = null, destinationOffset:Int64 = null):Bool + { + if (sourceOffset == null) sourceOffset = Int64.ofInt(0); + if (destinationOffset == null) destinationOffset = Int64.ofInt(0); + var state = [ + size.high, + size.low, + sourceOffset.high, + sourceOffset.low, + destinationOffset.high, + destinationOffset.low + ]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && source != null && source.isValid() && destination != null && destination.isValid()) + { + return NativeCFFI.lime_vk_cmd_copy_buffer(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, source.handle.high, source.handle.low, destination.handle.high, + destination.handle.low, state); + } + #end + + return false; + } + + public function copyBufferToImage(buffer:VKBuffer, image:VKImage, width:Int, height:Int, layout:Int = VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL):Bool + { + return copyBufferToImageRegion(buffer, image, width, height, layout); + } + + public function copyBufferToImageRegion(buffer:VKBuffer, image:VKImage, width:Int, height:Int, layout:Int = VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + depth:Int = 1, bufferOffset:Int64 = null, bufferRowLength:Int = 0, bufferImageHeight:Int = 0, imageX:Int = 0, imageY:Int = 0, imageZ:Int = 0, + mipLevel:Int = 0, baseArrayLayer:Int = 0, layerCount:Int = 1, aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT):Bool + { + if (bufferOffset == null) bufferOffset = Int64.ofInt(0); + var state = [ + width, + height, + depth, + layout, + bufferOffset.high, + bufferOffset.low, + bufferRowLength, + bufferImageHeight, + imageX, + imageY, + imageZ, + mipLevel, + baseArrayLayer, + layerCount, + aspectMask + ]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() + && device != null + && device.isValid() + && buffer != null + && buffer.isValid() + && image != null + && image.isValid()) + { + return NativeCFFI.lime_vk_cmd_copy_buffer_to_image_region(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, + image.handle.high, image.handle.low, state); + } + #end + + return false; + } + + public function copyImageToBufferRegion(image:VKImage, buffer:VKBuffer, width:Int, height:Int, layout:Int = VK.IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + depth:Int = 1, bufferOffset:Int64 = null, bufferRowLength:Int = 0, bufferImageHeight:Int = 0, imageX:Int = 0, imageY:Int = 0, imageZ:Int = 0, + mipLevel:Int = 0, baseArrayLayer:Int = 0, layerCount:Int = 1, aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT):Bool + { + if (bufferOffset == null) bufferOffset = Int64.ofInt(0); + var state = [ + width, + height, + depth, + layout, + bufferOffset.high, + bufferOffset.low, + bufferRowLength, + bufferImageHeight, + imageX, + imageY, + imageZ, + mipLevel, + baseArrayLayer, + layerCount, + aspectMask + ]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() + && device != null + && device.isValid() + && image != null + && image.isValid() + && buffer != null + && buffer.isValid()) + { + return NativeCFFI.lime_vk_cmd_copy_image_to_buffer_region(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, image.handle.high, image.handle.low, + buffer.handle.high, buffer.handle.low, state); + } + #end + + return false; + } + + public function draw(vertexCount:Int, instanceCount:Int = 1, firstVertex:Int = 0, firstInstance:Int = 0):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_cmd_draw(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, vertexCount, instanceCount, firstVertex, firstInstance); + } + #end + + return false; + } + + public function drawIndexed(indexCount:Int, instanceCount:Int = 1, firstIndex:Int = 0, vertexOffset:Int = 0, firstInstance:Int = 0):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_cmd_draw_indexed(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); + } + #end + + return false; + } + + public function drawIndirect(buffer:VKBuffer, offset:Int64, drawCount:Int, stride:Int):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid()) + { + return NativeCFFI.lime_vk_cmd_draw_indirect(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, offset.high, offset.low, drawCount, + stride); + } + #end + + return false; + } + + public function drawIndexedIndirect(buffer:VKBuffer, offset:Int64, drawCount:Int, stride:Int):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid()) + { + return NativeCFFI.lime_vk_cmd_draw_indexed_indirect(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, buffer.handle.high, buffer.handle.low, + offset.high, offset.low, drawCount, stride); + } + #end + + return false; + } + + public function end():Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && pool != null && pool.device != null && pool.device.isValid()) + { + return NativeCFFI.lime_vk_end_command_buffer(pool.device.instance.context.__windowHandle, pool.device.instance.handle.high, + pool.device.instance.handle.low, pool.device.handle.high, pool.device.handle.low, handle.high, handle.low); + } + #end + + return false; + } + + public function endRenderPass():Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_cmd_end_render_pass(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + } + #end + + return false; + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + public function reset(flags:Int = 0):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && pool != null && pool.device != null && pool.device.isValid()) + { + return NativeCFFI.lime_vk_reset_command_buffer(pool.device.instance.context.__windowHandle, pool.device.instance.handle.high, + pool.device.instance.handle.low, pool.device.handle.high, pool.device.handle.low, handle.high, handle.low, flags); + } + #end + + return false; + } + + public function pipelineBarrierImage(image:VKImage, oldLayout:Int, newLayout:Int, srcStageMask:Int, dstStageMask:Int, srcAccessMask:Int, + dstAccessMask:Int, aspectMask:Int, baseMipLevel:Int = 0, levelCount:Int = 1, baseArrayLayer:Int = 0, layerCount:Int = 1):Bool + { + var state = [ + oldLayout, + newLayout, + srcStageMask, + dstStageMask, + srcAccessMask, + dstAccessMask, + aspectMask, + baseMipLevel, + levelCount, + baseArrayLayer, + layerCount + ]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && image != null && image.isValid()) + { + return NativeCFFI.lime_vk_cmd_pipeline_barrier_image(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, image.handle.high, image.handle.low, state); + } + #end + + return false; + } + + public function pushConstants(layout:VKPipelineLayout, stageFlags:Int, bytes:haxe.io.Bytes, offset:Int = 0, byteOffset:Int = 0, byteLength:Int = -1):Bool + { + if (bytes == null || layout == null) + { + return false; + } + if (byteLength < 0) + { + byteLength = bytes.length - byteOffset; + } + var state = [stageFlags, offset, byteOffset, byteLength]; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && layout.isValid()) + { + return NativeCFFI.lime_vk_cmd_push_constants(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, layout.handle.high, layout.handle.low, state, bytes); + } + #end + + return false; + } + + public function setScissor(x:Int, y:Int, width:Int, height:Int):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_cmd_set_scissor(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, x, y, width, height); + } + #end + + return false; + } + + public function setViewport(x:Float, y:Float, width:Float, height:Float, minDepth:Float = 0, maxDepth:Float = 1):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_cmd_set_viewport(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, x, y, width, height, minDepth, maxDepth); + } + #end + + return false; + } + + @:allow(lime.graphics.vulkan.VKCommandPool) + private function __invalidate():Void + { + handle = Int64.ofInt(0); + } + + private inline function get_device():VKDevice + { + return (pool != null) ? pool.device : null; + } +} diff --git a/src/lime/graphics/vulkan/VKCommandPool.hx b/src/lime/graphics/vulkan/VKCommandPool.hx new file mode 100644 index 0000000000..f01e0c3a71 --- /dev/null +++ b/src/lime/graphics/vulkan/VKCommandPool.hx @@ -0,0 +1,92 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan command pool created from a `VKDevice`. +**/ +class VKCommandPool +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + public var queueFamilyIndex(default, null):Int; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, queueFamilyIndex:Int, handle:Int64) + { + this.device = device; + this.queueFamilyIndex = queueFamilyIndex; + this.handle = handle; + } + + public function allocateCommandBuffer(level:Int = VK.COMMAND_BUFFER_LEVEL_PRIMARY):VKCommandBuffer + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_allocate_command_buffer(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, level); + var commandBufferHandle = VK.__makeHandle(data); + if (!VK.__isZero(commandBufferHandle)) + { + return new VKCommandBuffer(this, commandBufferHandle, level); + } + } + #end + + return null; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_command_pool(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + public function reset(flags:Int = 0):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_reset_command_pool(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, flags); + } + #end + + return false; + } + + @:allow(lime.graphics.vulkan.VKCommandBuffer) + private function free(commandBuffer:VKCommandBuffer):Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (commandBuffer != null && commandBuffer.isValid() && isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_free_command_buffer(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, commandBuffer.handle.high, commandBuffer.handle.low); + commandBuffer.__invalidate(); + } + #end + } +} diff --git a/src/lime/graphics/vulkan/VKDescriptorPool.hx b/src/lime/graphics/vulkan/VKDescriptorPool.hx new file mode 100644 index 0000000000..8763407d72 --- /dev/null +++ b/src/lime/graphics/vulkan/VKDescriptorPool.hx @@ -0,0 +1,74 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKDescriptorPool +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function allocate(layout:VKDescriptorSetLayout):VKDescriptorSet + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && layout != null && layout.isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_allocate_descriptor_set(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, layout.handle.high, layout.handle.low); + var descriptorSetHandle = VK.__makeHandle(data); + if (!VK.__isZero(descriptorSetHandle)) + { + return new VKDescriptorSet(this, layout, descriptorSetHandle); + } + } + #end + + return null; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_descriptor_pool(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + public function reset(flags:Int = 0):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_reset_descriptor_pool(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, flags); + } + #end + + return false; + } +} diff --git a/src/lime/graphics/vulkan/VKDescriptorPoolSize.hx b/src/lime/graphics/vulkan/VKDescriptorPoolSize.hx new file mode 100644 index 0000000000..6b83cab5ef --- /dev/null +++ b/src/lime/graphics/vulkan/VKDescriptorPoolSize.hx @@ -0,0 +1,13 @@ +package lime.graphics.vulkan; + +class VKDescriptorPoolSize +{ + public var descriptorCount:Int; + public var descriptorType:Int; + + public function new(descriptorType:Int, descriptorCount:Int) + { + this.descriptorType = descriptorType; + this.descriptorCount = descriptorCount; + } +} diff --git a/src/lime/graphics/vulkan/VKDescriptorSet.hx b/src/lime/graphics/vulkan/VKDescriptorSet.hx new file mode 100644 index 0000000000..8fe7110a9f --- /dev/null +++ b/src/lime/graphics/vulkan/VKDescriptorSet.hx @@ -0,0 +1,71 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKDescriptorSet +{ + public var device(get, never):VKDevice; + public var handle(default, null):Int64; + public var layout(default, null):VKDescriptorSetLayout; + public var pool(default, null):VKDescriptorPool; + + @:allow(lime.graphics.vulkan.VKDescriptorPool) + private function new(pool:VKDescriptorPool, layout:VKDescriptorSetLayout, handle:Int64) + { + this.pool = pool; + this.layout = layout; + this.handle = handle; + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + public function updateBuffer(binding:Int, buffer:VKBuffer, range:Int, offset:Int = 0, descriptorType:Int = VK.DESCRIPTOR_TYPE_UNIFORM_BUFFER):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + var device = get_device(); + if (isValid() && device != null && device.isValid() && buffer != null && buffer.isValid()) + { + return NativeCFFI.lime_vk_update_descriptor_set_buffer(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, binding, descriptorType, buffer.handle.high, + buffer.handle.low, offset, range); + } + #end + + return false; + } + + public function updateImage(binding:Int, imageView:VKImageView, sampler:VKSampler = null, layout:Int = VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + descriptorType:Int = VK.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + var device = get_device(); + if (isValid() && device != null && device.isValid() && imageView != null && imageView.isValid()) + { + var samplerHandle = (sampler != null && sampler.isValid()) ? sampler.handle : Int64.ofInt(0); + return NativeCFFI.lime_vk_update_descriptor_set_image(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, binding, descriptorType, imageView.handle.high, + imageView.handle.low, samplerHandle.high, samplerHandle.low, layout); + } + #end + + return false; + } + + private inline function get_device():VKDevice + { + return pool != null ? pool.device : null; + } +} diff --git a/src/lime/graphics/vulkan/VKDescriptorSetLayout.hx b/src/lime/graphics/vulkan/VKDescriptorSetLayout.hx new file mode 100644 index 0000000000..fd6a04d14c --- /dev/null +++ b/src/lime/graphics/vulkan/VKDescriptorSetLayout.hx @@ -0,0 +1,43 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKDescriptorSetLayout +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_descriptor_set_layout(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKDescriptorSetLayoutBinding.hx b/src/lime/graphics/vulkan/VKDescriptorSetLayoutBinding.hx new file mode 100644 index 0000000000..b3ab2368ae --- /dev/null +++ b/src/lime/graphics/vulkan/VKDescriptorSetLayoutBinding.hx @@ -0,0 +1,17 @@ +package lime.graphics.vulkan; + +class VKDescriptorSetLayoutBinding +{ + public var binding:Int; + public var descriptorCount:Int; + public var descriptorType:Int; + public var stageFlags:Int; + + public function new(binding:Int, descriptorType:Int, stageFlags:Int, descriptorCount:Int = 1) + { + this.binding = binding; + this.descriptorType = descriptorType; + this.stageFlags = stageFlags; + this.descriptorCount = descriptorCount; + } +} diff --git a/src/lime/graphics/vulkan/VKDescriptorWrite.hx b/src/lime/graphics/vulkan/VKDescriptorWrite.hx new file mode 100644 index 0000000000..b06c522d7e --- /dev/null +++ b/src/lime/graphics/vulkan/VKDescriptorWrite.hx @@ -0,0 +1,115 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +/** + A single descriptor write used by `VKDevice.updateDescriptorSets()`. +**/ +class VKDescriptorWrite +{ + private static inline var KIND_BUFFER = 0; + private static inline var KIND_IMAGE = 1; + + public var arrayElement:Int; + public var binding:Int; + public var buffer:VKBuffer; + public var descriptorSet:VKDescriptorSet; + public var descriptorType:Int; + public var imageLayout:Int; + public var imageView:VKImageView; + public var offset:Int64; + public var range:Int64; + public var sampler:VKSampler; + + private var kind:Int; + + public function new() + { + arrayElement = 0; + binding = 0; + descriptorType = VK.DESCRIPTOR_TYPE_UNIFORM_BUFFER; + imageLayout = VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + kind = KIND_BUFFER; + offset = Int64.ofInt(0); + range = Int64.ofInt(0); + } + + public static function forBuffer(descriptorSet:VKDescriptorSet, binding:Int, buffer:VKBuffer, range:Int64 = null, offset:Int64 = null, + descriptorType:Int = VK.DESCRIPTOR_TYPE_UNIFORM_BUFFER, arrayElement:Int = 0):VKDescriptorWrite + { + var write = new VKDescriptorWrite(); + write.kind = KIND_BUFFER; + write.descriptorSet = descriptorSet; + write.binding = binding; + write.buffer = buffer; + write.range = range != null ? range : Int64.ofInt(0); + write.offset = offset != null ? offset : Int64.ofInt(0); + write.descriptorType = descriptorType; + write.arrayElement = arrayElement; + return write; + } + + public static function forImage(descriptorSet:VKDescriptorSet, binding:Int, imageView:VKImageView, sampler:VKSampler = null, + imageLayout:Int = VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, descriptorType:Int = VK.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + arrayElement:Int = 0):VKDescriptorWrite + { + var write = new VKDescriptorWrite(); + write.kind = KIND_IMAGE; + write.descriptorSet = descriptorSet; + write.binding = binding; + write.imageView = imageView; + write.sampler = sampler; + write.imageLayout = imageLayout; + write.descriptorType = descriptorType; + write.arrayElement = arrayElement; + return write; + } + + @:allow(lime.graphics.vulkan.VKDevice) + private function pack(result:Array):Bool + { + if (descriptorSet == null || !descriptorSet.isValid()) + { + return false; + } + + if (kind == KIND_IMAGE) + { + if (imageView == null || !imageView.isValid()) + { + return false; + } + var samplerHandle = (sampler != null && sampler.isValid()) ? sampler.handle : Int64.ofInt(0); + result.push(KIND_IMAGE); + result.push(descriptorSet.handle.high); + result.push(descriptorSet.handle.low); + result.push(binding); + result.push(arrayElement); + result.push(descriptorType); + result.push(imageView.handle.high); + result.push(imageView.handle.low); + result.push(samplerHandle.high); + result.push(samplerHandle.low); + result.push(imageLayout); + return true; + } + + if (buffer == null || !buffer.isValid()) + { + return false; + } + result.push(KIND_BUFFER); + result.push(descriptorSet.handle.high); + result.push(descriptorSet.handle.low); + result.push(binding); + result.push(arrayElement); + result.push(descriptorType); + result.push(buffer.handle.high); + result.push(buffer.handle.low); + result.push(offset.high); + result.push(offset.low); + result.push(range.high); + result.push(range.low); + return true; + } +} diff --git a/src/lime/graphics/vulkan/VKDevice.hx b/src/lime/graphics/vulkan/VKDevice.hx new file mode 100644 index 0000000000..50bd192581 --- /dev/null +++ b/src/lime/graphics/vulkan/VKDevice.hx @@ -0,0 +1,571 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +import haxe.io.Bytes; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A logical Vulkan device created from a `VKPhysicalDevice`. +**/ +class VKDevice +{ + public var extensions(default, null):Array; + public var graphicsQueue(default, null):VKQueue; + public var handle(default, null):Int64; + public var instance(default, null):VKInstance; + public var physicalDevice(default, null):VKPhysicalDevice; + public var queueFamily(default, null):VKQueueFamilyInfo; + + @:allow(lime.graphics.vulkan.VKPhysicalDevice) + private function new(physicalDevice:VKPhysicalDevice, queueFamily:VKQueueFamilyInfo, extensions:Array, data:Dynamic) + { + this.physicalDevice = physicalDevice; + this.instance = physicalDevice.instance; + this.queueFamily = queueFamily; + this.extensions = extensions.copy(); + handle = VK.__makeHandle(data.handle); + graphicsQueue = new VKQueue(this, VK.__makeHandle(data.queue), data.queueFamilyIndex, 0); + } + + public function createCommandPool(queueFamily:VKQueueFamilyInfo = null, flags:Int = VK.COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT):VKCommandPool + { + if (queueFamily == null) + { + queueFamily = this.queueFamily; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && queueFamily != null) + { + var data:Dynamic = NativeCFFI.lime_vk_create_command_pool(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, queueFamily.index, flags); + var commandPoolHandle = VK.__makeHandle(data); + if (!VK.__isZero(commandPoolHandle)) + { + return new VKCommandPool(this, queueFamily.index, commandPoolHandle); + } + } + #end + + return null; + } + + public function createFence(signaled:Bool = false):VKFence + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var flags = signaled ? VK.FENCE_CREATE_SIGNALED_BIT : 0; + var data:Dynamic = NativeCFFI.lime_vk_create_fence(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, flags); + var fenceHandle = VK.__makeHandle(data); + if (!VK.__isZero(fenceHandle)) + { + return new VKFence(this, fenceHandle); + } + } + #end + + return null; + } + + public function allocateMemory(requirements:VKMemoryRequirements, properties:Int):VKDeviceMemory + { + if (requirements == null) + { + return null; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_allocate_memory(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + physicalDevice.handle.high, physicalDevice.handle.low, handle.high, handle.low, requirements.size.high, requirements.size.low, + requirements.memoryTypeBits, properties); + var memoryHandle = VK.__makeHandle(data != null ? data.handle : null); + if (!VK.__isZero(memoryHandle)) + { + return new VKDeviceMemory(this, memoryHandle, requirements.size, data.memoryTypeIndex, properties); + } + } + #end + + return null; + } + + public function createBuffer(size:Int64, usage:Int):VKBuffer + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_buffer(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, size.high, size.low, usage); + var bufferHandle = VK.__makeHandle(data); + if (!VK.__isZero(bufferHandle)) + { + return new VKBuffer(this, bufferHandle, size, usage); + } + } + #end + + return null; + } + + public function createBufferWithMemory(size:Int64, usage:Int, properties:Int, bytes:Bytes = null):VKBuffer + { + var buffer = createBuffer(size, usage); + if (buffer == null) + { + return null; + } + + var memory = buffer.allocateMemory(properties); + if (memory == null) + { + buffer.dispose(); + return null; + } + + if (bytes != null && !buffer.upload(bytes)) + { + buffer.dispose(true); + return null; + } + + return buffer; + } + + public inline function createIndexBuffer(size:Int64, properties:Int, bytes:Bytes = null):VKBuffer + { + return createBufferWithMemory(size, VK.BUFFER_USAGE_INDEX_BUFFER_BIT, properties, bytes); + } + + public inline function createStagingBuffer(size:Int64, bytes:Bytes = null):VKBuffer + { + return createBufferWithMemory(size, VK.BUFFER_USAGE_TRANSFER_SRC_BIT, VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, + bytes); + } + + public inline function createUploadRing(byteCapacity:Int, usage:Int = VK.BUFFER_USAGE_TRANSFER_SRC_BIT, + properties:Int = VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT):VKUploadRing + { + return new VKUploadRing(this, byteCapacity, usage, properties); + } + + public inline function createStorageBuffer(size:Int64, properties:Int, bytes:Bytes = null):VKBuffer + { + return createBufferWithMemory(size, VK.BUFFER_USAGE_STORAGE_BUFFER_BIT, properties, bytes); + } + + public inline function createUniformBuffer(size:Int64, properties:Int, bytes:Bytes = null):VKBuffer + { + return createBufferWithMemory(size, VK.BUFFER_USAGE_UNIFORM_BUFFER_BIT, properties, bytes); + } + + public inline function createVertexBuffer(size:Int64, properties:Int, bytes:Bytes = null):VKBuffer + { + return createBufferWithMemory(size, VK.BUFFER_USAGE_VERTEX_BUFFER_BIT, properties, bytes); + } + + public function createDescriptorPool(maxSets:Int, poolSizes:Array, flags:Int = 0):VKDescriptorPool + { + var packed = [flags, maxSets, poolSizes != null ? poolSizes.length : 0]; + if (poolSizes != null) + { + for (poolSize in poolSizes) + { + packed.push(poolSize.descriptorType); + packed.push(poolSize.descriptorCount); + } + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_descriptor_pool(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, packed); + var descriptorPoolHandle = VK.__makeHandle(data); + if (!VK.__isZero(descriptorPoolHandle)) + { + return new VKDescriptorPool(this, descriptorPoolHandle); + } + } + #end + + return null; + } + + public function createDescriptorSetLayout(bindings:Array, flags:Int = 0):VKDescriptorSetLayout + { + var packed = [flags, bindings != null ? bindings.length : 0]; + if (bindings != null) + { + for (binding in bindings) + { + packed.push(binding.binding); + packed.push(binding.descriptorType); + packed.push(binding.descriptorCount); + packed.push(binding.stageFlags); + } + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_descriptor_set_layout(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, packed); + var descriptorSetLayoutHandle = VK.__makeHandle(data); + if (!VK.__isZero(descriptorSetLayoutHandle)) + { + return new VKDescriptorSetLayout(this, descriptorSetLayoutHandle); + } + } + #end + + return null; + } + + public function updateDescriptorSets(writes:Array):Bool + { + if (writes == null || writes.length == 0) + { + return true; + } + + var packed = [writes.length]; + for (write in writes) + { + if (write == null || !write.pack(packed)) + { + return false; + } + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + return NativeCFFI.lime_vk_update_descriptor_sets(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, packed); + } + #end + + return false; + } + + public function createFramebuffer(renderPass:VKRenderPass, attachments:Array, width:Int, height:Int, layers:Int = 1):VKFramebuffer + { + if (renderPass == null || !renderPass.isValid() || attachments == null || attachments.length == 0) + { + return null; + } + + var packed = [attachments.length]; + for (attachment in attachments) + { + if (attachment == null || !attachment.isValid()) + { + return null; + } + packed.push(attachment.handle.high); + packed.push(attachment.handle.low); + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_framebuffer(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, renderPass.handle.high, renderPass.handle.low, packed, width, height, layers); + var framebufferHandle = VK.__makeHandle(data); + if (!VK.__isZero(framebufferHandle)) + { + return new VKFramebuffer(this, renderPass, framebufferHandle, width, height); + } + } + #end + + return null; + } + + public function createGraphicsPipeline(renderPass:VKRenderPass, layout:VKPipelineLayout, vertexShader:VKShaderModule, fragmentShader:VKShaderModule, + info:VKGraphicsPipelineInfo, cache:VKPipelineCache = null):VKPipeline + { + if (renderPass == null || layout == null || vertexShader == null || fragmentShader == null) + { + return null; + } + if (info == null) + { + info = new VKGraphicsPipelineInfo(); + } + + var cacheHandle = cache != null && cache.isValid() ? cache.handle : Int64.ofInt(0); + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && renderPass.isValid() && layout.isValid() && vertexShader.isValid() && fragmentShader.isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_graphics_pipeline(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, renderPass.handle.high, renderPass.handle.low, layout.handle.high, layout.handle.low, vertexShader.handle.high, + vertexShader.handle.low, fragmentShader.handle.high, fragmentShader.handle.low, info.pack(cacheHandle)); + var pipelineHandle = VK.__makeHandle(data); + if (!VK.__isZero(pipelineHandle)) + { + return new VKPipeline(this, layout, pipelineHandle); + } + } + #end + + return null; + } + + public function createImage(width:Int, height:Int, format:Int, usage:Int, depth:Int = 1, mipLevels:Int = 1, arrayLayers:Int = 1, + imageType:Int = VK.IMAGE_TYPE_2D, tiling:Int = VK.IMAGE_TILING_OPTIMAL, samples:Int = VK.SAMPLE_COUNT_1_BIT):VKImage + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_image(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, width, height, depth, mipLevels, arrayLayers, format, imageType, tiling, usage, samples); + var imageHandle = VK.__makeHandle(data); + if (!VK.__isZero(imageHandle)) + { + return VKImage.createOwned(this, imageHandle, width, height, format); + } + } + #end + + return null; + } + + public function createPipelineCache(bytes:Bytes = null, byteOffset:Int = 0, byteLength:Int = -1):VKPipelineCache + { + if (byteLength < 0 && bytes != null) + { + byteLength = bytes.length - byteOffset; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_pipeline_cache(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, bytes, byteOffset, byteLength); + var pipelineCacheHandle = VK.__makeHandle(data); + if (!VK.__isZero(pipelineCacheHandle)) + { + return new VKPipelineCache(this, pipelineCacheHandle); + } + } + #end + + return null; + } + + public function createPipelineLayout(descriptorSetLayouts:Array = null, pushConstantStages:Int = 0, + pushConstantSize:Int = 0):VKPipelineLayout + { + var packed = [descriptorSetLayouts != null ? descriptorSetLayouts.length : 0]; + if (descriptorSetLayouts != null) + { + for (layout in descriptorSetLayouts) + { + if (layout == null || !layout.isValid()) + { + return null; + } + packed.push(layout.handle.high); + packed.push(layout.handle.low); + } + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_pipeline_layout(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, packed, pushConstantStages, pushConstantSize); + var pipelineLayoutHandle = VK.__makeHandle(data); + if (!VK.__isZero(pipelineLayoutHandle)) + { + return new VKPipelineLayout(this, pipelineLayoutHandle); + } + } + #end + + return null; + } + + public function createRenderPass(colorFormat:Int, depthStencilFormat:Int = VK.FORMAT_UNDEFINED, samples:Int = VK.SAMPLE_COUNT_1_BIT, + colorLoadOp:Int = VK.ATTACHMENT_LOAD_OP_CLEAR, colorStoreOp:Int = VK.ATTACHMENT_STORE_OP_STORE, + colorInitialLayout:Int = VK.IMAGE_LAYOUT_UNDEFINED, colorFinalLayout:Int = VK.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + depthInitialLayout:Int = VK.IMAGE_LAYOUT_UNDEFINED, depthFinalLayout:Int = VK.IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + depthLoadOp:Int = VK.ATTACHMENT_LOAD_OP_CLEAR, depthStoreOp:Int = VK.ATTACHMENT_STORE_OP_DONT_CARE, resolveFormat:Int = VK.FORMAT_UNDEFINED, + resolveLoadOp:Int = VK.ATTACHMENT_LOAD_OP_DONT_CARE, resolveStoreOp:Int = VK.ATTACHMENT_STORE_OP_STORE, + resolveInitialLayout:Int = VK.IMAGE_LAYOUT_UNDEFINED, resolveFinalLayout:Int = VK.IMAGE_LAYOUT_PRESENT_SRC_KHR):VKRenderPass + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var state = [ + colorFormat, + depthStencilFormat, + samples, + colorLoadOp, + colorStoreOp, + colorInitialLayout, + colorFinalLayout, + depthInitialLayout, + depthFinalLayout, + depthLoadOp, + depthStoreOp, + resolveFormat, + resolveLoadOp, + resolveStoreOp, + resolveInitialLayout, + resolveFinalLayout + ]; + var data:Dynamic = NativeCFFI.lime_vk_create_render_pass(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, state); + var renderPassHandle = VK.__makeHandle(data); + if (!VK.__isZero(renderPassHandle)) + { + return new VKRenderPass(this, renderPassHandle, colorFormat, depthStencilFormat, samples, resolveFormat); + } + } + #end + + return null; + } + + public function createSampler(filter:Int = VK.FILTER_LINEAR, addressMode:Int = VK.SAMPLER_ADDRESS_MODE_REPEAT, + mipmapMode:Int = VK.SAMPLER_MIPMAP_MODE_LINEAR, anisotropyEnable:Bool = false, maxAnisotropy:Float = 1, compareOp:Int = -1, minLod:Float = 0, + maxLod:Float = 0):VKSampler + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_sampler(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, filter, addressMode, mipmapMode, anisotropyEnable, maxAnisotropy, compareOp, minLod, maxLod); + var samplerHandle = VK.__makeHandle(data); + if (!VK.__isZero(samplerHandle)) + { + return new VKSampler(this, samplerHandle); + } + } + #end + + return null; + } + + public function createSemaphore():VKSemaphore + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_semaphore(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low); + var semaphoreHandle = VK.__makeHandle(data); + if (!VK.__isZero(semaphoreHandle)) + { + return new VKSemaphore(this, semaphoreHandle); + } + } + #end + + return null; + } + + public function createShaderModule(bytes:Bytes, byteOffset:Int = 0, byteLength:Int = -1):VKShaderModule + { + if (bytes == null) + { + return null; + } + if (byteLength < 0) + { + byteLength = bytes.length - byteOffset; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_shader_module(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + handle.high, handle.low, bytes, byteOffset, byteLength); + var shaderModuleHandle = VK.__makeHandle(data); + if (!VK.__isZero(shaderModuleHandle)) + { + return new VKShaderModule(this, shaderModuleHandle); + } + } + #end + + return null; + } + + /** + Creates a swapchain for a window surface. Pass an existing swapchain as + `oldSwapchain` when recreating resources after a resize. + **/ + public function createSwapchain(surface:VKSurface, width:Int = 0, height:Int = 0, presentMode:Int = VK.PRESENT_MODE_FIFO_KHR, + oldSwapchain:VKSwapchain = null):VKSwapchain + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && surface != null && surface.isValid() && queueFamily != null) + { + var oldSwapchainHandle = (oldSwapchain != null && oldSwapchain.isValid()) ? oldSwapchain.handle : Int64.ofInt(0); + var data:Dynamic = NativeCFFI.lime_vk_create_swapchain(instance.context.__windowHandle, instance.handle.high, instance.handle.low, + physicalDevice.handle.high, physicalDevice.handle.low, handle.high, handle.low, surface.high, surface.low, queueFamily.index, width, height, + presentMode, oldSwapchainHandle.high, oldSwapchainHandle.low); + var swapchainHandle = VK.__makeHandle(data != null ? data.handle : null); + if (!VK.__isZero(swapchainHandle)) + { + return new VKSwapchain(this, surface, data); + } + } + #end + + return null; + } + + /** + Destroys the logical device. All resources created from the device should + be destroyed before calling this method. + **/ + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + NativeCFFI.lime_vk_destroy_device(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + graphicsQueue = null; + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + /** + Blocks until the logical device has completed all submitted work. + **/ + public function waitIdle():Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid()) + { + return NativeCFFI.lime_vk_device_wait_idle(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, handle.low); + } + #end + + return false; + } +} diff --git a/src/lime/graphics/vulkan/VKDeviceMemory.hx b/src/lime/graphics/vulkan/VKDeviceMemory.hx new file mode 100644 index 0000000000..ef742ebffc --- /dev/null +++ b/src/lime/graphics/vulkan/VKDeviceMemory.hx @@ -0,0 +1,252 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +import haxe.io.Bytes; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + Device memory allocated from a `VKDevice`. +**/ +class VKDeviceMemory +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + public var memoryTypeIndex(default, null):Int; + public var mapped(default, null):Bool = false; + public var mappedOffset(default, null):Int64 = Int64.ofInt(0); + public var mappedSize(default, null):Int64 = Int64.ofInt(0); + public var properties(default, null):Int; + public var size(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64, size:Int64, memoryTypeIndex:Int, properties:Int) + { + this.device = device; + this.handle = handle; + this.size = size; + this.memoryTypeIndex = memoryTypeIndex; + this.properties = properties; + } + + public function dispose():Void + { + if (mapped) + { + unmap(); + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_free_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + /** + Maps host-visible memory and keeps it mapped for repeated writes or + readback. Passing `size` as `null` maps the rest of the allocation. + **/ + public function map(offset:Int64 = null, size:Int64 = null, flags:Int = 0):Bool + { + if (offset == null) + { + offset = Int64.ofInt(0); + } + if (size == null) + { + size = Int64.ofInt(0); + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var result = NativeCFFI.lime_vk_map_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, offset.high, offset.low, size.high, size.low, flags); + if (result) + { + mapped = true; + mappedOffset = offset; + mappedSize = size; + } + return result; + } + #end + + return false; + } + + public function unmap():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (mapped && isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_unmap_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + } + #end + + mapped = false; + mappedOffset = Int64.ofInt(0); + mappedSize = Int64.ofInt(0); + } + + /** + Copies bytes into a currently mapped range without unmapping. This is the + hot-path companion to `upload()` for dynamic vertex/uniform streaming. + **/ + public function writeBytes(bytes:Bytes, srcOffset:Int = 0, length:Int = -1, dstOffset:Int64 = null):Bool + { + if (bytes == null || !mapped) + { + return false; + } + if (dstOffset == null) + { + dstOffset = mappedOffset; + } + if (length < 0) + { + length = bytes.length - srcOffset; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_write_mapped_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, dstOffset.high, dstOffset.low, bytes, srcOffset, length); + } + #end + + return false; + } + + public function flush(offset:Int64 = null, size:Int64 = null):Bool + { + if (!mapped) + { + return false; + } + if (offset == null) + { + offset = mappedOffset; + } + if (size == null) + { + size = mappedSize; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_flush_mapped_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, offset.high, offset.low, size.high, size.low); + } + #end + + return false; + } + + public function invalidate(offset:Int64 = null, size:Int64 = null):Bool + { + if (!mapped) + { + return false; + } + if (offset == null) + { + offset = mappedOffset; + } + if (size == null) + { + size = mappedSize; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_invalidate_mapped_memory(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, offset.high, offset.low, size.high, size.low); + } + #end + + return false; + } + + /** + Copies bytes into host-visible memory. This maps and unmaps internally, + which is convenient for staging/uniform data and avoids exposing unsafe + raw pointers at the Lime boundary. + **/ + public function upload(bytes:Bytes, memoryOffset:Int64 = null, byteOffset:Int = 0, byteLength:Int = -1):Bool + { + if (memoryOffset == null) + { + memoryOffset = Int64.ofInt(0); + } + if (bytes == null) + { + return false; + } + if (byteLength < 0) + { + byteLength = bytes.length - byteOffset; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_upload_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, memoryOffset.high, memoryOffset.low, bytes, byteOffset, byteLength); + } + #end + + return false; + } + + /** + Copies host-visible memory into a Haxe `Bytes` buffer. Use this after an + image-to-buffer transfer for render target and texture capture paths. + **/ + public function download(bytes:Bytes, memoryOffset:Int64 = null, byteOffset:Int = 0, byteLength:Int = -1):Bool + { + if (memoryOffset == null) + { + memoryOffset = Int64.ofInt(0); + } + if (bytes == null) + { + return false; + } + if (byteLength < 0) + { + byteLength = bytes.length - byteOffset; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_download_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, memoryOffset.high, memoryOffset.low, bytes, byteOffset, byteLength); + } + #end + + return false; + } +} diff --git a/src/lime/graphics/vulkan/VKFence.hx b/src/lime/graphics/vulkan/VKFence.hx new file mode 100644 index 0000000000..9fc7d1779a --- /dev/null +++ b/src/lime/graphics/vulkan/VKFence.hx @@ -0,0 +1,77 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan fence used for CPU/GPU synchronization. +**/ +class VKFence +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_fence(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + public function reset():Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_reset_fence(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + } + #end + + return false; + } + + public function wait(timeout:Int64):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_wait_for_fence(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, timeout.high, timeout.low); + } + #end + + return false; + } + + public function waitForever():Bool + { + return wait(Int64.make(-1, -1)); + } +} diff --git a/src/lime/graphics/vulkan/VKFramebuffer.hx b/src/lime/graphics/vulkan/VKFramebuffer.hx new file mode 100644 index 0000000000..d2298a2f09 --- /dev/null +++ b/src/lime/graphics/vulkan/VKFramebuffer.hx @@ -0,0 +1,49 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKFramebuffer +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + public var height(default, null):Int; + public var renderPass(default, null):VKRenderPass; + public var width(default, null):Int; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, renderPass:VKRenderPass, handle:Int64, width:Int, height:Int) + { + this.device = device; + this.renderPass = renderPass; + this.handle = handle; + this.width = width; + this.height = height; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_framebuffer(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKGraphicsPipelineInfo.hx b/src/lime/graphics/vulkan/VKGraphicsPipelineInfo.hx new file mode 100644 index 0000000000..527a44ada0 --- /dev/null +++ b/src/lime/graphics/vulkan/VKGraphicsPipelineInfo.hx @@ -0,0 +1,121 @@ +package lime.graphics.vulkan; + +class VKGraphicsPipelineInfo +{ + public var alphaBlendOp:Int = VK.BLEND_OP_ADD; + public var colorBlendOp:Int = VK.BLEND_OP_ADD; + public var colorWriteMask:Int = VK.COLOR_COMPONENT_RGBA_BITS; + public var cullMode:Int = VK.CULL_MODE_BACK_BIT; + public var backCompareMask:Int = -1; + public var backCompareOp:Int = VK.COMPARE_OP_ALWAYS; + public var backDepthFailOp:Int = VK.STENCIL_OP_KEEP; + public var backFailOp:Int = VK.STENCIL_OP_KEEP; + public var backPassOp:Int = VK.STENCIL_OP_KEEP; + public var backReference:Int = 0; + public var backWriteMask:Int = -1; + public var depthCompareOp:Int = VK.COMPARE_OP_LESS; + public var depthTest:Bool = false; + public var depthWrite:Bool = false; + public var dstAlphaBlendFactor:Int = VK.BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + public var dstColorBlendFactor:Int = VK.BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + public var dynamicStateFlags:Int = VK.DYNAMIC_STATE_VIEWPORT_BIT | VK.DYNAMIC_STATE_SCISSOR_BIT; + public var frontCompareMask:Int = -1; + public var frontCompareOp:Int = VK.COMPARE_OP_ALWAYS; + public var frontDepthFailOp:Int = VK.STENCIL_OP_KEEP; + public var frontFailOp:Int = VK.STENCIL_OP_KEEP; + public var frontFace:Int = VK.FRONT_FACE_COUNTER_CLOCKWISE; + public var frontPassOp:Int = VK.STENCIL_OP_KEEP; + public var frontReference:Int = 0; + public var frontWriteMask:Int = -1; + public var polygonMode:Int = VK.POLYGON_MODE_FILL; + public var primitiveRestart:Bool = false; + public var rasterizationSamples:Int = VK.SAMPLE_COUNT_1_BIT; + public var sampleShading:Bool = false; + public var minSampleShading:Float = 0; + public var sampleMask:Int = 0; + public var alphaToCoverage:Bool = false; + public var alphaToOne:Bool = false; + public var srcAlphaBlendFactor:Int = VK.BLEND_FACTOR_ONE; + public var srcColorBlendFactor:Int = VK.BLEND_FACTOR_SRC_ALPHA; + public var stencilTest:Bool = false; + public var topology:Int = VK.PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + public var vertexAttributes:Array; + public var vertexBindings:Array; + public var blend:Bool = false; + + public function new() + { + vertexAttributes = []; + vertexBindings = []; + } + + @:allow(lime.graphics.vulkan.VKDevice) + private function pack(cacheHandle:haxe.Int64 = null):Array + { + if (cacheHandle == null) + { + cacheHandle = haxe.Int64.ofInt(0); + } + var result = [ + cacheHandle.high, + cacheHandle.low, + topology, + primitiveRestart ? 1 : 0, + polygonMode, + cullMode, + frontFace, + depthTest ? 1 : 0, + depthWrite ? 1 : 0, + depthCompareOp, + blend ? 1 : 0, + srcColorBlendFactor, + dstColorBlendFactor, + colorBlendOp, + srcAlphaBlendFactor, + dstAlphaBlendFactor, + alphaBlendOp, + dynamicStateFlags, + colorWriteMask, + stencilTest ? 1 : 0, + frontFailOp, + frontPassOp, + frontDepthFailOp, + frontCompareOp, + frontCompareMask, + frontWriteMask, + frontReference, + backFailOp, + backPassOp, + backDepthFailOp, + backCompareOp, + backCompareMask, + backWriteMask, + backReference, + rasterizationSamples, + sampleShading ? 1 : 0, + Std.int(minSampleShading * 1000000), + sampleMask, + alphaToCoverage ? 1 : 0, + alphaToOne ? 1 : 0, + vertexBindings.length + ]; + + for (binding in vertexBindings) + { + result.push(binding.binding); + result.push(binding.stride); + result.push(binding.inputRate); + } + + result.push(vertexAttributes.length); + for (attribute in vertexAttributes) + { + result.push(attribute.location); + result.push(attribute.binding); + result.push(attribute.format); + result.push(attribute.offset); + } + + return result; + } +} diff --git a/src/lime/graphics/vulkan/VKImage.hx b/src/lime/graphics/vulkan/VKImage.hx new file mode 100644 index 0000000000..fd5a556a81 --- /dev/null +++ b/src/lime/graphics/vulkan/VKImage.hx @@ -0,0 +1,163 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan image handle. Swapchain images are owned by their `VKSwapchain`. +**/ +class VKImage +{ + public var device(default, null):VKDevice; + public var format(default, null):Int; + public var handle(default, null):Int64; + public var height(default, null):Int; + public var index(default, null):Int; + public var memory(default, null):VKDeviceMemory; + public var ownsHandle(default, null):Bool; + public var swapchain(default, null):VKSwapchain; + public var width(default, null):Int; + + @:allow(lime.graphics.vulkan.VKSwapchain) + private function new(swapchain:VKSwapchain, handle:Int64, index:Int) + { + this.swapchain = swapchain; + this.device = swapchain != null ? swapchain.device : null; + this.handle = handle; + this.index = index; + this.format = swapchain != null ? swapchain.format : VK.FORMAT_UNDEFINED; + this.width = swapchain != null ? swapchain.width : 0; + this.height = swapchain != null ? swapchain.height : 0; + this.ownsHandle = false; + } + + @:allow(lime.graphics.vulkan.VKDevice) + private static function createOwned(device:VKDevice, handle:Int64, width:Int, height:Int, format:Int):VKImage + { + var image = new VKImage(null, handle, -1); + image.swapchain = null; + image.device = device; + image.handle = handle; + image.index = -1; + image.format = format; + image.width = width; + image.height = height; + image.ownsHandle = true; + return image; + } + + public function allocateMemory(properties:Int):VKDeviceMemory + { + if (device == null) + { + return null; + } + + var allocated = device.allocateMemory(getMemoryRequirements(), properties); + if (allocated != null && bindMemory(allocated)) + { + memory = allocated; + return allocated; + } + + if (allocated != null) + { + allocated.dispose(); + } + return null; + } + + public function bindMemory(memory:VKDeviceMemory, offset:Int64 = null):Bool + { + if (offset == null) + { + offset = Int64.ofInt(0); + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && memory != null && memory.isValid()) + { + var result = NativeCFFI.lime_vk_bind_image_memory(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, memory.handle.high, memory.handle.low, offset.high, offset.low); + if (result) + { + this.memory = memory; + } + return result; + } + #end + + return false; + } + + public function createView(format:Int = 0, aspectMask:Int = VK.IMAGE_ASPECT_COLOR_BIT, viewType:Int = VK.IMAGE_VIEW_TYPE_2D, baseMipLevel:Int = 0, + levelCount:Int = 1, baseArrayLayer:Int = 0, layerCount:Int = 1):VKImageView + { + if (format == 0) + { + format = this.format; + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_create_image_view_ex(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, format, aspectMask, viewType, baseMipLevel, + levelCount, baseArrayLayer, layerCount); + var imageViewHandle = VK.__makeHandle(data); + if (!VK.__isZero(imageViewHandle)) + { + return new VKImageView(this, imageViewHandle, format, aspectMask, viewType); + } + } + #end + + return null; + } + + public function dispose(destroyMemory:Bool = false):Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (ownsHandle && isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_image(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + + if (destroyMemory && memory != null) + { + memory.dispose(); + memory = null; + } + } + + public inline function get():Int64 + { + return handle; + } + + public function getMemoryRequirements():VKMemoryRequirements + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_get_image_memory_requirements(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low); + return VKMemoryRequirements.fromDynamic(data); + } + #end + + return null; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKImageView.hx b/src/lime/graphics/vulkan/VKImageView.hx new file mode 100644 index 0000000000..6f911c1b60 --- /dev/null +++ b/src/lime/graphics/vulkan/VKImageView.hx @@ -0,0 +1,54 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan image view created for a `VKImage`. +**/ +class VKImageView +{ + public var aspectMask(default, null):Int; + public var device(default, null):VKDevice; + public var format(default, null):Int; + public var handle(default, null):Int64; + public var image(default, null):VKImage; + public var viewType(default, null):Int; + + @:allow(lime.graphics.vulkan.VKImage) + private function new(image:VKImage, handle:Int64, format:Int, aspectMask:Int, viewType:Int) + { + this.image = image; + this.device = image.device; + this.handle = handle; + this.format = format; + this.aspectMask = aspectMask; + this.viewType = viewType; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_image_view(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKInstance.hx b/src/lime/graphics/vulkan/VKInstance.hx new file mode 100644 index 0000000000..42601584fc --- /dev/null +++ b/src/lime/graphics/vulkan/VKInstance.hx @@ -0,0 +1,110 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +import lime.graphics.VulkanRenderContext; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A lightweight managed `VkInstance` wrapper created through `VK.createInstance`. +**/ +class VKInstance +{ + public var context(default, null):VulkanRenderContext; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VK) + private function new(context:VulkanRenderContext, handle:Int64) + { + this.context = context; + this.handle = handle; + } + + /** + Creates a `VKSurface` for the current window using this instance. + **/ + public function createSurface(contextOverride:VulkanRenderContext = null):VKSurface + { + var activeContext = (contextOverride != null) ? contextOverride : context; + + if (activeContext == null || VK.__isZero(handle)) + { + return null; + } + + #if (!macro && lime_cffi) + var surfaceData:Dynamic = NativeCFFI.lime_window_create_vulkan_surface(activeContext.__windowHandle, handle.high, handle.low); + if (surfaceData != null) + { + return new VKSurface(activeContext, this, surfaceData.high, surfaceData.low); + } + #end + + return null; + } + + /** + Destroys the managed `VkInstance`. + **/ + public function dispose():Void + { + #if (!macro && lime_cffi) + if (context != null && !VK.__isZero(handle)) + { + NativeCFFI.lime_vk_destroy_instance(context.__windowHandle, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + /** + Enumerates physical devices visible to this instance. If a surface is + provided, queue family presentation support is populated for that surface. + **/ + public function enumeratePhysicalDevices(surface:VKSurface = null):Array + { + var devices = new Array(); + + if (context == null || VK.__isZero(handle)) + { + return devices; + } + + #if (!macro && lime_cffi) + var result:Dynamic = NativeCFFI.lime_vk_get_physical_devices(context.__windowHandle, handle.high, handle.low, surface != null ? surface.high : 0, + surface != null ? surface.low : 0); + + if (result != null) + { + var length:Int = untyped result.length; + for (i in 0...length) + { + devices.push(new VKPhysicalDevice(this, untyped result[i])); + } + } + #end + + return devices; + } + + /** + Selects a preferred physical device using Lime's lightweight heuristics. + **/ + public function pickPhysicalDevice(surface:VKSurface = null, preferDiscrete:Bool = true):VKPhysicalDevice + { + return VK.pickPhysicalDevice(enumeratePhysicalDevices(surface), surface != null && surface.isValid(), preferDiscrete); + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKMemoryRequirements.hx b/src/lime/graphics/vulkan/VKMemoryRequirements.hx new file mode 100644 index 0000000000..5be95984ff --- /dev/null +++ b/src/lime/graphics/vulkan/VKMemoryRequirements.hx @@ -0,0 +1,32 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +/** + Memory requirements returned by Vulkan for buffers and images. +**/ +class VKMemoryRequirements +{ + public var alignment(default, null):Int64; + public var memoryTypeBits(default, null):Int; + public var size(default, null):Int64; + + public function new(size:Int64, alignment:Int64, memoryTypeBits:Int) + { + this.size = size; + this.alignment = alignment; + this.memoryTypeBits = memoryTypeBits; + } + + @:allow(lime.graphics.vulkan.VKBuffer) + @:allow(lime.graphics.vulkan.VKImage) + private static function fromDynamic(data:Dynamic):VKMemoryRequirements + { + if (data == null) + { + return null; + } + + return new VKMemoryRequirements(VK.__makeHandle(data.size), VK.__makeHandle(data.alignment), data.memoryTypeBits); + } +} diff --git a/src/lime/graphics/vulkan/VKPhysicalDevice.hx b/src/lime/graphics/vulkan/VKPhysicalDevice.hx new file mode 100644 index 0000000000..f21d0e9d0b --- /dev/null +++ b/src/lime/graphics/vulkan/VKPhysicalDevice.hx @@ -0,0 +1,186 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime.system.CFFI; +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + Describes a Vulkan physical device discovered through a `VKInstance`. +**/ +class VKPhysicalDevice +{ + public var instance(default, null):VKInstance; + public var handle(default, null):Int64; + public var name(default, null):String; + public var apiVersion(default, null):Int; + public var apiVersionString(default, null):String; + public var driverVersion(default, null):Int; + public var vendorID(default, null):Int; + public var deviceID(default, null):Int; + public var deviceType(default, null):Int; + public var deviceTypeName(default, null):String; + public var framebufferColorSampleCounts(default, null):Int; + public var framebufferDepthSampleCounts(default, null):Int; + public var framebufferNoAttachmentsSampleCounts(default, null):Int; + public var framebufferStencilSampleCounts(default, null):Int; + public var isDiscrete(default, null):Bool; + public var maxPushConstantsSize(default, null):Int; + public var minStorageBufferOffsetAlignment(default, null):Int64; + public var minUniformBufferOffsetAlignment(default, null):Int64; + public var nonCoherentAtomSize(default, null):Int64; + public var supportsPresent(default, null):Bool; + public var queueFamilies(default, null):Array; + + @:allow(lime.graphics.vulkan.VKInstance) + private function new(instance:VKInstance, data:Dynamic) + { + this.instance = instance; + handle = VK.__makeHandle(data.handle); + name = (data.name != null) ? #if (!lime_doc_gen || lime_cffi) CFFI.stringValue(data.name) #else cast data.name #end : ""; + apiVersion = data.apiVersion; + apiVersionString = VK.versionString(apiVersion); + driverVersion = data.driverVersion; + vendorID = data.vendorID; + deviceID = data.deviceID; + deviceType = data.deviceType; + framebufferColorSampleCounts = data.framebufferColorSampleCounts; + framebufferDepthSampleCounts = data.framebufferDepthSampleCounts; + framebufferNoAttachmentsSampleCounts = data.framebufferNoAttachmentsSampleCounts; + framebufferStencilSampleCounts = data.framebufferStencilSampleCounts; + maxPushConstantsSize = data.maxPushConstantsSize; + minStorageBufferOffsetAlignment = VK.__makeHandle(data.minStorageBufferOffsetAlignment); + minUniformBufferOffsetAlignment = VK.__makeHandle(data.minUniformBufferOffsetAlignment); + nonCoherentAtomSize = VK.__makeHandle(data.nonCoherentAtomSize); + deviceTypeName = switch (deviceType) + { + case 1: "integrated-gpu"; + case 2: "discrete-gpu"; + case 3: "virtual-gpu"; + case 4: "cpu"; + default: "other"; + } + isDiscrete = (deviceType == 2); + supportsPresent = false; + + queueFamilies = []; + var rawQueueFamilies:Dynamic = data.queueFamilies; + if (rawQueueFamilies != null) + { + var length:Int = untyped rawQueueFamilies.length; + for (i in 0...length) + { + var queueFamily = new VKQueueFamilyInfo(untyped rawQueueFamilies[i]); + queueFamilies.push(queueFamily); + if (queueFamily.supportsPresent) + { + supportsPresent = true; + } + } + } + } + + /** + Creates a logical device with one queue from the requested queue family. + If no queue family is provided, Lime selects a graphics-capable family + that can present to the current surface when that data is available. + **/ + public function createDevice(queueFamily:VKQueueFamilyInfo = null, extensions:Array = null):VKDevice + { + if (queueFamily == null) + { + queueFamily = getQueueFamily(true, supportsPresent); + } + + if (extensions == null) + { + extensions = [VK.KHR_SWAPCHAIN_EXTENSION_NAME]; + } + + if (queueFamily == null || instance == null || instance.context == null || !instance.isValid()) + { + return null; + } + + #if (!macro && lime_cffi && lime_vulkan) + var data:Dynamic = NativeCFFI.lime_vk_create_device(instance.context.__windowHandle, instance.handle.high, instance.handle.low, handle.high, + handle.low, queueFamily.index, extensions); + if (data != null) + { + return new VKDevice(this, queueFamily, extensions, data); + } + #end + + return null; + } + + /** + Returns the first queue family that matches the requested capabilities. + **/ + public function getQueueFamily(requireGraphics:Bool = true, requirePresent:Bool = false, requireCompute:Bool = false, + requireTransfer:Bool = false):VKQueueFamilyInfo + { + for (queueFamily in queueFamilies) + { + if (queueFamily.matches(requireGraphics, requirePresent, requireCompute, requireTransfer)) + { + return queueFamily; + } + } + + return null; + } + + public inline function hasQueueFamily(requireGraphics:Bool = true, requirePresent:Bool = false, requireCompute:Bool = false, + requireTransfer:Bool = false):Bool + { + return getQueueFamily(requireGraphics, requirePresent, requireCompute, requireTransfer) != null; + } + + public function getMaxUsableSampleCount(requireDepth:Bool = false, requireStencil:Bool = false):Int + { + var counts = framebufferColorSampleCounts; + if (requireDepth) + { + counts &= framebufferDepthSampleCounts; + } + if (requireStencil) + { + counts &= framebufferStencilSampleCounts; + } + + for (sampleCount in [ + VK.SAMPLE_COUNT_64_BIT, + VK.SAMPLE_COUNT_32_BIT, + VK.SAMPLE_COUNT_16_BIT, + VK.SAMPLE_COUNT_8_BIT, + VK.SAMPLE_COUNT_4_BIT, + VK.SAMPLE_COUNT_2_BIT + ]) + { + if ((counts & sampleCount) != 0) + { + return sampleCount; + } + } + + return VK.SAMPLE_COUNT_1_BIT; + } + + public function supportsSampleCount(samples:Int, requireDepth:Bool = false, requireStencil:Bool = false):Bool + { + var counts = framebufferColorSampleCounts; + if (requireDepth) + { + counts &= framebufferDepthSampleCounts; + } + if (requireStencil) + { + counts &= framebufferStencilSampleCounts; + } + return (counts & samples) != 0; + } +} diff --git a/src/lime/graphics/vulkan/VKPipeline.hx b/src/lime/graphics/vulkan/VKPipeline.hx new file mode 100644 index 0000000000..6baa424b04 --- /dev/null +++ b/src/lime/graphics/vulkan/VKPipeline.hx @@ -0,0 +1,45 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKPipeline +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + public var layout(default, null):VKPipelineLayout; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, layout:VKPipelineLayout, handle:Int64) + { + this.device = device; + this.layout = layout; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_pipeline(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKPipelineCache.hx b/src/lime/graphics/vulkan/VKPipelineCache.hx new file mode 100644 index 0000000000..9214294458 --- /dev/null +++ b/src/lime/graphics/vulkan/VKPipelineCache.hx @@ -0,0 +1,61 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +import haxe.io.Bytes; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKPipelineCache +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_pipeline_cache(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + public function getData():Bytes + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var bytes = Bytes.alloc(0); + if (NativeCFFI.lime_vk_get_pipeline_cache_data(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, bytes)) + { + return bytes; + } + } + #end + + return null; + } +} diff --git a/src/lime/graphics/vulkan/VKPipelineLayout.hx b/src/lime/graphics/vulkan/VKPipelineLayout.hx new file mode 100644 index 0000000000..958a77c519 --- /dev/null +++ b/src/lime/graphics/vulkan/VKPipelineLayout.hx @@ -0,0 +1,43 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKPipelineLayout +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_pipeline_layout(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKQueue.hx b/src/lime/graphics/vulkan/VKQueue.hx new file mode 100644 index 0000000000..6e563c193a --- /dev/null +++ b/src/lime/graphics/vulkan/VKQueue.hx @@ -0,0 +1,124 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan queue retrieved from a `VKDevice`. +**/ +class VKQueue +{ + public var device(default, null):VKDevice; + public var familyIndex(default, null):Int; + public var handle(default, null):Int64; + public var index(default, null):Int; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64, familyIndex:Int, index:Int) + { + this.device = device; + this.handle = handle; + this.familyIndex = familyIndex; + this.index = index; + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + /** + Presents an acquired swapchain image on this queue. + **/ + public function present(swapchain:VKSwapchain, imageIndex:Int, waitSemaphore:VKSemaphore = null):Int + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && swapchain != null && swapchain.isValid()) + { + var waitSemaphoreHandle = (waitSemaphore != null && waitSemaphore.isValid()) ? waitSemaphore.handle : Int64.ofInt(0); + return NativeCFFI.lime_vk_queue_present(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, swapchain.handle.high, swapchain.handle.low, imageIndex, + waitSemaphoreHandle.high, waitSemaphoreHandle.low); + } + #end + + return VK.ERROR_INITIALIZATION_FAILED; + } + + /** + Submits one command buffer to this queue. A fence may be provided to track + completion from the CPU. + **/ + public function submit(commandBuffer:VKCommandBuffer, fence:VKFence = null):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && commandBuffer != null && commandBuffer.isValid()) + { + var fenceHigh = (fence != null && fence.isValid()) ? fence.handle.high : 0; + var fenceLow = (fence != null && fence.isValid()) ? fence.handle.low : 0; + + return NativeCFFI.lime_vk_queue_submit(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, commandBuffer.handle.high, commandBuffer.handle.low, fenceHigh, fenceLow); + } + #end + + return false; + } + + /** + Submits one command buffer with optional acquire/render/present sync. + This preserves the simple `submit(commandBuffer, fence)` path while + exposing the explicit wait/signal pieces renderers need per frame. + **/ + public function submitSynced(commandBuffer:VKCommandBuffer, waitSemaphore:VKSemaphore = null, signalSemaphore:VKSemaphore = null, fence:VKFence = null, + waitStageMask:Int = VK.PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT):Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid() && commandBuffer != null && commandBuffer.isValid()) + { + var waitHandle = waitSemaphore != null && waitSemaphore.isValid() ? waitSemaphore.handle : Int64.ofInt(0); + var signalHandle = signalSemaphore != null && signalSemaphore.isValid() ? signalSemaphore.handle : Int64.ofInt(0); + var fenceHandle = fence != null && fence.isValid() ? fence.handle : Int64.ofInt(0); + var state = [ + waitHandle.high, + waitHandle.low, + waitStageMask, + signalHandle.high, + signalHandle.low, + fenceHandle.high, + fenceHandle.low + ]; + + return NativeCFFI.lime_vk_queue_submit_synced(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low, commandBuffer.handle.high, commandBuffer.handle.low, state); + } + #end + + return false; + } + + /** + Blocks until this queue has completed all submitted work. + **/ + public function waitIdle():Bool + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + return NativeCFFI.lime_vk_queue_wait_idle(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + } + #end + + return false; + } +} diff --git a/src/lime/graphics/vulkan/VKQueueFamilyInfo.hx b/src/lime/graphics/vulkan/VKQueueFamilyInfo.hx new file mode 100644 index 0000000000..d80c4ed39c --- /dev/null +++ b/src/lime/graphics/vulkan/VKQueueFamilyInfo.hx @@ -0,0 +1,41 @@ +package lime.graphics.vulkan; + +/** + Describes one queue family on a Vulkan physical device. +**/ +class VKQueueFamilyInfo +{ + public var index(default, null):Int; + public var flags(default, null):Int; + public var queueCount(default, null):Int; + public var timestampValidBits(default, null):Int; + public var supportsGraphics(default, null):Bool; + public var supportsCompute(default, null):Bool; + public var supportsTransfer(default, null):Bool; + public var supportsPresent(default, null):Bool; + + @:allow(lime.graphics.vulkan.VKPhysicalDevice) + private function new(data:Dynamic) + { + index = data.index; + flags = data.flags; + queueCount = data.queueCount; + timestampValidBits = data.timestampValidBits; + supportsGraphics = data.supportsGraphics; + supportsCompute = data.supportsCompute; + supportsTransfer = data.supportsTransfer; + supportsPresent = data.supportsPresent; + } + + /** + Checks whether this queue family satisfies a requested capability set. + **/ + public inline function matches(requireGraphics:Bool = false, requirePresent:Bool = false, requireCompute:Bool = false, requireTransfer:Bool = false):Bool + { + if (requireGraphics && !supportsGraphics) return false; + if (requirePresent && !supportsPresent) return false; + if (requireCompute && !supportsCompute) return false; + if (requireTransfer && !supportsTransfer) return false; + return true; + } +} diff --git a/src/lime/graphics/vulkan/VKRenderPass.hx b/src/lime/graphics/vulkan/VKRenderPass.hx new file mode 100644 index 0000000000..fa0f580e70 --- /dev/null +++ b/src/lime/graphics/vulkan/VKRenderPass.hx @@ -0,0 +1,53 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKRenderPass +{ + public var colorFormat(default, null):Int; + public var depthStencilFormat(default, null):Int; + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + public var hasResolve(default, null):Bool; + public var resolveFormat(default, null):Int; + public var samples(default, null):Int; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64, colorFormat:Int, depthStencilFormat:Int, samples:Int, resolveFormat:Int) + { + this.device = device; + this.handle = handle; + this.colorFormat = colorFormat; + this.depthStencilFormat = depthStencilFormat; + this.samples = samples; + this.resolveFormat = resolveFormat; + this.hasResolve = resolveFormat != VK.FORMAT_UNDEFINED; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_render_pass(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKRenderer.hx b/src/lime/graphics/vulkan/VKRenderer.hx new file mode 100644 index 0000000000..25ca3651b6 --- /dev/null +++ b/src/lime/graphics/vulkan/VKRenderer.hx @@ -0,0 +1,152 @@ +package lime.graphics.vulkan; + +import lime.graphics.Image; +#if (!lime_doc_gen || lime_cffi) +import lime.system.CFFI; +#end +#if (!lime_doc_gen || lime_cffi) +import lime.system.CFFIPointer; +#end +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + Lime's managed Vulkan validation renderer. + + This is useful for smoke tests and samples, but application renderers should + build on `VK` handles such as `VKInstance`, `VKDevice`, and `VKQueue`. +**/ +class VKRenderer +{ + public var info(get, never):String; + public var isValid(get, never):Bool; + public var lastError(get, never):String; + + private var __handle:#if (!lime_doc_gen || lime_cffi) CFFIPointer #else Dynamic #end; + private var __info:String; + + @:allow(lime.graphics.VulkanRenderContext) + private function new(handle:#if (!lime_doc_gen || lime_cffi) CFFIPointer #else Dynamic #end) + { + __handle = handle; + __info = ""; + + #if (!macro && lime_cffi) + if (__handle != null) + { + refreshInfo(); + } + #end + } + + public function dispose():Void + { + #if (!macro && lime_cffi) + if (__handle != null) + { + NativeCFFI.lime_vulkan_renderer_destroy(__handle); + __handle = null; + } + #end + } + + public function render(red:Float, green:Float, blue:Float, alpha:Float = 1.0):Bool + { + #if (!macro && lime_cffi) + if (__handle != null) + { + return NativeCFFI.lime_vulkan_renderer_render(__handle, red, green, blue, alpha); + } + #end + + return false; + } + + public function refreshInfo():String + { + #if (!macro && lime_cffi) + if (__handle != null) + { + var value:Dynamic = NativeCFFI.lime_vulkan_renderer_get_info(__handle); + __info = (value != null) ? CFFI.stringValue(value) : ""; + } + #end + + return __info; + } + + public function setOverlayImage(image:Image, x:Int, y:Int):Bool + { + #if (!macro && lime_cffi) + if (__handle != null) + { + if (image == null) + { + return NativeCFFI.lime_vulkan_renderer_clear_overlay(__handle); + } + + if (image.buffer != null && image.width > 0 && image.height > 0) + { + return NativeCFFI.lime_vulkan_renderer_set_overlay(__handle, image.data.toBytes(), image.width, image.height, x, y); + } + } + #end + + return false; + } + + public function clearOverlay():Bool + { + #if (!macro && lime_cffi) + if (__handle != null) + { + return NativeCFFI.lime_vulkan_renderer_clear_overlay(__handle); + } + #end + + return false; + } + + public function resize():Bool + { + #if (!macro && lime_cffi) + if (__handle != null) + { + return NativeCFFI.lime_vulkan_renderer_resize(__handle); + } + #end + + return false; + } + + public static function getLastError():String + { + #if (!macro && lime_cffi) + var value:Dynamic = NativeCFFI.lime_vulkan_renderer_get_last_error(); + if (value != null) + { + return CFFI.stringValue(value); + } + #end + + return ""; + } + + private inline function get_info():String + { + return __info; + } + + private inline function get_isValid():Bool + { + return __handle != null; + } + + private inline function get_lastError():String + { + return getLastError(); + } +} diff --git a/src/lime/graphics/vulkan/VKSampler.hx b/src/lime/graphics/vulkan/VKSampler.hx new file mode 100644 index 0000000000..7c3cbafd67 --- /dev/null +++ b/src/lime/graphics/vulkan/VKSampler.hx @@ -0,0 +1,43 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKSampler +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_sampler(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKSemaphore.hx b/src/lime/graphics/vulkan/VKSemaphore.hx new file mode 100644 index 0000000000..9301dfc3c6 --- /dev/null +++ b/src/lime/graphics/vulkan/VKSemaphore.hx @@ -0,0 +1,46 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan semaphore used for GPU/GPU synchronization. +**/ +class VKSemaphore +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_semaphore(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKShaderModule.hx b/src/lime/graphics/vulkan/VKShaderModule.hx new file mode 100644 index 0000000000..09edfc1411 --- /dev/null +++ b/src/lime/graphics/vulkan/VKShaderModule.hx @@ -0,0 +1,43 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +class VKShaderModule +{ + public var device(default, null):VKDevice; + public var handle(default, null):Int64; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, handle:Int64) + { + this.device = device; + this.handle = handle; + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_shader_module(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } +} diff --git a/src/lime/graphics/vulkan/VKSurface.hx b/src/lime/graphics/vulkan/VKSurface.hx new file mode 100644 index 0000000000..f6166a3e41 --- /dev/null +++ b/src/lime/graphics/vulkan/VKSurface.hx @@ -0,0 +1,51 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +import lime.graphics.VulkanRenderContext; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A lightweight managed `VkSurfaceKHR` wrapper for the current Lime window. +**/ +class VKSurface +{ + public var context(default, null):VulkanRenderContext; + public var instance(default, null):VKInstance; + public var high(default, null):Int; + public var low(default, null):Int; + + @:allow(lime.graphics.vulkan.VKInstance) + private function new(context:VulkanRenderContext, instance:VKInstance, high:Int, low:Int) + { + this.context = context; + this.instance = instance; + this.high = high; + this.low = low; + } + + public function dispose():Void + { + #if (!macro && lime_cffi) + if (context != null && instance != null && instance.isValid() && (high != 0 || low != 0)) + { + NativeCFFI.lime_vk_destroy_surface(context.__windowHandle, instance.handle.high, instance.handle.low, high, low); + high = 0; + low = 0; + } + #end + } + + public inline function isValid():Bool + { + return high != 0 || low != 0; + } + + public inline function toInt64():Int64 + { + return Int64.make(high, low); + } +} diff --git a/src/lime/graphics/vulkan/VKSwapchain.hx b/src/lime/graphics/vulkan/VKSwapchain.hx new file mode 100644 index 0000000000..089f38adcd --- /dev/null +++ b/src/lime/graphics/vulkan/VKSwapchain.hx @@ -0,0 +1,139 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +#if (!lime_doc_gen || lime_cffi) +import lime._internal.backend.native.NativeCFFI; +#end + +@:access(lime.graphics.VulkanRenderContext) +@:access(lime._internal.backend.native.NativeCFFI) +/** + A Vulkan swapchain created for a Lime window surface. +**/ +class VKSwapchain +{ + public var colorSpace(default, null):Int; + public var device(default, null):VKDevice; + public var format(default, null):Int; + public var handle(default, null):Int64; + public var height(default, null):Int; + public var imageCount(default, null):Int; + public var images(default, null):Array; + public var presentMode(default, null):Int; + public var surface(default, null):VKSurface; + public var width(default, null):Int; + + @:allow(lime.graphics.vulkan.VKDevice) + private function new(device:VKDevice, surface:VKSurface, data:Dynamic) + { + this.device = device; + this.surface = surface; + handle = VK.__makeHandle(data.handle); + format = data.format; + colorSpace = data.colorSpace; + width = data.width; + height = data.height; + imageCount = data.imageCount; + presentMode = data.presentMode; + images = []; + refreshImages(); + } + + /** + Acquires the next presentable image from the swapchain. + **/ + public function acquireNextImage(semaphore:VKSemaphore = null, fence:VKFence = null, timeout:Int64 = null):VKAcquireResult + { + if (timeout == null) + { + timeout = Int64.make(-1, -1); + } + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var semaphoreHandle = (semaphore != null && semaphore.isValid()) ? semaphore.handle : Int64.ofInt(0); + var fenceHandle = (fence != null && fence.isValid()) ? fence.handle : Int64.ofInt(0); + var data:Dynamic = NativeCFFI.lime_vk_acquire_next_image(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low, timeout.high, timeout.low, semaphoreHandle.high, + semaphoreHandle.low, fenceHandle.high, fenceHandle.low); + + if (data != null) + { + return new VKAcquireResult(data.result, data.imageIndex); + } + } + #end + + return new VKAcquireResult(VK.ERROR_INITIALIZATION_FAILED, -1); + } + + public function dispose():Void + { + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + NativeCFFI.lime_vk_destroy_swapchain(device.instance.context.__windowHandle, device.instance.handle.high, device.instance.handle.low, + device.handle.high, device.handle.low, handle.high, handle.low); + handle = Int64.ofInt(0); + images = []; + imageCount = 0; + } + #end + } + + public inline function get():Int64 + { + return handle; + } + + public inline function isValid():Bool + { + return !VK.__isZero(handle); + } + + public function refreshImages():Array + { + images = []; + imageCount = 0; + + #if (!macro && lime_cffi && lime_vulkan) + if (isValid() && device != null && device.isValid()) + { + var data:Dynamic = NativeCFFI.lime_vk_get_swapchain_images(device.instance.context.__windowHandle, device.instance.handle.high, + device.instance.handle.low, device.handle.high, device.handle.low, handle.high, handle.low); + + if (data != null) + { + var length:Int = untyped data.length; + for (i in 0...length) + { + images.push(new VKImage(this, VK.__makeHandle(untyped data[i]), i)); + } + imageCount = images.length; + } + } + #end + + return images; + } + + /** + Creates a replacement swapchain using this swapchain as the old handle. + Dispose the old swapchain after any in-flight work has finished. + **/ + public function recreate(width:Int = 0, height:Int = 0, presentMode:Int = -1):VKSwapchain + { + if (presentMode < 0) + { + presentMode = this.presentMode; + } + + if (device == null) + { + return null; + } + + return device.createSwapchain(surface, width, height, presentMode, this); + } +} diff --git a/src/lime/graphics/vulkan/VKUploadRing.hx b/src/lime/graphics/vulkan/VKUploadRing.hx new file mode 100644 index 0000000000..772c7f6933 --- /dev/null +++ b/src/lime/graphics/vulkan/VKUploadRing.hx @@ -0,0 +1,106 @@ +package lime.graphics.vulkan; + +import haxe.Int64; +import haxe.io.Bytes; + +/** + A persistently mapped host-visible ring buffer for staging dynamic uploads. +**/ +class VKUploadRing +{ + public var buffer(default, null):VKBuffer; + public var byteCapacity(default, null):Int; + public var device(default, null):VKDevice; + public var frameIndex(default, null):Int = 0; + public var head(default, null):Int = 0; + + public function new(device:VKDevice, byteCapacity:Int, usage:Int = VK.BUFFER_USAGE_TRANSFER_SRC_BIT, + properties:Int = VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT) + { + this.device = device; + this.byteCapacity = byteCapacity; + + if (device != null && byteCapacity > 0) + { + buffer = device.createBufferWithMemory(Int64.ofInt(byteCapacity), usage | VK.BUFFER_USAGE_TRANSFER_SRC_BIT, properties); + if (buffer != null && !buffer.map(Int64.ofInt(0), Int64.ofInt(byteCapacity))) + { + buffer.dispose(true); + buffer = null; + } + } + } + + public function beginFrame(frameIndex:Int):Void + { + this.frameIndex = frameIndex; + head = 0; + } + + public function reserve(byteCount:Int, alignment:Int):VKUploadSlice + { + if (!isValid() || byteCount <= 0) + { + return null; + } + if (alignment <= 0) + { + alignment = 1; + } + + var aligned = __align(head, alignment); + if (aligned + byteCount > byteCapacity) + { + return null; + } + + head = aligned + byteCount; + return new VKUploadSlice(buffer, Int64.ofInt(aligned), byteCount, frameIndex); + } + + public function writeBytes(slice:VKUploadSlice, bytes:Bytes, srcOffset:Int = 0, length:Int = -1):Bool + { + if (slice == null || slice.buffer != buffer || bytes == null) + { + return false; + } + if (length < 0) + { + length = bytes.length - srcOffset; + } + if (length < 0 || length > slice.size) + { + return false; + } + return buffer.writeBytes(bytes, srcOffset, length, slice.offset); + } + + public function flush():Bool + { + return isValid() ? buffer.flush(Int64.ofInt(0), Int64.ofInt(0)) : false; + } + + public function invalidate():Bool + { + return isValid() ? buffer.invalidate(Int64.ofInt(0), Int64.ofInt(0)) : false; + } + + public function dispose():Void + { + if (buffer != null) + { + buffer.dispose(true); + buffer = null; + } + } + + public inline function isValid():Bool + { + return buffer != null && buffer.isValid(); + } + + private inline function __align(value:Int, alignment:Int):Int + { + return Std.int((value + alignment - 1) / alignment) * alignment; + } +} diff --git a/src/lime/graphics/vulkan/VKUploadSlice.hx b/src/lime/graphics/vulkan/VKUploadSlice.hx new file mode 100644 index 0000000000..b0d9b0d8c9 --- /dev/null +++ b/src/lime/graphics/vulkan/VKUploadSlice.hx @@ -0,0 +1,23 @@ +package lime.graphics.vulkan; + +import haxe.Int64; + +/** + A reserved range in a `VKUploadRing`. +**/ +class VKUploadSlice +{ + public var buffer(default, null):VKBuffer; + public var frameIndex(default, null):Int; + public var offset(default, null):Int64; + public var size(default, null):Int; + + @:allow(lime.graphics.vulkan.VKUploadRing) + private function new(buffer:VKBuffer, offset:Int64, size:Int, frameIndex:Int) + { + this.buffer = buffer; + this.offset = offset; + this.size = size; + this.frameIndex = frameIndex; + } +} diff --git a/src/lime/graphics/vulkan/VKVertexAttribute.hx b/src/lime/graphics/vulkan/VKVertexAttribute.hx new file mode 100644 index 0000000000..4a1641c077 --- /dev/null +++ b/src/lime/graphics/vulkan/VKVertexAttribute.hx @@ -0,0 +1,17 @@ +package lime.graphics.vulkan; + +class VKVertexAttribute +{ + public var binding:Int; + public var format:Int; + public var location:Int; + public var offset:Int; + + public function new(location:Int, binding:Int, format:Int, offset:Int) + { + this.location = location; + this.binding = binding; + this.format = format; + this.offset = offset; + } +} diff --git a/src/lime/graphics/vulkan/VKVertexBinding.hx b/src/lime/graphics/vulkan/VKVertexBinding.hx new file mode 100644 index 0000000000..071a35139e --- /dev/null +++ b/src/lime/graphics/vulkan/VKVertexBinding.hx @@ -0,0 +1,15 @@ +package lime.graphics.vulkan; + +class VKVertexBinding +{ + public var binding:Int; + public var inputRate:Int; + public var stride:Int; + + public function new(binding:Int, stride:Int, inputRate:Int = VK.VERTEX_INPUT_RATE_VERTEX) + { + this.binding = binding; + this.stride = stride; + this.inputRate = inputRate; + } +} diff --git a/src/lime/math/Matrix3.hx b/src/lime/math/Matrix3.hx index 330cad97c9..15aedcbdd1 100644 --- a/src/lime/math/Matrix3.hx +++ b/src/lime/math/Matrix3.hx @@ -70,9 +70,15 @@ abstract Matrix3(Float32Array) to Float32Array { // Column-major order means adjacent values form a column, not a row. this = new Float32Array([ - a, b, 0, // column 0 - c, d, 0, // column 1 - tx, ty, 1 // column 2 + a, + b, + 0, // column 0 + c, + d, + 0, // column 1 + tx, + ty, + 1 // column 2 ]); } @@ -561,7 +567,8 @@ abstract Matrix3(Float32Array) to Float32Array { return this[0]; } - inline function set_a(value: Float):Float + + inline function set_a(value:Float):Float { return this[0] = value; } @@ -570,7 +577,8 @@ abstract Matrix3(Float32Array) to Float32Array { return this[1]; } - inline function set_b(value: Float):Float + + inline function set_b(value:Float):Float { return this[1] = value; } @@ -579,7 +587,8 @@ abstract Matrix3(Float32Array) to Float32Array { return this[3]; } - inline function set_c(value: Float):Float + + inline function set_c(value:Float):Float { return this[3] = value; } @@ -588,7 +597,8 @@ abstract Matrix3(Float32Array) to Float32Array { return this[4]; } - inline function set_d(value: Float):Float + + inline function set_d(value:Float):Float { return this[4] = value; } @@ -597,7 +607,8 @@ abstract Matrix3(Float32Array) to Float32Array { return this[6]; } - inline function set_tx(value: Float):Float + + inline function set_tx(value:Float):Float { return this[6] = value; } @@ -606,7 +617,8 @@ abstract Matrix3(Float32Array) to Float32Array { return this[7]; } - inline function set_ty(value: Float):Float + + inline function set_ty(value:Float):Float { return this[7] = value; } diff --git a/src/lime/math/Matrix4.hx b/src/lime/math/Matrix4.hx index 4c70f38066..65807d478b 100644 --- a/src/lime/math/Matrix4.hx +++ b/src/lime/math/Matrix4.hx @@ -378,7 +378,7 @@ abstract Matrix4(Float32Array) from Float32Array to Float32Array this[14] = -(zNear + zFar) * sz; this[15] = 1; } - + /** Initializes this matrix with values for a perspective projection @param fov The field of view @@ -416,7 +416,7 @@ abstract Matrix4(Float32Array) from Float32Array to Float32Array this[12] = 0; this[13] = 0; this[14] = -2 * zFar * zNear / (zFar - zNear); - this[15] = 1; + this[15] = 0; } /** diff --git a/src/lime/media/AudioBuffer.hx b/src/lime/media/AudioBuffer.hx index 8d3756d268..b3cfa7e1d3 100644 --- a/src/lime/media/AudioBuffer.hx +++ b/src/lime/media/AudioBuffer.hx @@ -70,6 +70,7 @@ class AudioBuffer @:noCompletion private var __srcAudio:#if (js && html5) Audio #else Dynamic #end; @:noCompletion private var __srcBuffer:#if lime_cffi ALBuffer #else Dynamic #end; + @:noCompletion private var __srcBufferContext:Int; @:noCompletion private var __srcCustom:Dynamic; @:noCompletion private var __srcHowl:#if lime_howlerjs Howl #else Dynamic #end; @:noCompletion private var __isDisposed:Bool; @@ -135,7 +136,13 @@ class AudioBuffer } var audioBuffer = new AudioBuffer(); - audioBuffer.src = new Howl({src: [base64String], html5: true, preload: false}); + + #if force_html5_audio + audioBuffer.src = new Howl({src: [base64String], html5: true, preload: true}); + #else + audioBuffer.src = new Howl({src: [base64String], preload: true}); + #end + return audioBuffer; #elseif (lime_cffi && !macro) #if !cs @@ -181,7 +188,12 @@ class AudioBuffer #if (js && html5 && lime_howlerjs) var audioBuffer = new AudioBuffer(); - audioBuffer.src = new Howl({src: ["data:" + __getCodec(bytes) + ";base64," + Base64.encode(bytes)], html5: true, preload: false}); + + #if force_html5_audio + audioBuffer.src = new Howl({src: ["data:" + __getCodec(bytes) + ";base64," + Base64.encode(bytes)], html5: true, preload: true}); + #else + audioBuffer.src = new Howl({src: ["data:" + __getCodec(bytes) + ";base64," + Base64.encode(bytes)], preload: true}); + #end return audioBuffer; #elseif (lime_cffi && !macro) @@ -384,7 +396,6 @@ class AudioBuffer @return An `AudioBuffer` instance with the decoded audio data. **/ #if lime_vorbis - public static function fromVorbisFile(vorbisFile:VorbisFile):AudioBuffer { if (vorbisFile == null) return null; @@ -497,22 +508,19 @@ class AudioBuffer var promise = new Promise(); var request = new HTTPRequest(); - request.load(path) - .onProgress(promise.progress) - .onComplete(function(bytes) + request.load(path).onProgress(promise.progress).onComplete(function(bytes) + { + var buffer = fromBytesStream(bytes); + + if (buffer != null) { - var buffer = fromBytesStream(bytes); - - if (buffer != null) - { - promise.complete(buffer); - } - else - { - promise.error(""); - } - }) - .onError(promise.error); + promise.complete(buffer); + } + else + { + promise.error(""); + } + }).onError(promise.error); return promise.future; } @@ -682,7 +690,7 @@ class AudioBuffer } }).onError(function(_) { - __loadFromFilesStream(paths, promise, index + 1); + __loadFromFilesStream(paths, promise, index + 1); }); } diff --git a/src/lime/media/AudioInput.hx b/src/lime/media/AudioInput.hx new file mode 100644 index 0000000000..7fc3919d97 --- /dev/null +++ b/src/lime/media/AudioInput.hx @@ -0,0 +1,199 @@ +package lime.media; + +import haxe.io.Bytes; +import lime.app.Event; + +#if !lime_debug +@:fileXml('tags="haxe,release"') +@:noDebug +#end + +/** + The `AudioInput` class provides polling-based access to microphone or other + audio capture input. + + `AudioInput` reads raw PCM sample frames into a `Bytes` buffer. Use + `samplesAvailable` to determine how many sample frames can be read without + blocking, then call `read`. + + @see lime.media.AudioInputDevice + @see lime.media.AudioBuffer +**/ +class AudioInput +{ + /** + The backend's default audio input device, or `null` if capture is not + available. + **/ + public static var defaultDevice(get, never):AudioInputDevice; + + /** + The available audio input devices reported by the backend. + **/ + public static var devices(get, never):Array; + + /** + Whether audio input capture is supported by the current backend. + **/ + public static var isSupported(get, never):Bool; + + /** + The number of bits per sample used by this input. + **/ + public var bitsPerSample(default, null):Int; + + /** + The capture buffer size, in sample frames. + **/ + public var bufferSize(default, null):Int; + + /** + The number of capture channels. + **/ + public var channels(default, null):Int; + + /** + The audio input device used by this input. + **/ + public var device(default, null):AudioInputDevice; + + /** + An event that is dispatched if the backend reports that the input device + has disconnected. + **/ + public var onDisconnect = new EventVoid>(); + + /** + Whether this input is currently capturing. + **/ + public var running(default, null):Bool; + + /** + The capture sample rate, in Hz. + **/ + public var sampleRate(default, null):Int; + + /** + The number of sample frames currently available to read. + **/ + public var samplesAvailable(get, never):Int; + + @:noCompletion private var __backend:AudioInputBackend; + @:noCompletion private var __disposed:Bool; + + /** + Creates a new `AudioInput` instance. + + @param device The input device to use. If `null`, the backend default is used. + @param sampleRate The requested capture sample rate, in Hz. + @param channels The requested channel count. + @param bitsPerSample The requested bits per sample. + @param bufferSize The capture buffer size, in sample frames. + **/ + public function new(device:AudioInputDevice = null, sampleRate:Int = 44100, channels:Int = 1, bitsPerSample:Int = 16, bufferSize:Int = 4096) + { + this.device = device != null ? device : defaultDevice; + this.sampleRate = sampleRate > 0 ? sampleRate : 44100; + this.channels = channels; + this.bitsPerSample = bitsPerSample; + this.bufferSize = bufferSize > 0 ? bufferSize : 4096; + running = false; + + __backend = new AudioInputBackend(this); + } + + /** + Releases any resources used by this `AudioInput`. + **/ + public function dispose():Void + { + if (__disposed) + { + return; + } + + stop(); + __backend.dispose(); + __disposed = true; + } + + /** + Reads captured PCM sample frames into `buffer`. + + @param buffer The destination buffer. + @param samples The maximum number of sample frames to read. + @return The number of sample frames actually read. + **/ + public function read(buffer:Bytes, samples:Int):Int + { + if (__disposed) + { + return 0; + } + + return __backend.read(buffer, samples); + } + + /** + Starts audio capture. + + On backends that require asynchronous permission, such as HTML5, + `running` may become true after this method returns. + **/ + public function start():Void + { + if (__disposed || running) + { + return; + } + + running = __backend.start(); + } + + /** + Stops audio capture. + **/ + public function stop():Void + { + if (__disposed) + { + return; + } + + __backend.stop(); + running = false; + } + + @:noCompletion private static function get_defaultDevice():AudioInputDevice + { + return AudioInputBackend.getDefaultDevice(); + } + + @:noCompletion private static function get_devices():Array + { + return AudioInputBackend.getDevices(); + } + + @:noCompletion private static function get_isSupported():Bool + { + return AudioInputBackend.isSupported(); + } + + @:noCompletion private function get_samplesAvailable():Int + { + if (__disposed) + { + return 0; + } + + return __backend.getSamplesAvailable(); + } +} + +#if flash +@:noCompletion private typedef AudioInputBackend = lime._internal.backend.flash.FlashAudioInput; +#elseif (js && html5) +@:noCompletion private typedef AudioInputBackend = lime._internal.backend.html5.HTML5AudioInput; +#else +@:noCompletion private typedef AudioInputBackend = lime._internal.backend.native.NativeAudioInput; +#end diff --git a/src/lime/media/AudioInputDevice.hx b/src/lime/media/AudioInputDevice.hx new file mode 100644 index 0000000000..cfcf4a6ced --- /dev/null +++ b/src/lime/media/AudioInputDevice.hx @@ -0,0 +1,40 @@ +package lime.media; + +#if !lime_debug +@:fileXml('tags="haxe,release"') +@:noDebug +#end + +/** + The `AudioInputDevice` class describes an audio capture device that can be + used with `AudioInput`. + + @see lime.media.AudioInput +**/ +class AudioInputDevice +{ + /** + The backend identifier for this device, when one is available. + **/ + public var id(default, null):String; + + /** + Whether this device is the backend's default audio input device. + **/ + public var isDefault(default, null):Bool; + + /** + The user-visible name of this audio input device. + **/ + public var name(default, null):String; + + /** + Creates a new `AudioInputDevice` instance. + **/ + public function new(name:String = null, id:String = null, isDefault:Bool = false) + { + this.name = name; + this.id = id != null ? id : name; + this.isDefault = isDefault; + } +} diff --git a/src/lime/media/AudioManager.hx b/src/lime/media/AudioManager.hx index 8a085f253d..5001f7ab72 100644 --- a/src/lime/media/AudioManager.hx +++ b/src/lime/media/AudioManager.hx @@ -1,11 +1,16 @@ package lime.media; import haxe.Timer; +#if (lime_cffi && !macro && lime_openal) import lime._internal.backend.native.NativeCFFI; +import lime._internal.backend.native.NativeAudioSource; +#end +#if (!lime_doc_gen || lime_openal) import lime.media.openal.AL; import lime.media.openal.ALC; import lime.media.openal.ALContext; import lime.media.openal.ALDevice; +#end #if (js && html5) import js.Browser; #end @@ -18,6 +23,18 @@ import js.Browser; class AudioManager { public static var context:AudioContext; + @:noCompletion public static var __contextGeneration(default, null):Int = 0; + private static inline var OUTPUT_DEVICE_POLL_TIME:Int = 1000; + #if (!lime_doc_gen || lime_openal) + private static var outputDevice:ALDevice; + #else + private static var outputDevice:Dynamic; + #end + private static var outputDeviceHasDisconnectExt:Bool; + private static var outputDeviceName:String; + private static var outputDevicePreferredName:String; + private static var outputDeviceRecovering:Bool; + private static var outputDeviceTimer:Timer; public static function init(context:AudioContext = null) { @@ -39,12 +56,14 @@ class AudioManager var ctx = alc.createContext(device); alc.makeContextCurrent(ctx); alc.processContext(ctx); + __contextGeneration++; } } #end } AudioManager.context = context; + setupOutputDeviceRecovery(); #if (lime_cffi && !macro && lime_openal && (ios || tvos || mac)) var timer = new Timer(100); @@ -77,6 +96,8 @@ class AudioManager public static function shutdown():Void { #if !lime_doc_gen + stopOutputDeviceRecovery(); + if (context != null && context.type == OPENAL) { var alc = context.openal; @@ -120,4 +141,208 @@ class AudioManager } #end } + + private static function closeOpenALContext():Void + { + #if !lime_doc_gen + if (context == null || context.type != OPENAL) + { + return; + } + + var alc = context.openal; + var currentContext = alc.getCurrentContext(); + + if (currentContext != null) + { + var device = alc.getContextsDevice(currentContext); + alc.makeContextCurrent(null); + alc.destroyContext(currentContext); + + if (device != null) + { + alc.closeDevice(device); + } + } + #end + } + + private static function getCurrentOutputDeviceName():String + { + #if (lime_cffi && !macro && lime_openal) + var name = ALC.getString(null, ALC.DEFAULT_ALL_DEVICES_SPECIFIER); + + if (name == null || name.length == 0) + { + name = ALC.getString(null, ALC.DEFAULT_DEVICE_SPECIFIER); + } + + return name; + #else + return null; + #end + } + + private static function isOutputDeviceConnected():Bool + { + #if (lime_cffi && !macro && lime_openal) + if (outputDevice == null || !outputDeviceHasDisconnectExt) + { + return true; + } + + var connected = ALC.getIntegerv(outputDevice, ALC.CONNECTED, 1); + return connected == null || connected.length == 0 || connected[0] == ALC.TRUE; + #else + return true; + #end + } + + private static function openOpenALContext(deviceName:String = null):Bool + { + #if !lime_doc_gen + if (context == null || context.type != OPENAL) + { + return false; + } + + var alc = context.openal; + var device = alc.openDevice(deviceName); + + if (device == null && deviceName != null) + { + device = alc.openDevice(); + } + + if (device == null) + { + return false; + } + + var currentContext = alc.createContext(device); + + if (currentContext == null) + { + alc.closeDevice(device); + return false; + } + + alc.makeContextCurrent(currentContext); + alc.processContext(currentContext); + __contextGeneration++; + return true; + #else + return false; + #end + } + + private static function recoverOutputDevice(deviceName:String = null):Void + { + #if (lime_cffi && !macro && lime_openal) + if (outputDeviceRecovering || context == null || context.type != OPENAL) + { + return; + } + + outputDeviceRecovering = true; + NativeAudioSource.prepareAudioContextRecovery(); + closeOpenALContext(); + + if (openOpenALContext(deviceName)) + { + refreshOutputDeviceRecovery(); + NativeAudioSource.restoreAudioContextRecovery(); + } + + outputDeviceRecovering = false; + #end + } + + private static function refreshOutputDeviceRecovery():Void + { + #if (lime_cffi && !macro && lime_openal) + if (context == null || context.type != OPENAL) + { + outputDevice = null; + outputDeviceHasDisconnectExt = false; + outputDeviceName = null; + return; + } + + var alc = context.openal; + var currentContext = alc.getCurrentContext(); + outputDevice = currentContext != null ? alc.getContextsDevice(currentContext) : null; + outputDeviceHasDisconnectExt = outputDevice != null && ALC.isExtensionPresent(outputDevice, "ALC_EXT_disconnect"); + outputDeviceName = getCurrentOutputDeviceName(); + #end + } + + private static function setupOutputDeviceRecovery():Void + { + #if (lime_cffi && !macro && lime_openal) + stopOutputDeviceRecovery(); + + if (context == null || context.type != OPENAL) + { + return; + } + + refreshOutputDeviceRecovery(); + + if (!outputDeviceHasDisconnectExt) + { + return; + } + + outputDevicePreferredName = outputDeviceName; + // ALC_EXT_disconnect exposes disconnect state, but not device-change events. + // Polling is kept as the compatibility fallback for that older API. + outputDeviceTimer = new Timer(OUTPUT_DEVICE_POLL_TIME); + outputDeviceTimer.run = updateOutputDeviceRecovery; + #end + } + + private static function stopOutputDeviceRecovery():Void + { + if (outputDeviceTimer != null) + { + outputDeviceTimer.stop(); + outputDeviceTimer = null; + } + + outputDevice = null; + outputDeviceHasDisconnectExt = false; + outputDeviceName = null; + outputDevicePreferredName = null; + outputDeviceRecovering = false; + } + + private static function updateOutputDeviceRecovery():Void + { + #if (lime_cffi && !macro && lime_openal) + if (outputDeviceRecovering || context == null || context.type != OPENAL) + { + return; + } + + if (!isOutputDeviceConnected()) + { + recoverOutputDevice(); + return; + } + + if (outputDevicePreferredName != null && outputDeviceName != outputDevicePreferredName) + { + var currentName = getCurrentOutputDeviceName(); + + if (currentName == outputDevicePreferredName) + { + recoverOutputDevice(outputDevicePreferredName); + return; + } + + outputDeviceName = currentName; + } + #end + } } diff --git a/src/lime/media/AudioSource.hx b/src/lime/media/AudioSource.hx index 2ccc9b1465..5e883167ad 100644 --- a/src/lime/media/AudioSource.hx +++ b/src/lime/media/AudioSource.hx @@ -9,6 +9,7 @@ import lime.math.Vector4; @:fileXml('tags="haxe,release"') @:noDebug #end + /** The `AudioSource` class provides a way to control audio playback in a Lime application. It allows for playing, pausing, and stopping audio, as well as controlling various @@ -24,7 +25,7 @@ class AudioSource An event that is dispatched when the audio playback is complete. **/ public var onComplete = new EventVoid>(); - + /** The `AudioBuffer` associated with this `AudioSource`. **/ @@ -78,16 +79,13 @@ class AudioSource { this.buffer = buffer; this.offset = offset; - __backend = new AudioSourceBackend(this); if (length != null && length != 0) { this.length = length; } - this.loops = loops; - if (buffer != null) { init(); diff --git a/src/lime/media/OpenALAudioContext.hx b/src/lime/media/OpenALAudioContext.hx index d731f72397..b7d0cc90e6 100644 --- a/src/lime/media/OpenALAudioContext.hx +++ b/src/lime/media/OpenALAudioContext.hx @@ -8,6 +8,7 @@ import lime.media.openal.ALContext; import lime.media.openal.ALDevice; import lime.media.openal.ALSource; import lime.utils.ArrayBufferView; +import haxe.io.Bytes; #if !lime_debug @:fileXml('tags="haxe,release"') @@ -90,6 +91,9 @@ class OpenALAudioContext public var ENUMERATE_ALL_EXT:Int = 1; public var DEFAULT_ALL_DEVICES_SPECIFIER:Int = 0x1012; public var ALL_DEVICES_SPECIFIER:Int = 0x1013; + public var CAPTURE_DEVICE_SPECIFIER:Int = 0x310; + public var CAPTURE_DEFAULT_DEVICE_SPECIFIER:Int = 0x311; + public var CAPTURE_SAMPLES:Int = 0x312; @:noCompletion private function new() {} @@ -403,14 +407,23 @@ class OpenALAudioContext public function getString(param:Int, device:ALDevice = null):String { - if (device == null) + if (device != null) { - return AL.getString(param); + return ALC.getString(device, param); } - else + + if (param == DEFAULT_DEVICE_SPECIFIER + || param == DEVICE_SPECIFIER + || param == ALC.EXTENSIONS + || param == DEFAULT_ALL_DEVICES_SPECIFIER + || param == ALL_DEVICES_SPECIFIER + || param == CAPTURE_DEVICE_SPECIFIER + || param == CAPTURE_DEFAULT_DEVICE_SPECIFIER) { - return ALC.getString(device, param); + return ALC.getString(cast null, param); } + + return AL.getString(param); } public function isBuffer(buffer:ALBuffer):Bool @@ -423,9 +436,14 @@ class OpenALAudioContext return AL.isEnabled(capability); } - public function isExtensionPresent(extname:String):Bool + public function isExtensionPresent(extname:String, device:ALDevice = null):Bool { - return AL.isExtensionPresent(extname); + if (extname == null) + { + return false; + } + + return device != null ? ALC.isExtensionPresent(device, extname) : AL.isExtensionPresent(extname); } public function isSource(source:ALSource):Bool @@ -587,5 +605,30 @@ class OpenALAudioContext { ALC.suspendContext(context); } + + public function captureOpenDevice(deviceName:String = null, frequency:Int, format:Int, bufferSize:Int):ALDevice + { + return ALC.captureOpenDevice(deviceName, frequency, format, bufferSize); + } + + public function captureCloseDevice(device:ALDevice):Bool + { + return ALC.captureCloseDevice(device); + } + + public function captureStart(device:ALDevice):Void + { + ALC.captureStart(device); + } + + public function captureStop(device:ALDevice):Void + { + ALC.captureStop(device); + } + + public function captureSamples(device:ALDevice, buffer:Bytes, samples:Int):Void + { + ALC.captureSamples(device, buffer, samples); + } } #end diff --git a/src/lime/media/openal/ALC.hx b/src/lime/media/openal/ALC.hx index 4cd4379d21..a897a232a8 100644 --- a/src/lime/media/openal/ALC.hx +++ b/src/lime/media/openal/ALC.hx @@ -4,6 +4,7 @@ package lime.media.openal; import lime._internal.backend.native.NativeCFFI; import lime.system.CFFI; import lime.system.CFFIPointer; +import haxe.io.Bytes; #if !lime_debug @:fileXml('tags="haxe,release"') @@ -33,6 +34,10 @@ class ALC public static inline var ENUMERATE_ALL_EXT:Int = 1; public static inline var DEFAULT_ALL_DEVICES_SPECIFIER:Int = 0x1012; public static inline var ALL_DEVICES_SPECIFIER:Int = 0x1013; + public static inline var CAPTURE_DEVICE_SPECIFIER:Int = 0x310; + public static inline var CAPTURE_DEFAULT_DEVICE_SPECIFIER:Int = 0x311; + public static inline var CAPTURE_SAMPLES:Int = 0x312; + public static inline var CONNECTED:Int = 0x313; public static function closeDevice(device:ALDevice):Bool { @@ -202,5 +207,63 @@ class ALC NativeCFFI.lime_alc_suspend_context(context); #end } + + public static function isExtensionPresent(device:ALDevice, extname:String):Bool + { + if (extname == null) + { + return false; + } + + #if (lime_cffi && lime_openal && !macro) + return NativeCFFI.lime_alc_is_extension_present(device, extname); + #else + return false; + #end + } + + public static function captureOpenDevice(deviceName:String = null, frequency:Int, format:Int, bufferSize:Int):ALDevice + { + #if (lime_cffi && lime_openal && !macro) + var handle = NativeCFFI.lime_alc_capture_open_device(deviceName, frequency, format, bufferSize); + + if (handle != null) + { + return new ALDevice(handle); + } + #end + + return null; + } + + public static function captureCloseDevice(device:ALDevice):Bool + { + #if (lime_cffi && lime_openal && !macro) + return NativeCFFI.lime_alc_capture_close_device(device); + #end + + return false; + } + + public static function captureStart(device:ALDevice):Void + { + #if (lime_cffi && lime_openal && !macro) + NativeCFFI.lime_alc_capture_start(device); + #end + } + + public static function captureStop(device:ALDevice):Void + { + #if (lime_cffi && lime_openal && !macro) + NativeCFFI.lime_alc_capture_stop(device); + #end + } + + public static function captureSamples(device:ALDevice, buffer:Bytes, samples:Int):Void + { + #if (lime_cffi && lime_openal && !macro) + NativeCFFI.lime_alc_capture_samples(device, buffer, samples); + #end + } } #end diff --git a/src/lime/net/HTTPRequest.hx b/src/lime/net/HTTPRequest.hx index 70c0ac8fe8..6703673b52 100644 --- a/src/lime/net/HTTPRequest.hx +++ b/src/lime/net/HTTPRequest.hx @@ -160,10 +160,13 @@ public function load(uri:String = null):Future } } -@:noCompletion class _HTTPRequestErrorResponse { +@:noCompletion class _HTTPRequestErrorResponse +{ public var error:Dynamic; public var responseData:T; - public function new(error:Dynamic, responseData:T) { + + public function new(error:Dynamic, responseData:T) + { this.error = error; this.responseData = responseData; } diff --git a/src/lime/system/BackgroundWorker.hx b/src/lime/system/BackgroundWorker.hx index 30d69d1ed8..df72812a36 100644 --- a/src/lime/system/BackgroundWorker.hx +++ b/src/lime/system/BackgroundWorker.hx @@ -14,7 +14,6 @@ import neko.vm.Deque; import neko.vm.Thread; #end #end - /** A `BackgroundWorker` allows the execution of a function on a background thread, avoiding the blocking of the main thread. This is particularly useful for long-running @@ -24,7 +23,7 @@ import neko.vm.Thread; - **Thread Support:** Only system targets (such as C++, Neko) support threading. - **Events:** The class uses the `Event` class to dispatch completion, error, and progress notifications. - + @see `ThreadPool` for more advanced threading capabilities, including thread safety, HTML5 threads, and more robust handling of tasks. **/ @@ -62,7 +61,7 @@ class BackgroundWorker Dispatched if an error occurs during the execution of the worker's task. **/ public var onError = new EventVoid>(); - + /** Dispatched periodically during the worker's task to provide progress updates. **/ @@ -154,7 +153,7 @@ class BackgroundWorker } #end } - + /** Sends a progress update message. @param message An optional message to pass to the `onProgress` event. diff --git a/src/lime/system/CFFI.hx b/src/lime/system/CFFI.hx index add385db32..20fb07e438 100644 --- a/src/lime/system/CFFI.hx +++ b/src/lime/system/CFFI.hx @@ -315,7 +315,10 @@ class CFFI var ndllFolder = __findNDLLFolder() + __sysName(); throw "Could not load lime.ndll. This file is provided with Lime's Haxelib releases, but not via Git. " + "Please copy it from Lime's latest Haxelib release into either " - + ndllFolder + " or " + ndllFolder + "64, as appropriate for your system. " + + ndllFolder + + " or " + + ndllFolder + + "64, as appropriate for your system. " + "Advanced users may run `lime rebuild cpp` instead." + (error != null ? '\nInternal error: $error' : ""); } diff --git a/src/lime/system/JNI.hx b/src/lime/system/JNI.hx index 8c1c4ad5bd..ed2007028b 100644 --- a/src/lime/system/JNI.hx +++ b/src/lime/system/JNI.hx @@ -17,7 +17,6 @@ import cpp.vm.Thread; import neko.vm.Thread; #end #end - using StringTools; /** @@ -51,12 +50,10 @@ class JNI private static function transformClassName(className:String):String { var parts:Array = className.split("."); - if (parts.length <= 1) - return className; + if (parts.length <= 1) return className; var nestedClassName:String = ""; - if (~/^[A-Z]/.match(parts[parts.length - 2])) - nestedClassName = "$" + parts.pop(); + if (~/^[A-Z]/.match(parts[parts.length - 2])) nestedClassName = "$" + parts.pop(); return parts.join("/") + nestedClassName; } @@ -430,8 +427,7 @@ class JNISafetyTools } // Don't modify functions lacking `@:runOnMainThread`. - if (field.meta == null || !Lambda.exists(field.meta, - function(meta) return meta.name == ":runOnMainThread")) + if (field.meta == null || !Lambda.exists(field.meta, function(meta) return meta.name == ":runOnMainThread")) { continue; } @@ -445,13 +441,12 @@ class JNISafetyTools // Make sure there's no return value. switch (f.ret) { - case macro:Void: + case macro :Void: // Good to go. case null: - f.ret = macro:Void; + f.ret = macro :Void; default: - Context.error("Expected return type Void, got " - + new haxe.macro.Printer().printComplexType(f.ret) + ".", field.pos); + Context.error("Expected return type Void, got " + new haxe.macro.Printer().printComplexType(f.ret) + ".", field.pos); } var args:Array = []; @@ -460,16 +455,12 @@ class JNISafetyTools args.push(macro $i{arg.name}); // Account for an unlikely edge case. - if (arg.name == field.name) - Context.error('${field.name}() should not take an argument named ${field.name}.', field.pos); + if (arg.name == field.name) Context.error('${field.name}() should not take an argument named ${field.name}.', field.pos); } // Check the thread before running the function. - f.expr = macro - if (!lime.system.JNI.JNISafetyTools.onMainThread()) - haxe.MainLoop.runInMainThread($i{field.name}.bind($a{args})) - else - ${f.expr}; + f.expr = macro if (!lime.system.JNI.JNISafetyTools.onMainThread()) haxe.MainLoop.runInMainThread($i{field.name}.bind($a{args})) else + ${f.expr}; default: } } diff --git a/src/lime/system/Orientation.hx b/src/lime/system/Orientation.hx index b3d076b908..34e5bfb95a 100644 --- a/src/lime/system/Orientation.hx +++ b/src/lime/system/Orientation.hx @@ -7,4 +7,4 @@ package lime.system; var LANDSCAPE_FLIPPED = 2; var PORTRAIT = 3; var PORTRAIT_FLIPPED = 4; -} \ No newline at end of file +} diff --git a/src/lime/system/System.hx b/src/lime/system/System.hx index e3a5f7c15a..25c1fca04a 100644 --- a/src/lime/system/System.hx +++ b/src/lime/system/System.hx @@ -252,17 +252,16 @@ class System #if android var getDisplaySafeArea = JNI.createStaticMethod("org/haxe/lime/GameActivity", "getDisplaySafeAreaInsets", "()[I"); var result = getDisplaySafeArea(); - display.safeArea = new Rectangle( - display.bounds.x + result[0], - display.bounds.y + result[1], - display.bounds.width - result[0] - result[2], - display.bounds.height - result[1] - result[3]); + display.safeArea = new Rectangle(display.bounds.x + + result[0], display.bounds.y + + result[1], display.bounds.width + - result[0] + - result[2], + display.bounds.height + - result[1] + - result[3]); #else - display.safeArea = new Rectangle( - displayInfo.safeArea.x, - displayInfo.safeArea.y, - displayInfo.safeArea.width, - displayInfo.safeArea.height); + display.safeArea = new Rectangle(displayInfo.safeArea.x, displayInfo.safeArea.y, displayInfo.safeArea.width, displayInfo.safeArea.height); #end #if ios @@ -328,7 +327,8 @@ class System display.dpi = Capabilities.screenDPI; display.currentMode = new DisplayMode(Std.int(Capabilities.screenResolutionX), Std.int(Capabilities.screenResolutionY), 60, ARGB32); #if air - switch (flash.Lib.current.stage.orientation) { + switch (flash.Lib.current.stage.orientation) + { case DEFAULT: display.orientation = PORTRAIT; case UPSIDE_DOWN: @@ -340,7 +340,6 @@ class System default: display.orientation = UNKNOWN; } - #else display.orientation = UNKNOWN; #end @@ -627,6 +626,8 @@ class System attributes.resizable = __parseBool(argValue); case "stencil", "stencil-buffer": attributes.context.stencil = __parseBool(argValue); + case "transparent": + attributes.transparent = __parseBool(argValue); // case "title": windowConfig.title = argValue; case "vsync", "vsync-mode": var vsyncMode = __parseVSyncMode(argValue); diff --git a/src/lime/system/ThreadPool.hx b/src/lime/system/ThreadPool.hx index 6e0150341f..8cb6a874f7 100644 --- a/src/lime/system/ThreadPool.hx +++ b/src/lime/system/ThreadPool.hx @@ -16,7 +16,6 @@ import neko.vm.Thread; #elseif html5 import lime._internal.backend.html5.HTML5Thread as Thread; import lime._internal.backend.html5.HTML5Thread.Transferable; - #if lime_threads_deque #error "lime_threads_deque is not yet supported in HTML5" #end @@ -474,21 +473,21 @@ class ThreadPool extends WorkOutput } } #end - else if (event.jobID != null) + else if (event.jobID != null) + { + #if (lime_threads && lime_threads_deque) + // `cancelJob()` can't remove the job from the queue, so instead it + // marks it to be canceled later. (And "later" is now.) + if (event.event == WORK && event.threadID != null) { - #if (lime_threads && lime_threads_deque) - // `cancelJob()` can't remove the job from the queue, so instead it - // marks it to be canceled later. (And "later" is now.) - if (event.event == WORK && event.threadID != null) - { - __threads[event.threadID].thread.sendMessage({event: IDLE}); - __queuedWorkEvents--; - } - #end - - activeJob = oldActiveJob; - return; + __threads[event.threadID].thread.sendMessage({event: IDLE}); + __queuedWorkEvents--; } + #end + + activeJob = oldActiveJob; + return; + } switch (event.event) { @@ -514,7 +513,7 @@ class ThreadPool extends WorkOutput } else { - message = (event.message:Exception).details(); + message = (event.message : Exception).details(); } } else @@ -553,8 +552,7 @@ class ThreadPool extends WorkOutput case EXIT: var threadData:ThreadData = __threads[event.threadID]; - if (threadData.jobID != null) - activeThreads--; + if (threadData.jobID != null) activeThreads--; else __idleThreads--; @@ -834,7 +832,6 @@ class ThreadPool extends WorkOutput } #if lime_threads - /** Handles a thread that just became idle. Depending on the circumstances, this may do one of three things: @@ -897,12 +894,13 @@ class ThreadPool extends WorkOutput job.doWork.makePortable(); #end - var threadEvent:ThreadEvent = { - event: WORK, - jobID: job.id, - doWork: job.doWork, - state: job.state - }; + var threadEvent:ThreadEvent = + { + event: WORK, + jobID: job.id, + doWork: job.doWork, + state: job.state + }; #if lime_threads_deque __multiThreadedQueue.add(threadEvent); @@ -991,19 +989,19 @@ class ThreadPool extends WorkOutput __threads[index] = {thread: thread, jobID: null}; __idleThreads++; - thread.sendMessage({ - #if !html5 - output: this, - #end - #if lime_threads_deque - queue: __multiThreadedQueue, - #end - threadID: index - }); + thread.sendMessage( + { + #if !html5 + output: this, + #end + #if lime_threads_deque + queue: __multiThreadedQueue, + #end + threadID: index + }); return thread; } - #end // Getters & Setters @@ -1026,7 +1024,7 @@ class ThreadPool extends WorkOutput private inline function get_idleThreads():Int { return __idleThreads - #if lime_threads - __queuedExitEvents #end; + #if lime_threads - __queuedExitEvents #end; } private inline function set___singleThreadedJobRunning(value:Bool):Bool @@ -1255,7 +1253,8 @@ private abstract JobQueue(Deque) from Deque } #end -private typedef ThreadArguments = { +private typedef ThreadArguments = +{ #if !html5 var output:WorkOutput; #end @@ -1268,7 +1267,8 @@ private typedef ThreadArguments = { }; #if lime_threads -private typedef ThreadData = { +private typedef ThreadData = +{ var thread:Thread; @:optional var jobID:Int; }; diff --git a/src/lime/text/Font.hx b/src/lime/text/Font.hx index 586a75d25a..090499423f 100644 --- a/src/lime/text/Font.hx +++ b/src/lime/text/Font.hx @@ -35,56 +35,55 @@ import haxe.io.Path; class Font { /** - * The ascender value of the font. - */ + * The ascender value of the font. + */ public var ascender:Int; - /** - * The descender value of the font. - */ + /** + * The descender value of the font. + */ public var descender:Int; /** - * The height of the font. - */ + * The height of the font. + */ public var height:Int; /** - * The name of the font. - */ + * The name of the font. + */ public var name(default, null):String; /** - * The number of glyphs in the font. - */ + * The number of glyphs in the font. + */ public var numGlyphs:Int; - public var src:Dynamic; /** - * The underline position of the font. - */ + * The underline position of the font. + */ public var underlinePosition:Int; /** - * The underline thickness of the font. - */ + * The underline thickness of the font. + */ public var underlineThickness:Int; /** - * The underline position of the font. - */ + * The underline position of the font. + */ public var strikethroughPosition:Int; /** - * The underline thickness of the font. - */ + * The underline thickness of the font. + */ public var strikethroughThickness:Int; /** - * The units per EM of the font. - */ + * The units per EM of the font. + */ public var unitsPerEM:Int; @:noCompletion private var __fontID:String; @@ -95,10 +94,10 @@ class Font @:noCompletion private var __init:Bool; /** - * Creates a new instance of a Font object. - * - * @param name Optional name of the font. - */ + * Creates a new instance of a Font object. + * + * @param name Optional name of the font. + */ public function new(name:String = null) { if (name != null) @@ -149,19 +148,18 @@ class Font } /** - * Decomposes the font into outline data. - * - * @param forceAutoHint When `true`, force auto-hinting for outline decomposition. - * When `false`, preserve the unhinted glyph outlines. - * @return An instance of `NativeFontData` that contains decomposed font outline information. - */ + * Decomposes the font into outline data. + * + * @param forceAutoHint When `true`, force auto-hinting for outline decomposition. + * When `false`, preserve the unhinted glyph outlines. + * @return An instance of `NativeFontData` that contains decomposed font outline information. + */ public function decompose(forceAutoHint:Bool = true):NativeFontData { #if (lime_cffi && !macro) if (src == null) throw "Uninitialized font handle."; - var data:Dynamic = forceAutoHint - ? NativeCFFI.lime_font_outline_decompose(src, 1024 * 20) - : NativeCFFI.lime_font_outline_decompose_no_hint(src, 1024 * 20); + var data:Dynamic = forceAutoHint ? NativeCFFI.lime_font_outline_decompose(src, + 1024 * 20) : NativeCFFI.lime_font_outline_decompose_no_hint(src, 1024 * 20); #if hl if (data != null) { @@ -176,11 +174,11 @@ class Font } /** - * Creates a Font instance from byte data. - * - * @param bytes The byte data containing the font. - * @return A `Font` instance. - */ + * Creates a Font instance from byte data. + * + * @param bytes The byte data containing the font. + * @return A `Font` instance. + */ public static function fromBytes(bytes:Bytes):Font { if (bytes == null) return null; @@ -196,11 +194,11 @@ class Font } /** - * Creates a Font instance from a file path. - * - * @param path The file path of the font. - * @return A `Font` instance. - */ + * Creates a Font instance from a file path. + * + * @param path The file path of the font. + * @return A `Font` instance. + */ public static function fromFile(path:String):Font { if (path == null) return null; @@ -216,22 +214,22 @@ class Font } /** - * Loads a Font from byte data asynchronously. - * - * @param bytes The byte data containing the font. - * @return A `Future` containing a `Font` instance. - */ + * Loads a Font from byte data asynchronously. + * + * @param bytes The byte data containing the font. + * @return A `Future` containing a `Font` instance. + */ public static function loadFromBytes(bytes:Bytes):Future { return Future.withValue(fromBytes(bytes)); } /** - * Loads a Font from a file path asynchronously. - * - * @param path The file path of the font. - * @return A `Future` containing a `Font` instance. - */ + * Loads a Font from a file path asynchronously. + * + * @param path The file path of the font. + * @return A `Future` containing a `Font` instance. + */ public static function loadFromFile(path:String):Future { var request = new HTTPRequest(); @@ -249,11 +247,11 @@ class Font } /** - * Loads a Font by its name asynchronously. - * - * @param path The name of the font. - * @return A `Future` containing a `Font` instance. - */ + * Loads a Font by its name asynchronously. + * + * @param path The name of the font. + * @return A `Future` containing a `Font` instance. + */ public static function loadFromName(path:String):Future { #if (js && html5) @@ -265,11 +263,11 @@ class Font } /** - * Retrieves a glyph from the font by a character. - * - * @param character The character whose glyph to retrieve. - * @return A `Glyph` instance representing the glyph of the character. - */ + * Retrieves a glyph from the font by a character. + * + * @param character The character whose glyph to retrieve. + * @return A `Glyph` instance representing the glyph of the character. + */ public function getGlyph(character:String):Glyph { #if (lime_cffi && !macro) @@ -280,16 +278,18 @@ class Font } /** - * Retrieves an array of glyphs for a set of characters. - * - * @param characters The string containing characters to retrieve glyphs for. - * @return An array of `Glyph` instances representing the glyphs of the characters. - */ + * Retrieves an array of glyphs for a set of characters. + * + * @param characters The string containing characters to retrieve glyphs for. + * @return An array of `Glyph` instances representing the glyphs of the characters. + */ public function getGlyphs(characters:String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^`'\"/\\&*()[]{}<>|:;_-+=?,. "):Array { #if (lime_cffi && !macro) #if hl - return [for (index in NativeCFFI.lime_font_get_glyph_indices(src, characters)) new Glyph(index)]; + return [ + for (index in NativeCFFI.lime_font_get_glyph_indices(src, characters)) new Glyph(index) + ]; #else return NativeCFFI.lime_font_get_glyph_indices(src, characters); #end @@ -299,11 +299,11 @@ class Font } /** - * Retrieves metrics for a given glyph. - * - * @param glyph The glyph whose metrics to retrieve. - * @return A `GlyphMetrics` instance containing the metrics of the glyph. - */ + * Retrieves metrics for a given glyph. + * + * @param glyph The glyph whose metrics to retrieve. + * @return A `GlyphMetrics` instance containing the metrics of the glyph. + */ public function getGlyphMetrics(glyph:Glyph):GlyphMetrics { #if (lime_cffi && !macro) @@ -322,26 +322,26 @@ class Font } /** - * Renders a specific glyph to an image. - * - * @param glyph The glyph to render. - * @param fontSize The size to render the glyph at. - * @return An `Image` instance representing the rendered glyph. - */ + * Renders a specific glyph to an image. + * + * @param glyph The glyph to render. + * @param fontSize The size to render the glyph at. + * @return An `Image` instance representing the rendered glyph. + */ public function renderGlyph(glyph:Glyph, fontSize:Int, dpi:Int = 96):Image { return renderGlyphWithLoadFlags(glyph, fontSize, dpi); } /** - * Renders a specific glyph to an image using explicit FreeType load flags. - * - * @param glyph The glyph to render. - * @param fontSize The size to render the glyph at. - * @param dpi The DPI used to size the glyph before rasterization. - * @param loadFlags Additional FreeType load flags to apply when rasterizing. - * @return An `Image` instance representing the rendered glyph. - */ + * Renders a specific glyph to an image using explicit FreeType load flags. + * + * @param glyph The glyph to render. + * @param fontSize The size to render the glyph at. + * @param dpi The DPI used to size the glyph before rasterization. + * @param loadFlags Additional FreeType load flags to apply when rasterizing. + * @return An `Image` instance representing the rendered glyph. + */ public function renderGlyphWithLoadFlags(glyph:Glyph, fontSize:Int, dpi:Int = 96, ?loadFlags:Int):Image { #if (lime_cffi && !macro) @@ -351,9 +351,8 @@ class Font var bytes:Bytes = Bytes.alloc(0); // Allocate some reasonable initial size // Call native function to render glyph and get byte data - bytes = loadFlags == null - ? NativeCFFI.lime_font_render_glyph(src, glyph, bytes) - : NativeCFFI.lime_font_render_glyph_with_flags(src, glyph, loadFlags, bytes); + bytes = loadFlags == null ? NativeCFFI.lime_font_render_glyph(src, glyph, + bytes) : NativeCFFI.lime_font_render_glyph_with_flags(src, glyph, loadFlags, bytes); if (bytes != null && bytes.length > 0) { @@ -405,13 +404,14 @@ class Font return null; } + /** - * Renders a set of glyphs to images. - * - * @param glyphs The glyphs to render. - * @param fontSize The size to render the glyphs at. - * @return A `Map` containing glyphs mapped to their corresponding images. - */ + * Renders a set of glyphs to images. + * + * @param glyphs The glyphs to render. + * @param fontSize The size to render the glyphs at. + * @return A `Map` containing glyphs mapped to their corresponding images. + */ public function renderGlyphs(glyphs:Array, fontSize:Int):Map { #if (lime_cffi && !macro) @@ -760,8 +760,8 @@ class Font } /** -* Represents decomposed font data, containing kerning information, glyphs, and other properties. -*/ + * Represents decomposed font data, containing kerning information, glyphs, and other properties. + */ typedef NativeFontData = { var has_kerning:Bool; @@ -781,8 +781,8 @@ typedef NativeFontData = } /** -* Represents data for an individual glyph, including dimensions and control points. -*/ + * Represents data for an individual glyph, including dimensions and control points. + */ typedef NativeGlyphData = { var char_code:Int; @@ -795,8 +795,8 @@ typedef NativeGlyphData = } /** -* Represents kerning information between two glyphs. -*/ + * Represents kerning information between two glyphs. + */ typedef NativeKerningData = { var left_glyph:Int; diff --git a/src/lime/text/harfbuzz/HBBufferSerializeFormat.hx b/src/lime/text/harfbuzz/HBBufferSerializeFormat.hx index 92f60090e3..b932134305 100644 --- a/src/lime/text/harfbuzz/HBBufferSerializeFormat.hx +++ b/src/lime/text/harfbuzz/HBBufferSerializeFormat.hx @@ -12,6 +12,7 @@ package lime.text.harfbuzz; // // } } + // @:cffi private static function lime_hb_buffer_serialize_format_from_string (str:String, len:Int):Int; // @:cffi private static function lime_hb_buffer_serialize_format_to_string (format:Int):CFFIPointer; // @:cffi private static function lime_hb_buffer_serialize_list_formats ():CFFIPointer; diff --git a/src/lime/tools/AIRHelper.hx b/src/lime/tools/AIRHelper.hx index d3837bba5c..5495fc39cc 100644 --- a/src/lime/tools/AIRHelper.hx +++ b/src/lime/tools/AIRHelper.hx @@ -5,22 +5,20 @@ import sys.FileSystem; class AIRHelper { - public static function build(project:HXProject, workingDirectory:String, targetPlatform:Platform, targetPathWithoutExtension:String, applicationXML:String, - files:Array, fileDirectory:String = null):String + public static function build(project:HXProject, workingDirectory:String, targetPlatform:Platform, targetPathWithoutExtension:String, + applicationXML:String, files:Array, fileDirectory:String = null):String { var airTarget = "bundle"; - switch(targetPlatform) + switch (targetPlatform) { case WINDOWS: - if (project.targetFlags.exists("shared")) { airTarget = "air"; } case MAC: - if (project.targetFlags.exists("shared")) { airTarget = "air"; @@ -53,7 +51,8 @@ class AIRHelper exportMethod = m; } } - if (exportMethod == null && project.targetFlags.exists("final")) { + if (exportMethod == null && project.targetFlags.exists("final")) + { exportMethod = "appstore"; } @@ -122,14 +121,12 @@ class AIRHelper switch (targetPlatform) { case WINDOWS: - if (airTarget == "air") { extension = ".air"; } case MAC: - if (airTarget == "bundle") { extension = ".app"; @@ -140,7 +137,6 @@ class AIRHelper } case ANDROID: - if (StringTools.startsWith(airTarget, "aab")) { extension = ".aab"; @@ -155,7 +151,6 @@ class AIRHelper } case IOS: - extension = ".ipa"; default: diff --git a/src/lime/tools/ApplicationData.hx b/src/lime/tools/ApplicationData.hx index 301917209d..a81d4688c2 100644 --- a/src/lime/tools/ApplicationData.hx +++ b/src/lime/tools/ApplicationData.hx @@ -12,13 +12,14 @@ abstract ApplicationData({ }) from Dynamic { @:noCompletion - public static var expectedFields:ApplicationData = { - file: "", - init: "", - main: "", - path: "", - preloader: "", - swfVersion: 0.0, - url: "" - }; + public static var expectedFields:ApplicationData = + { + file: "", + init: "", + main: "", + path: "", + preloader: "", + swfVersion: 0.0, + url: "" + }; } diff --git a/src/lime/tools/AssetHelper.hx b/src/lime/tools/AssetHelper.hx index f0ab371c82..ed4bb6bdbb 100644 --- a/src/lime/tools/AssetHelper.hx +++ b/src/lime/tools/AssetHelper.hx @@ -25,13 +25,65 @@ class AssetHelper { knownExtensions = [ - "jpg" => IMAGE, "jpeg" => IMAGE, "png" => IMAGE, "gif" => IMAGE, "webp" => IMAGE, "bmp" => IMAGE, "tiff" => IMAGE, "jfif" => IMAGE, "otf" => FONT, - "ttf" => FONT, "wav" => SOUND, "wave" => SOUND, "flac" => SOUND, "mid" => SOUND, "midi" => SOUND, "ogg" => SOUND, "spx" => SOUND, "au" => SOUND, - "aiff" => SOUND, "oga" => SOUND, "mp3" => MUSIC, "mp2" => MUSIC, "exe" => BINARY, "bin" => BINARY, "so" => BINARY, "pch" => BINARY, - "dll" => BINARY, "zip" => BINARY, "tar" => BINARY, "gz" => BINARY, "fla" => BINARY, "swf" => BINARY, "atf" => BINARY, "psd" => BINARY, - "awd" => BINARY, "txt" => TEXT, "text" => TEXT, "xml" => TEXT, "java" => TEXT, "hx" => TEXT, "cpp" => TEXT, "c" => TEXT, "h" => TEXT, - "cs" => TEXT, "js" => TEXT, "mm" => TEXT, "hxml" => TEXT, "html" => TEXT, "json" => TEXT, "css" => TEXT, "gpe" => TEXT, "pbxproj" => TEXT, - "plist" => TEXT, "properties" => TEXT, "ini" => TEXT, "hxproj" => TEXT, "nmml" => TEXT, "lime" => TEXT, "svg" => TEXT, + "jpg" => IMAGE, + "jpeg" => IMAGE, + "png" => IMAGE, + "gif" => IMAGE, + "webp" => IMAGE, + "bmp" => IMAGE, + "tiff" => IMAGE, + "jfif" => IMAGE, + "otf" => FONT, + "ttf" => FONT, + "wav" => SOUND, + "wave" => SOUND, + "flac" => SOUND, + "mid" => SOUND, + "midi" => SOUND, + "ogg" => SOUND, + "spx" => SOUND, + "au" => SOUND, + "aiff" => SOUND, + "oga" => SOUND, + "mp3" => MUSIC, + "mp2" => MUSIC, + "exe" => BINARY, + "bin" => BINARY, + "so" => BINARY, + "pch" => BINARY, + "dll" => BINARY, + "zip" => BINARY, + "tar" => BINARY, + "gz" => BINARY, + "fla" => BINARY, + "swf" => BINARY, + "atf" => BINARY, + "psd" => BINARY, + "awd" => BINARY, + "txt" => TEXT, + "text" => TEXT, + "xml" => TEXT, + "java" => TEXT, + "hx" => TEXT, + "cpp" => TEXT, + "c" => TEXT, + "h" => TEXT, + "cs" => TEXT, + "js" => TEXT, + "mm" => TEXT, + "hxml" => TEXT, + "html" => TEXT, + "json" => TEXT, + "css" => TEXT, + "gpe" => TEXT, + "pbxproj" => TEXT, + "plist" => TEXT, + "properties" => TEXT, + "ini" => TEXT, + "hxproj" => TEXT, + "nmml" => TEXT, + "lime" => TEXT, + "svg" => TEXT, ]; } diff --git a/src/lime/tools/CPPHelper.hx b/src/lime/tools/CPPHelper.hx index e2877c9205..66d2dc71bc 100644 --- a/src/lime/tools/CPPHelper.hx +++ b/src/lime/tools/CPPHelper.hx @@ -208,7 +208,10 @@ class CPPHelper if (!FileSystem.exists(path)) { - Log.warn("Skipping rebuild. Path not found: " + path + "\nIf you are using a release from Haxelib, source code for native binaries may not be bundled. To rebuild, you may need to check out the full repository."); + Log.warn("Skipping rebuild. Path not found: " + + path + + + "\nIf you are using a release from Haxelib, source code for native binaries may not be bundled. To rebuild, you may need to check out the full repository."); return; } @@ -221,7 +224,10 @@ class CPPHelper if (!FileSystem.exists(Path.combine(path, buildFile))) { - Log.warn("Skipping rebuild. Path not found: " + path + "\nIf you are using a release from Haxelib, source code for native binaries may not be bundled. To rebuild, you may need to check out the full repository."); + Log.warn("Skipping rebuild. Path not found: " + + path + + + "\nIf you are using a release from Haxelib, source code for native binaries may not be bundled. To rebuild, you may need to check out the full repository."); return; } diff --git a/src/lime/tools/CSHelper.hx b/src/lime/tools/CSHelper.hx index 2aa3a391d1..e92149248c 100644 --- a/src/lime/tools/CSHelper.hx +++ b/src/lime/tools/CSHelper.hx @@ -11,8 +11,16 @@ using StringTools; class CSHelper { public static var ndllSourceFiles:Array = [ - "cs.ndll.NDLLFunction", "cs.ndll.CFFICSLoader", "cs.ndll.CSAbstract", "cs.ndll.CSHandleContainer", "cs.ndll.CSHandleScope", "cs.ndll.CSPersistent", - "cs.ndll.DelegateConverter", "cs.ndll.HandleUtils", "cs.ndll.NativeMethods", "cs.ndll.NDLLFunction", + "cs.ndll.NDLLFunction", + "cs.ndll.CFFICSLoader", + "cs.ndll.CSAbstract", + "cs.ndll.CSHandleContainer", + "cs.ndll.CSHandleScope", + "cs.ndll.CSPersistent", + "cs.ndll.DelegateConverter", + "cs.ndll.HandleUtils", + "cs.ndll.NativeMethods", + "cs.ndll.NDLLFunction", ]; private static function getAndroidABIName(arch:Architecture):String diff --git a/src/lime/tools/ConfigData.hx b/src/lime/tools/ConfigData.hx index 96b3928505..1ae3c54c2e 100644 --- a/src/lime/tools/ConfigData.hx +++ b/src/lime/tools/ConfigData.hx @@ -175,7 +175,7 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic return defaultValue; } - public function getKeyValueArray(id:String, defaultValues:Dynamic = null):Array<{ key:String, value:Dynamic }> + public function getKeyValueArray(id:String, defaultValues:Dynamic = null):Array<{key:String, value:Dynamic}> { var values = {}; if (defaultValues != null) @@ -192,10 +192,10 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic } } - var pairs:Array<{ key:String, value:Dynamic }> = []; + var pairs:Array<{key:String, value:Dynamic}> = []; for (key in Reflect.fields(values)) { - pairs.push({ key: key, value: Reflect.field(values, key) }); + pairs.push({key: key, value: Reflect.field(values, key)}); } return pairs; @@ -237,7 +237,10 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic continue; } - if (valueSource != valueDest && valueDest != null && typeSource != "TObject" && !#if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(valueSource, Array)) + if (valueSource != valueDest + && valueDest != null + && typeSource != "TObject" + && !#if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (valueSource, Array)) { if (!Reflect.hasField(destination, ARRAY + field)) { @@ -264,11 +267,13 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic { mergeValues(valueSource, valueDest); } - else if (typeDest == "TClass" && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (valueSource, Array) && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(valueDest, Array)) + else if (typeDest == "TClass" + && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (valueSource, Array) + && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (valueDest, Array)) { - for (item in (cast valueSource:Array)) + for (item in (cast valueSource : Array)) { - (cast valueDest:Array).push(item); + (cast valueDest : Array).push(item); } } else @@ -529,11 +534,13 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic // Getters & Setters - private inline function get_xmlChildren():Array { + private inline function get_xmlChildren():Array + { return Reflect.field(this, "config:xml_children"); } - private inline function set_xmlChildren(value:Array):Array { + private inline function set_xmlChildren(value:Array):Array + { Reflect.setField(this, "config:xml_children", value); return value; } diff --git a/src/lime/tools/FlashHelper.hx b/src/lime/tools/FlashHelper.hx index 07b68201f5..0b4f840432 100644 --- a/src/lime/tools/FlashHelper.hx +++ b/src/lime/tools/FlashHelper.hx @@ -623,7 +623,22 @@ class FlashHelper var label = (id > 0 ? Std.string(id + 1) : ""); var swfVersions = [ - 9, 10, /*10.1,*/ 10.2, 10.3, 11, 11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 11.7, 11.8, 12, 13, 14 + 9, + 10, /*10.1,*/ + 10.2, + 10.3, + 11, + 11.1, + 11.2, + 11.3, + 11.4, + 11.5, + 11.6, + 11.7, + 11.8, + 12, + 13, + 14 ]; var flashVersion = 9; diff --git a/src/lime/tools/HTML5Helper.hx b/src/lime/tools/HTML5Helper.hx index d7550381f1..f895a46295 100644 --- a/src/lime/tools/HTML5Helper.hx +++ b/src/lime/tools/HTML5Helper.hx @@ -107,11 +107,11 @@ class HTML5Helper { suffix += "32"; } - else if( System.hostArchitecture == ARMV7) + else if (System.hostArchitecture == ARMV7) { suffix += "Arm"; } - else if( System.hostArchitecture == ARM64) + else if (System.hostArchitecture == ARM64) { suffix += "Arm64"; } @@ -174,7 +174,8 @@ class HTML5Helper { var executable = "npx"; var terser = "terser"; - if (!project.targetFlags.exists("npx")) { + if (!project.targetFlags.exists("npx")) + { var suffix = switch (System.hostPlatform) { case WINDOWS: "-windows.exe"; @@ -207,14 +208,7 @@ class HTML5Helper } } - var args = [ - terser, - sourceFile, - "-c", - "-m", - "-o", - tempFile - ]; + var args = [terser, sourceFile, "-c", "-m", "-o", tempFile]; if (FileSystem.exists(sourceFile + ".map")) { @@ -245,9 +239,7 @@ class HTML5Helper if (project.targetFlags.exists("npx")) { executable = "npx"; - args = [ - "google-closure-compiler" - ]; + args = ["google-closure-compiler"]; } else { diff --git a/src/lime/tools/HXProject.hx b/src/lime/tools/HXProject.hx index 164a3e0fee..f114920708 100644 --- a/src/lime/tools/HXProject.hx +++ b/src/lime/tools/HXProject.hx @@ -50,6 +50,7 @@ class HXProject extends Script public var platformType:PlatformType; public var postBuildCallbacks:Array; public var preBuildCallbacks:Array; + @:noCompletion public var processedHaxelibIncludes:Array; public var samplePaths:Array; public var sources:Array; public var splashScreens:Array; @@ -107,7 +108,7 @@ class HXProject extends Script var classRef = Type.resolveClass(inputData.name); if (classRef == null) { - Log.error('Unable to find class ${ inputData.name } in ${ inputData.projectFile }'); + Log.error('Unable to find class ${inputData.name} in ${inputData.projectFile}'); return; } var instance = Type.createInstance(classRef, []); @@ -189,7 +190,20 @@ class HXProject extends Script else { environment = Sys.environment(); - for (conflict in ["air", "android", "cpp", "flash", "hl", "html5", "ios", "linux", "mac", "neko", "webassembly", "windows"]) + for (conflict in [ + "air", + "android", + "cpp", + "flash", + "hl", + "html5", + "ios", + "linux", + "mac", + "neko", + "webassembly", + "windows" + ]) { environment.remove(conflict); } @@ -207,12 +221,13 @@ class HXProject extends Script ndlls = new Array(); postBuildCallbacks = new Array(); preBuildCallbacks = new Array(); + processedHaxelibIncludes = new Array(); sources = new Array(); samplePaths = new Array(); splashScreens = new Array(); targetHandlers = new Map(); - config.set("android", { manifest:{}, application:{}, activity:{} }); + config.set("android", {manifest: {}, application: {}, activity: {}}); config.get("android.manifest").xmlChildren = []; config.get("android.application").xmlChildren = []; config.get("android.activity").xmlChildren = []; @@ -310,6 +325,7 @@ class HXProject extends Script project.platformType = platformType; project.postBuildCallbacks = postBuildCallbacks.copy(); project.preBuildCallbacks = preBuildCallbacks.copy(); + project.processedHaxelibIncludes = processedHaxelibIncludes.copy(); project.samplePaths = samplePaths.copy(); project.sources = sources.copy(); @@ -403,11 +419,12 @@ class HXProject extends Script var args = [ name, #if lime - "-lib", "lime", - "-lib", "hxp", + "-lib", "lime", "-lib", "hxp", #end - "-cp", tempDirectory, - "-cp", Path.combine(Haxelib.getPath(new Haxelib("hxp")), "src") + "-cp", + tempDirectory, + "-cp", + Path.combine(Haxelib.getPath(new Haxelib("hxp")), "src") ]; var input = File.read(classFile, false); var tag = "@:compiler("; @@ -682,6 +699,7 @@ class HXProject extends Script @:privateAccess projectXML.parseXML(new Access(Xml.parse(xml).firstElement()), ""); merge(projectXML); } + // #end private function initializeDefines():Void @@ -793,8 +811,7 @@ class HXProject extends Script defines.set("native", "1"); defines.set("cpp", "1"); } - else if (targetFlags.exists("cpp") - || ((platformType != PlatformType.WEB) && !targetFlags.exists("html5"))) + else if (targetFlags.exists("cpp") || ((platformType != PlatformType.WEB) && !targetFlags.exists("html5"))) { defines.set("targetType", "cpp"); defines.set("native", "1"); @@ -911,6 +928,15 @@ class HXProject extends Script excludeArchitectures = ArrayTools.concatUnique(excludeArchitectures, project.excludeArchitectures); haxeflags = ArrayTools.concatUnique(haxeflags, project.haxeflags); haxelibs = ArrayTools.concatUnique(haxelibs, project.haxelibs, true, "name"); + if (processedHaxelibIncludes == null) + { + processedHaxelibIncludes = new Array(); + } + + if (project.processedHaxelibIncludes != null) + { + processedHaxelibIncludes = ArrayTools.concatUnique(processedHaxelibIncludes, project.processedHaxelibIncludes); + } icons = ArrayTools.concatUnique(icons, project.icons); javaPaths = ArrayTools.concatUnique(javaPaths, project.javaPaths, true); @@ -977,6 +1003,11 @@ class HXProject extends Script // #if lime @:noCompletion private static function processHaxelibs(project:HXProject, userDefines:Map):Void { + if (project.processedHaxelibIncludes == null) + { + project.processedHaxelibIncludes = new Array(); + } + var haxelibs = project.haxelibs.copy(); project.haxelibs = []; @@ -985,6 +1016,11 @@ class HXProject extends Script var validatePath = Haxelib.getPath(haxelib, true); project.haxelibs.push(haxelib); + if (ArrayTools.containsValue(project.processedHaxelibIncludes, getHaxelibIncludeKey(haxelib))) + { + continue; + } + var includeProject = HXProject.fromHaxelib(haxelib, userDefines); if (includeProject != null) @@ -1002,6 +1038,16 @@ class HXProject extends Script } } + @:noCompletion public static function getHaxelibIncludeKey(haxelib:Haxelib):String + { + if (haxelib.version != null && haxelib.version != "") + { + return haxelib.name + ":" + haxelib.version; + } + + return haxelib.name; + } + @:noCompletion private static function resolveClass(name:String):Class { var type = Type.resolveClass(name); diff --git a/src/lime/tools/HashlinkHelper.hx b/src/lime/tools/HashlinkHelper.hx index 759f471493..879f180bcc 100644 --- a/src/lime/tools/HashlinkHelper.hx +++ b/src/lime/tools/HashlinkHelper.hx @@ -8,10 +8,49 @@ import lime.tools.HXProject; import lime.tools.Platform; import hxp.Path; import hxp.System; +import sys.io.File; class HashlinkHelper { public static inline var BUNDLED_HL_VER = "1.14.0"; + private static inline var IMAGE_SUBSYSTEM_WINDOWS_GUI = 2; + + private static function readUInt32LE(bytes:haxe.io.Bytes, offset:Int):Int + { + return bytes.get(offset) | (bytes.get(offset + 1) << 8) | (bytes.get(offset + 2) << 16) | (bytes.get(offset + 3) << 24); + } + + private static function setWindowsGUISubsystem(executablePath:String):Void + { + try + { + var bytes = File.getBytes(executablePath); + + if (bytes.length < 0x100 || bytes.get(0) != 0x4D || bytes.get(1) != 0x5A) + { + Log.warn('Could not hide HashLink console: "$executablePath" is not a valid Windows executable'); + return; + } + + var peOffset = readUInt32LE(bytes, 0x3C); + var subsystemOffset = peOffset + 24 + 68; + + if (peOffset < 0 || subsystemOffset + 1 >= bytes.length || bytes.get(peOffset) != 0x50 || bytes.get(peOffset + 1) != 0x45 + || bytes.get(peOffset + 2) != 0 || bytes.get(peOffset + 3) != 0) + { + Log.warn('Could not hide HashLink console: "$executablePath" has an unsupported PE header'); + return; + } + + bytes.set(subsystemOffset, IMAGE_SUBSYSTEM_WINDOWS_GUI); + bytes.set(subsystemOffset + 1, 0); + File.saveBytes(executablePath, bytes); + } + catch (e:Dynamic) + { + Log.warn('Could not hide HashLink console for "$executablePath": $e'); + } + } public static function copyHashlink(project:HXProject, targetDirectory:String, applicationDirectory:String, executablePath:String, ?is64 = true) { @@ -26,7 +65,8 @@ class HashlinkHelper Sys.exit(1); ""; }; - if(is64) { + if (is64) + { bindir += "64"; } @@ -39,9 +79,8 @@ class HashlinkHelper if (project.targetFlags.exists("hlc")) { var limeDirectory = Haxelib.getPath(new Haxelib("lime"), true); - var includeDirectory = sys.FileSystem.exists(Path.combine(limeDirectory, "project")) - ? Path.combine(limeDirectory, "project/lib/hashlink/src") - : Path.combine(limeDirectory, "templates/bin/hl/include"); + var includeDirectory = sys.FileSystem.exists(Path.combine(limeDirectory, + "project")) ? Path.combine(limeDirectory, "project/lib/hashlink/src") : Path.combine(limeDirectory, "templates/bin/hl/include"); System.copyFile(Path.combine(includeDirectory, "hlc.h"), Path.combine(targetDirectory, "obj/hlc.h"), null, false); System.copyFile(Path.combine(includeDirectory, "hl.h"), Path.combine(targetDirectory, "obj/hl.h"), null, false); @@ -94,6 +133,11 @@ class HashlinkHelper } } + if (platform == WINDOWS && !project.targetFlags.exists("hlc") && !project.environment.exists("SHOW_CONSOLE")) + { + setWindowsGUISubsystem(executablePath); + } + // make sure no hxcpp hash files or MSVC build artifacts remain for (file in System.readDirectory(applicationDirectory)) @@ -120,7 +164,8 @@ class HashlinkHelper var appMainCPath = Path.combine(targetDirectory, "obj/ApplicationMain.c"); var appMainCText = System.readText(appMainCPath); var index = appMainCText.indexOf("#ifndef HL_MAKE"); - appMainCText = appMainCText.substr(0, index) + " + appMainCText = appMainCText.substr(0, index) + + " // --------- START LIME HL/C INJECTED CODE --------- // // undefine things to avoid Haxe field name conflicts #undef BIG_ENDIAN @@ -150,7 +195,8 @@ class HashlinkHelper #undef __valid #undef WAIT_FAILED // ---------- END LIME HL/C INJECTED CODE ---------- // -" + appMainCText.substr(index); +" + + appMainCText.substr(index); System.writeText(appMainCText, appMainCPath); } else diff --git a/src/lime/tools/IOSHelper.hx b/src/lime/tools/IOSHelper.hx index c4202c2faf..431312f13a 100644 --- a/src/lime/tools/IOSHelper.hx +++ b/src/lime/tools/IOSHelper.hx @@ -364,7 +364,8 @@ class IOSHelper var requireIPhone = project.config.getString("ios.device", "universal") == "iphone"; var xcodeVersion = Std.parseFloat(getXcodeVersion()); - if (!Math.isNaN(xcodeVersion) && xcodeVersion >= 16) { + if (!Math.isNaN(xcodeVersion) && xcodeVersion >= 16) + { // ios-deploy doesn't work with newer iOS SDKs where it can't // find DeveloperDiskImage.dmg. however, Xcode 16 adds new // commands for installing and launching apps on connected @@ -389,10 +390,7 @@ class IOSHelper // 1. the platform must always be iOS (which includes iPadOS). // 2. the device must be in developer mode. // 3. if required by the project config, limit to iPhone or iPad only - var baseFilters = [ - filterPlatformIOS, - filterDeveloperModeEnabled, - ]; + var baseFilters = [filterPlatformIOS, filterDeveloperModeEnabled,]; if (requireIPad) { baseFilters.push(filterDeviceTypeIPad); @@ -411,10 +409,7 @@ class IOSHelper { for (transportTypeFilter in transportTypeFilters) { - deviceUUID = findDeviceUUIDWithFilters(baseFilters.concat([ - stateFilter, - transportTypeFilter - ])); + deviceUUID = findDeviceUUIDWithFilters(baseFilters.concat([stateFilter, transportTypeFilter])); if (deviceUUID != null && deviceUUID.length > 0) { break; @@ -426,7 +421,8 @@ class IOSHelper } } - if (deviceUUID == null || deviceUUID.length == 0) { + if (deviceUUID == null || deviceUUID.length == 0) + { // devices running iOS 16 and older don't support // xcrun devicectl, so if no device was found, try falling // back to ios-deploy @@ -440,9 +436,28 @@ class IOSHelper Log.info("Detected iOS device UUID: " + deviceUUID); } - System.runCommand("", "xcrun", ["devicectl", "device", "install", "app", "--device", deviceUUID, FileSystem.fullPath(applicationPath)]); - System.runCommand("", "xcrun", ["devicectl", "device", "process", "launch", "--console", "--device", deviceUUID, project.meta.packageName]); - } else { + System.runCommand("", "xcrun", [ + "devicectl", + "device", + "install", + "app", + "--device", + deviceUUID, + FileSystem.fullPath(applicationPath) + ]); + System.runCommand("", "xcrun", [ + "devicectl", + "device", + "process", + "launch", + "--console", + "--device", + deviceUUID, + project.meta.packageName + ]); + } + else + { // continue using ios-deploy if Xcode version is 15 or older fallbackLaunch(project, applicationPath); } @@ -451,12 +466,16 @@ class IOSHelper private static function findDeviceUUIDWithFilters(filters:Array):String { - var listDevicesOutput = System.runProcess("", "xcrun", - [ - "devicectl", "list", "devices", - "--hide-default-columns", "--columns", "Identifier", - "--filter", filters.join(" AND ") - ]); + var listDevicesOutput = System.runProcess("", "xcrun", [ + "devicectl", + "list", + "devices", + "--hide-default-columns", + "--columns", + "Identifier", + "--filter", + filters.join(" AND ") + ]); var ready = false; for (line in listDevicesOutput.split("\n")) { diff --git a/src/lime/tools/IconHelper.hx b/src/lime/tools/IconHelper.hx index 95b1a7d6c0..694c18af4f 100644 --- a/src/lime/tools/IconHelper.hx +++ b/src/lime/tools/IconHelper.hx @@ -311,7 +311,8 @@ class IconHelper } if (Math.abs(iconDifference) < Math.abs(matchDifference) - || iconDifference == matchDifference && icon.priority >= match.priority) + || iconDifference == matchDifference + && icon.priority >= match.priority) { match = icon; matchDifference = iconDifference; diff --git a/src/lime/tools/MetaData.hx b/src/lime/tools/MetaData.hx index f06a76b20d..8680a18dc8 100644 --- a/src/lime/tools/MetaData.hx +++ b/src/lime/tools/MetaData.hx @@ -14,15 +14,16 @@ abstract MetaData({ }) from Dynamic { @:noCompletion - public static var expectedFields:MetaData = { - buildNumber: "", - company: "", - companyId: "", - companyUrl: "", - description: "", - packageName: "", - title: "", - version: "", - copyrightYears: "" - }; + public static var expectedFields:MetaData = + { + buildNumber: "", + company: "", + companyId: "", + companyUrl: "", + description: "", + packageName: "", + title: "", + version: "", + copyrightYears: "" + }; } diff --git a/src/lime/tools/PlatformTarget.hx b/src/lime/tools/PlatformTarget.hx index d616a2e352..b752ac16f9 100644 --- a/src/lime/tools/PlatformTarget.hx +++ b/src/lime/tools/PlatformTarget.hx @@ -57,8 +57,7 @@ class PlatformTarget // known issue: this may not log in `-eval` mode on Linux inline function logCommand(command:String):Void { - if (!Reflect.hasField(metaFields, command) - || !Reflect.hasField(Reflect.field(metaFields, command), "ignore")) + if (!Reflect.hasField(metaFields, command) || !Reflect.hasField(Reflect.field(metaFields, command), "ignore")) { Log.info("", "\n" + Log.accentColor + "Running command: " + command.toUpperCase() + Log.resetColor); } @@ -137,8 +136,7 @@ class PlatformTarget run(); } - if ((command == "test" || command == "trace" || command == "run" || command == "rerun") - && (traceEnabled || command == "trace")) + if ((command == "test" || command == "trace" || command == "run" || command == "rerun") && (traceEnabled || command == "trace")) { logCommand("trace"); this.trace(); @@ -201,6 +199,33 @@ class PlatformTarget // Common functionality used by subclasses + /** + Copies all embedded assets into a temporary directory and sets their + `sourcePath`. This must happen before generating template contexts. + **/ + private function prepareEmbeddedAssets():Void + { + var embedDirectory = Path.combine(targetDirectory, "obj/tmp"); + + for (asset in project.assets) + { + if (asset.type != AssetType.TEMPLATE && asset.embed == true && asset.sourcePath == "") + { + var path = Path.combine(embedDirectory, asset.targetPath); + System.mkdir(Path.directory(path)); + AssetHelper.copyAsset(asset, path); + asset.sourcePath = path; + } + } + } + + /** + Copies all non-embedded assets into the given directories. + @param outputDirectory The root directory for template assets. + @param assetDirectory The root directory for non-template assets. If not + an absolute path, interpreted relative to `outputDirectory`. If null, + defaults to `outputDirectory`. + **/ private function copyProjectAssets(outputDirectory:String, assetDirectory:String = null) { if (assetDirectory == null) @@ -212,36 +237,35 @@ class PlatformTarget assetDirectory = Path.combine(outputDirectory, assetDirectory); } - var embedDirectory = Path.combine(targetDirectory, "obj/tmp"); - for (asset in project.assets) { + var path = Path.combine(assetDirectory, asset.targetPath); + if (asset.type == AssetType.TEMPLATE) { - var path = Path.combine(outputDirectory, asset.targetPath); + path = Path.combine(outputDirectory, asset.targetPath); System.mkdir(Path.directory(path)); AssetHelper.copyAsset(asset, path, project.templateContext); } else if (asset.embed == true) { - if (asset.sourcePath == "") + if (FileSystem.exists(path) && !FileSystem.isDirectory(path)) { - var path = Path.combine(embedDirectory, asset.targetPath); - System.mkdir(Path.directory(path)); - AssetHelper.copyAsset(asset, path); - asset.sourcePath = path; + System.deleteFile(path); } } else { - var path = Path.combine(assetDirectory, asset.targetPath); System.mkdir(Path.directory(path)); AssetHelper.copyAssetIfNewer(asset, path); } } } - private function getDisplayHXML():HXML { return null; } + private function getDisplayHXML():HXML + { + return null; + } // Functions to track and delete stale files diff --git a/src/lime/tools/ProjectXMLParser.hx b/src/lime/tools/ProjectXMLParser.hx index 876d59d1c3..3cf69bd9ef 100644 --- a/src/lime/tools/ProjectXMLParser.hx +++ b/src/lime/tools/ProjectXMLParser.hx @@ -1120,6 +1120,7 @@ class ProjectXMLParser extends HXProject } } + ArrayTools.addUnique(processedHaxelibIncludes, HXProject.getHaxelibIncludeKey(haxelib)); merge(includeProject); } @@ -1434,7 +1435,6 @@ class ProjectXMLParser extends HXProject sources.push(path); case "extension": - // deprecated case "haxedef": @@ -1536,7 +1536,6 @@ class ProjectXMLParser extends HXProject parseModuleElement(element, extensionPath); case "ssl": - // if (wantSslCertificate()) // parseSsl (element); @@ -1984,6 +1983,15 @@ class ProjectXMLParser extends HXProject case "parameters", "title": Reflect.setField(windows[id], name, Std.string(value)); + case "renderer": + var renderType = Std.string(value).toLowerCase(); + Reflect.setField(windows[id], "renderType", renderType); + if (renderType == "vulkan") + { + defines.set("lime-vulkan", ""); + haxedefs.set("lime-vulkan", ""); + } + case "allow-high-dpi": Reflect.setField(windows[id], "allowHighDPI", value == "true"); diff --git a/src/lime/tools/WindowData.hx b/src/lime/tools/WindowData.hx index df74318d29..712cb44b7e 100644 --- a/src/lime/tools/WindowData.hx +++ b/src/lime/tools/WindowData.hx @@ -19,12 +19,14 @@ abstract WindowData({ @:optional var allowHighDPI:Bool; @:optional var alwaysOnTop:Bool; @:optional var antialiasing:Int; + @:optional var renderType:String; @:optional var orientation:Orientation; @:optional var allowShaders:Bool; @:optional var requireShaders:Bool; @:optional var depthBuffer:Bool; @:optional var stencilBuffer:Bool; @:optional var title:String; + @:optional var transparent:Bool; #if (js && html5) @:optional var element:js.html.Element; #end @@ -35,36 +37,39 @@ abstract WindowData({ }) from Dynamic { @:noCompletion - public static var expectedFields:WindowData = { - width: 0, - height: 0, - x: 0.0, - y: 0.0, - background: 0, - parameters: "", - fps: 0, - hardware: false, - display: 0, - resizable: false, - borderless: false, - vsync: false, - vsyncMode: null, - fullscreen: false, - allowHighDPI: false, - alwaysOnTop: false, - antialiasing: 0, - orientation: Orientation.AUTO, - allowShaders: false, - requireShaders: false, - depthBuffer: false, - stencilBuffer: false, - title: "", - #if (js && html5) - element: null, - #end - colorDepth: 0, - minimized: false, - maximized: false, - hidden: false - }; + public static var expectedFields:WindowData = + { + width: 0, + height: 0, + x: 0.0, + y: 0.0, + background: 0, + parameters: "", + fps: 0, + hardware: false, + display: 0, + resizable: false, + borderless: false, + vsync: false, + vsyncMode: null, + fullscreen: false, + allowHighDPI: false, + alwaysOnTop: false, + antialiasing: 0, + renderType: null, + orientation: Orientation.AUTO, + allowShaders: false, + requireShaders: false, + depthBuffer: false, + stencilBuffer: false, + title: "", + transparent: false, + #if (js && html5) + element: null, + #end + colorDepth: 0, + minimized: false, + maximized: false, + hidden: false + }; } diff --git a/src/lime/tools/XCodeHelper.hx b/src/lime/tools/XCodeHelper.hx index 7abd0c08dd..1121a79090 100644 --- a/src/lime/tools/XCodeHelper.hx +++ b/src/lime/tools/XCodeHelper.hx @@ -7,10 +7,7 @@ class XCodeHelper { // different computers may have different sets of simulators installed // so there isn't necessarily a reasonable default for ipads - private static var DEFAULT_IPAD_SIMULATOR_NAMES = [ - "ipad", - "ipad-air" - ]; + private static var DEFAULT_IPAD_SIMULATOR_NAMES = ["ipad", "ipad-air"]; private static var DEFAULT_IPAD_AIR_SIMULATOR_FALLBACK_REGEX = ~/ipad-air-.+/g; private static var DEFAULT_IPAD_SIMULATOR_FALLBACK_REGEX = ~/ipad-.+/g; // this should be a standard iPhone of a particular generation diff --git a/src/lime/ui/FileDialog.hx b/src/lime/ui/FileDialog.hx index 014c11b8b5..709e9dc864 100644 --- a/src/lime/ui/FileDialog.hx +++ b/src/lime/ui/FileDialog.hx @@ -82,14 +82,43 @@ class FileDialog public function new() {} + private static function __extensionFromFilter(filter:String):String + { + for (entry in filter.split(",")) + { + if (entry.length == 0) continue; + + var extension = entry; + + if (StringTools.startsWith(extension, "*.")) + { + extension = extension.substr(2); + } + else if (StringTools.startsWith(extension, ".")) + { + extension = extension.substr(1); + } + + if (extension.length == 0 || extension.indexOf("*") != -1 || extension.indexOf("?") != -1 || extension.indexOf("/") != -1 + || extension.indexOf("\\") != -1) + { + continue; + } + + return extension; + } + + return null; + } + /** Opens a file selection dialog. If successful, either `onSelect` or `onSelectMultiple` will trigger with the result(s). This function only works on desktop targets, and will return `false` otherwise. @param type Type of the file dialog: `OPEN`, `SAVE`, `OPEN_DIRECTORY` or `OPEN_MULTIPLE`. - @param filter A filter to use when browsing. Asterisks are treated as wildcards. For example, - `"*.jpg"` will match any file ending in `.jpg`. + @param filter A filter to use when browsing. Use a bare extension such as `"jpg"` or + a wildcard pattern such as `"*.jpg"`. Multiple filters may be separated by commas. @param defaultPath The directory in which to start browsing and/or the default filename to suggest. Defaults to `Sys.getCwd()`, with no default filename. @param title The title to give the dialog window. @@ -100,9 +129,7 @@ class FileDialog if (type == null) type = FileDialogType.OPEN; #if sys - if (defaultPath != null && defaultPath.length > 0 - && FileSystem.exists(defaultPath) - && FileSystem.isDirectory(defaultPath)) + if (defaultPath != null && defaultPath.length > 0 && FileSystem.exists(defaultPath) && FileSystem.isDirectory(defaultPath)) { // if the default path is a directory, and the default path doesn't // end with a separator, tiny file dialogs may open its parent @@ -137,7 +164,8 @@ class FileDialog // Makes sure the filename ends with extension if (type == SAVE && filter != null && path.indexOf(".") == -1) { - path += "." + filter; + var extension = __extensionFromFilter(filter); + if (extension != null) path += "." + extension; } onSelect.dispatch(path); @@ -172,7 +200,7 @@ class FileDialog var path = null; #if (!macro && lime_cffi) - trace(defaultPath); + // trace(defaultPath); path = CFFI.stringValue(NativeCFFI.lime_file_dialog_open_file(title, filter, defaultPath)); #end @@ -239,8 +267,8 @@ class FileDialog Shows an open file dialog. If successful, `onOpen` will trigger with the file contents. This function only works on desktop targets, and will return `false` otherwise. - @param filter A filter to use when browsing. Asterisks are treated as wildcards. For example, - `"*.jpg"` will match any file ending in `.jpg`. + @param filter A filter to use when browsing. Use a bare extension such as `"jpg"` or + a wildcard pattern such as `"*.jpg"`. Multiple filters may be separated by commas. @param defaultPath The directory in which to start browsing and/or the default filename to suggest. Defaults to `Sys.getCwd()`, with no default filename. @param title The title to give the dialog window. @@ -293,8 +321,8 @@ class FileDialog This function only works on desktop and HMTL5 targets, and will return `false` otherwise. @param data The file contents, in `haxe.io.Bytes` format. (Implicit casting possible.) - @param filter A filter to use when browsing. Asterisks are treated as wildcards. For example, - `"*.jpg"` will match any file ending in `.jpg`. Used only if targeting deskop. + @param filter A filter to use when browsing. Use a bare extension such as `"jpg"` or + a wildcard pattern such as `"*.jpg"`. Multiple filters may be separated by commas. Used only if targeting deskop. @param defaultPath The directory in which to start browsing and/or the default filename to suggest. When targeting destkop, this defaults to `Sys.getCwd()` with no default filename. When targeting HTML5, this defaults to the browser's download directory, with a default filename based on the MIME type. diff --git a/src/lime/ui/Gamepad.hx b/src/lime/ui/Gamepad.hx index 19017ead14..3c7ab47f74 100644 --- a/src/lime/ui/Gamepad.hx +++ b/src/lime/ui/Gamepad.hx @@ -65,18 +65,17 @@ class Gamepad #if (lime_cffi && !macro) NativeCFFI.lime_gamepad_rumble(this.id, lowFrequencyRumble, highFrequencyRumble, duration); #elseif (js && html5) - var actuator:Dynamic = (untyped __jsGamepad.vibrationActuator) ? untyped __jsGamepad.vibrationActuator - : (untyped __jsGamepad.hapticActuators) ? untyped __jsGamepad.hapticActuators[0] - : null; + var actuator:Dynamic = (untyped __jsGamepad.vibrationActuator) ? untyped __jsGamepad.vibrationActuator : (untyped __jsGamepad.hapticActuators) ? untyped __jsGamepad.hapticActuators[0] : null; if (actuator == null) return; if (untyped actuator.playEffect) { - untyped actuator.playEffect("dual-rumble", { - duration: duration, - strongMagnitude: lowFrequencyRumble, - weakMagnitude: highFrequencyRumble - }); + untyped actuator.playEffect("dual-rumble", + { + duration: duration, + strongMagnitude: lowFrequencyRumble, + weakMagnitude: highFrequencyRumble + }); } else if (untyped actuator.pulse) { diff --git a/src/lime/ui/KeyCode.hx b/src/lime/ui/KeyCode.hx index 36bdedf7de..7772aaa710 100644 --- a/src/lime/ui/KeyCode.hx +++ b/src/lime/ui/KeyCode.hx @@ -10,8 +10,7 @@ import lime._internal.backend.native.NativeCFFI; @see `lime.ui.Window.onKeyUp` @see `lime.ui.ScanCode` **/ -@:access(lime._internal.backend.native.NativeCFFI) -#if (haxe_ver >= 4.0) enum #else @:enum #end abstract KeyCode(Int) from Int to Int from UInt to UInt +@:access(lime._internal.backend.native.NativeCFFI) #if (haxe_ver >= 4.0) enum #else @:enum #end abstract KeyCode(Int) from Int to Int from UInt to UInt { var UNKNOWN = 0x00; var BACKSPACE = 0x08; diff --git a/src/lime/ui/ScanCode.hx b/src/lime/ui/ScanCode.hx index 1d115499ed..c6a9eab247 100644 --- a/src/lime/ui/ScanCode.hx +++ b/src/lime/ui/ScanCode.hx @@ -11,8 +11,7 @@ import lime._internal.backend.native.NativeCFFI; @see `lime.ui.KeyCode` **/ @:access(lime._internal.backend.native.NativeCFFI) -@:access(lime.ui.KeyCode) -#if (haxe_ver >= 4.0) enum #else @:enum #end abstract ScanCode(Int) from Int to Int from UInt to UInt +@:access(lime.ui.KeyCode) #if (haxe_ver >= 4.0) enum #else @:enum #end abstract ScanCode(Int) from Int to Int from UInt to UInt { var UNKNOWN = 0; var BACKSPACE = 42; diff --git a/src/lime/ui/Window.hx b/src/lime/ui/Window.hx index 4a25da753c..eb364c4bcd 100644 --- a/src/lime/ui/Window.hx +++ b/src/lime/ui/Window.hx @@ -56,6 +56,7 @@ class Window * vertical-sync setting. **/ public var vsyncMode(get, set):VSyncMode; + public var fullscreen(get, set):Bool; public var height(get, set):Int; public var hidden(get, null):Bool; @@ -149,6 +150,7 @@ class Window #end public var textInputEnabled(get, set):Bool; public var title(get, set):String; + public var transparent(default, null):Bool; public var alwaysOnTop(get, set):Bool; public var visible(get, set):Bool; public var width(get, set):Int; @@ -236,207 +238,2257 @@ class Window __resizable = Reflect.hasField(__attributes, "resizable") ? __attributes.resizable : false; __maximized = Reflect.hasField(__attributes, "maximized") ? __attributes.maximized : false; __minimized = Reflect.hasField(__attributes, "minimized") ? __attributes.minimized : false; + transparent = Reflect.hasField(__attributes, "transparent") ? __attributes.transparent : false; id = -1; __backend = new WindowBackend(this); + if (id != -1 && application != null) application.__seedFrameConfiguration(__attributes); #if windows var mappings = [ - "8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2", - "341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", - "ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", - "6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", - "0d0f6e00000000000000504944564944,HORIPAD 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows", - "6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", - "88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows", - "4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows", - "25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows", - "4c05c405000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows", - "4c05cc09000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows", - "4c05a00b000000000000504944564944,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows", - "6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "36280100000000000000504944564944,OUYA Controller,platform:Windows,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13", - "4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Windows", - "00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows", - "00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows", - "28040140000000000000504944564944,GamePad Pro USB,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7", - "ff113133000000000000504944564944,SVEN X-PAD,platform:Windows,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9", - "8f0e0300000000000000504944564944,Piranha xtreme,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2", - "8f0e0d31000000000000504944564944,Multilaser JS071 USB,platform:Windows,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7", - "10080300000000000000504944564944,PS2 USB,platform:Windows,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5", - "79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows", - "4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,platform:Windows", - "d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows", - "a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows", - "4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,platform:Windows,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2", - "83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Windows", - - "10080100000000000000504944564944,PS1 USB,platform:Windows,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2", - "49190204000000000000504944564944,Ipega PG-9023,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,platform:Windows", - - "4f0423b3000000000000504944564944,Dual Trigger 3-in-1,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Windows", - "0d0f4900000000000000504944564944,Hatsune Miku Sho Controller,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows", - "79004318000000000000504944564944,Mayflash GameCube Controller Adapter,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b0,start:b9,guide:b0,leftshoulder:b4,rightshoulder:b7,leftstick:b0,rightstick:b0,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2", - "79000018000000000000504944564944,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows", - - "2509e803000000000000504944564944,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows", - "300f1001000000000000504944564944,Saitek P480 Rumble Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,platform:Windows", - "10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,y:b3,x:b4,start:b11,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,platform:Windows", - "63252305000000000000504944564944,USB Vibration Joystick (BM),platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "20380900000000000000504944564944,8Bitdo NES30 PRO Wireless,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8", - "02200090000000000000504944564944,8Bitdo NES30 PRO USB,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8", - "ff113133000000000000504944564944,Gembird JPD-DualForce,platform:Windows,a:b2,b:b3,x:b0,y:b1,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,leftstick:b10,rightstick:b11", - "341a0108000000000000504944564944,EXEQ RF USB Gamepad 8206,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,leftstick:b8,rightstick:b7,back:b8,start:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows", - "c0111352000000000000504944564944,Battalife Joystick,platform:Windows,x:b4,a:b6,b:b7,y:b5,back:b2,start:b3,leftshoulder:b0,rightshoulder:b1,leftx:a0,lefty:a1", - "100801e5000000000000504944564944,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Windows", - "79000600000000000000504944564944,NGS Phantom,a:b2,b:b3,y:b1,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows" + "03000000300f00000a01000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows", + "03000000fa190000918d000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows", + "03000000fa2d00000100000000000000,3dRudder Foot Motion Controller,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows", + "03000000d0160000040d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows", + "03000000d0160000050d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows", + "03000000d0160000060d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows", + "03000000d0160000070d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows", + "03000000d0160000600a000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows", + "03000000c82d00001930000000000000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b11,platform:Windows", + "03000000c82d00000031000000000000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000531000000000000,8BitDo Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000951000000000000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightx:a3,righty:a5,start:b11,platform:Windows", + "03000000008000000210000000000000,8BitDo F30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "030000003512000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000c82d00001028000000000000,8BitDo F30 Arcade Joystick,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00006a28000000000000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Windows", + "03000000c82d00001251000000000000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00001151000000000000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000150000000000000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000151000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00005106000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,guide:b2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00002090000000000000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000310000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000451000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightx:a3,righty:a5,start:b11,platform:Windows", + "03000000c82d00002028000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00008010000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d0000e002000000000000,8BitDo N30,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b6,platform:Windows", + "03000000c82d00000190000000000000,8BitDo N30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000290000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows", + "03000000c82d00003038000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows", + "03000000c82d00006928000000000000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b11,platform:Windows", + "03000000c82d00002590000000000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "030000003512000012ab000000000000,8BitDo NES30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Windows", + "03000000c82d000012ab000000000000,8BitDo NES30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000022000000090000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000203800000900000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00002038000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000751000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000851000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000360000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000361000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000660000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000960000000000000,8BitDo Pro 3,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000131000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000231000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000331000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000431000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00002867000000000000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b10,x:b3,y:b4,platform:Windows", + "03000000c82d00000130000000000000,8BitDo SF30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000060000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000061000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows", + "03000000102800000900000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d000021ab000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00003028000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "030000003512000020ab000000000000,8BitDo SN30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000351000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a2,rightshoulder:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00001290000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d000020ab000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00004028000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00006228000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000021000000000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00001130000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001230000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001330000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001260000000000000,8BitDo Ultimate 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001b30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001c30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001d30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001530000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001630000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001730000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00000121000000000000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000a00500003232000000000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows", + "03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows", + "03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows", + "030000008f0e00001200000000000000,Acme GA02,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "03000000c01100000355000000000000,Acrux,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000fa190000f0ff000000000000,Acteck AGJ 3200,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000d1180000402c000000000000,ADT1,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a3,rightx:a2,righty:a5,x:b3,y:b4,platform:Windows", + "030000006f0e00008801000000000000,Afterglow Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00000263000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001101000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001401000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001402000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001901000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001a01000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001301000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e00001302000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e00001304000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e00001413000000000000,Afterglow Xbox Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00003901000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ab1200000103000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b000000f9000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000100000008200000000000000,Akishop Customs PS360,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000007c1800000006000000000000,Alienware Dual Compatible PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows", + "03000000491900001904000000000000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows", + "03000000710100001904000000000000,Amazon Luna Controller,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b8,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b4,rightstick:b7,rightx:a3,righty:a4,start:b6,x:b3,y:b2,platform:Windows", + "0300000008100000e501000000000000,Anbernic Game Pad,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000020500000913000000000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000373500000710000000000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000373500004610000000000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000190e00000110000000000000,Aquaplus Piece,a:b1,b:b0,back:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b2,platform:Windows", + "03000000830500000160000000000000,Arcade,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b4,platform:Windows", + "03000000120c0000100e000000000000,Armor 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000490b00004406000000000000,ASCII Seamic Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "03000000869800002500000000000000,Astro C40 TR PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows", + "03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows", + "03000000050b00000579000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000050b00000679000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "030000006a0e00001140000000000000,Atari CX Controller,a:b0,leftx:a0,lefty:a1,platform:Windows", + "03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,start:b3,platform:Windows", + "03000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows", + "03000000380800001889000000000000,AtGames Legends Gamer Pro,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b14,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000008a3500000102000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows", + "030000008a3500000201000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows", + "030000008a3500000302000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows", + "030000008a3500000402000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows", + "03000000e4150000103f000000000000,Batarang,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000d6200000e557000000000000,Batarang PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows", + "030000006f0e00003201000000000000,Battlefield 4 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000ad1b000001f9000000000000,BB 070,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000d62000002a79000000000000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000bc2000005250000000000000,Beitong G3,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a3,righty:a4,start:b15,x:b3,y:b4,platform:Windows", + "030000000d0500000208000000000000,Belkin Nostromo N40,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "030000000d0500000308000000000000,Belkin Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows", + "03000000bc2000006012000000000000,Betop 2126F,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000bc2000000055000000000000,Betop BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000790000000700000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows", + "03000000808300000300000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows", + "03000000bc2000006312000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000bc2000006321000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000bc2000006412000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000c01100000555000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000c01100000655000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000006f0e00006401000000000000,BF One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows", + "03000000300f00000202000000000000,Bigben,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a5,righty:a2,start:b7,x:b2,y:b3,platform:Windows", + "030000006b1400000209000000000000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006b1400000055000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000006b1400000103000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows", + "03000000120c0000200e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000210e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000f10e000000000000,Brook PS2 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000120c0000310c000000000000,Brook Super Converter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows", + "03000000d81d00000b00000000000000,Buffalo BSGP1601 Series,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows", + "030000005a1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows", + "030000005b1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows", + "030000005b1c00002500000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows", + "030000006d04000042c2000000000000,ChillStream,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000457500000401000000000000,Cobra,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000b0400003365000000000000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows", + "030000004c050000c505000000000000,CronusMax Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000d814000007cd000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000d8140000cefa000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows", + "030000003807000002cb000000000000,Cyborg,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000a306000022f6000000000000,Cyborg V.3 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000f806000000a3000000000000,DA Leader,a:b7,b:b6,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b8,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:b3,rightx:a2,righty:a3,start:b12,x:b4,y:b5,platform:Windows", + "030000001a1c00000001000000000000,Datel Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000791d00000103000000000000,Dual Box Wii,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000151a00006222000000000000,Dual Plus PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "030000004f040000070f000000000000,Dual Power,a:b8,b:b9,back:b4,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,leftshoulder:b13,leftstick:b6,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b12,rightstick:b7,righttrigger:b15,start:b5,x:b10,y:b11,platform:Windows", + "030000004f04000012b3000000000000,Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows", + "030000004f04000020b3000000000000,Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows", + "03000000bd12000002e0000000000000,Dual Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows", + "03000000ff1100003133000000000000,DualForce,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b1,platform:Windows", + "030000006f0e00003001000000000000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000fc0400000250000000000000,Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "03000000bc2000000091000000000000,EasySMX Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000006e0500000a20000000000000,Elecom DUX60 MMO,a:b2,b:b3,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b14,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b15,righttrigger:b13,rightx:a3,righty:a4,start:b20,x:b0,y:b1,platform:Windows", + "03000000b80500000410000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows", + "03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows", + "03000095090000010000000000000000,Elecom JC-U609,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows", + "0300004112000000e500000000000000,Elecom JC-U909Z,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows", + "03000041120000001050000000000000,Elecom JC-U911,a:b1,b:b2,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b0,x:b4,y:b5,platform:Windows", + "030000006e0500000520000000000000,Elecom P301U PlayStation Adapter,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows", + "03000000250900000218000000000000,Elecom PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000411200004450000000000000,Elecom U1012,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows", + "030000006e0500000320000000000000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows", + "030000006e0500000e20000000000000,Elecom U3912T,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows", + "030000006e0500000f20000000000000,Elecom U4013S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows", + "030000006e0500001320000000000000,Elecom U4113,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006e0500001020000000000000,Elecom U4113S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows", + "030000006e0500000720000000000000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows", + "030000007d0400000640000000000000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Windows", + "03000000120c0000f61c000000000000,Elite,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000430b00000300000000000000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000062000001801000000000000,EMS TrioLinker Plus II,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Windows", + "03000000242f000000b7000000000000,ESM 9110,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows", + "03000000101c0000181c000000000000,Essential,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b4,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "030000008f0e00000f31000000000000,EXEQ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows", + "03000000341a00000108000000000000,EXEQ RF Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000006f0e00008401000000000000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00008101000000000000,Faceoff Deluxe Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00008001000000000000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000021000000090000000000000,FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows", + "0300000011040000c600000000000000,FC801,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows", + "03000000852100000201000000000000,FF GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000ad1b000028f0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b00002ef0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b000038f0000000000000,Fightpad TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows", + "03005036852100000000000000000000,Final Fantasy XIV Online Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000f806000001a3000000000000,Firestorm,a:b9,b:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b10,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b12,x:b8,y:b4,platform:Windows", + "03000000b50700000399000000000000,Firestorm 2,a:b2,b:b4,back:b10,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b9,start:b11,x:b3,y:b5,platform:Windows", + "03000000b50700001302000000000000,Firestorm D3,a:b0,b:b2,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,x:b1,y:b3,platform:Windows", + "03000000b40400001024000000000000,Flydigi Apex,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000151900004000000000000000,Flydigi Vader 2,a:b27,b:b26,back:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b23,leftstick:b17,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b22,rightstick:b16,righttrigger:b20,rightx:a3,righty:a4,start:b18,x:b25,y:b24,platform:Windows", + "03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b14,paddle1:b4,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows", + "03000000b40400001224000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows", + "0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows", + "03000000790000004618000000000000,GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "03000000260900002625000000000000,GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows", + "03000000341a000005f7000000000000,GameCube Controller,a:b2,b:b3,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b1,y:b0,platform:Windows", + "03000000430b00000500000000000000,GameCube Controller,a:b0,b:b2,dpdown:b10,dpleft:b8,dpright:b9,dpup:b11,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a3,rightx:a5,righty:a2,start:b7,x:b1,y:b3,platform:Windows", + "03000000790000004718000000000000,GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "030000008f0e00000d31000000000000,Gamepad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000ac0500003d03000000000000,GameSir G3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000ac0500005b05000000000000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000ac0500002d02000000000000,GameSir G4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000ac0500004d04000000000000,GameSir G4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000373500002210000000000000,GameSir G7 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000ac0500001a06000000000000,GameSir T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000373500000410000000000000,GameSir T4 Kaleid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000373500009410000000000000,GameSir Tegenaria Lite,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "030000004c0e00001035000000000000,Gamester,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "030000000d0f00001110000000000000,GameStick Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "0300000047530000616d000000000000,GameStop,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000c01100000140000000000000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000b62500000100000000000000,Gametel GT004 01,a:b3,b:b0,dpdown:b10,dpleft:b9,dpright:b8,dpup:b11,leftshoulder:b4,rightshoulder:b5,start:b7,x:b1,y:b2,platform:Windows", + "030000008f0e00001411000000000000,Gamo2 Divaller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000120c0000a857000000000000,Gator Claw,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000008305000009a0000000000000,Genius,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000008305000031b0000000000000,Genius Maxfire Blaze 3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000451300000010000000000000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000005c1a00003330000000000000,Genius MaxFire Grandias 12V,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "03000000300f00000b01000000000000,GGE909 Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000f0250000c283000000000000,Gioteck PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000f025000021c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000f025000031c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000f0250000c383000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000f0250000c483000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000d11800000094000000000000,Google Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows", + "030000004f04000026b3000000000000,GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "0300000079000000d418000000000000,GPD Win,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000c6240000025b000000000000,GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000007d0400000840000000000000,Gravis Destroyer Tilt,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows", + "030000007d0400000540000000000000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "03000000280400000140000000000000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a3,dpup:-a4,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000008f0e00000610000000000000,GreenAsia,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a5,righty:a2,start:b11,x:b3,y:b0,platform:Windows", + "03000000ac0500006b05000000000000,GT2a,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000008a2e0000dd10000000000000,Hand Held Legend GC Ultimate,a:b0,b:b2,back:b17,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b18,leftshoulder:b10,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b19,misc2:b24,paddle1:b13,paddle2:b12,rightshoulder:b11,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b1,y:b3,platform:Windows", + "030000008a2e0000df10000000000000,Hand Held Legend ProGCC,a:b1,b:b0,back:b17,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b18,leftshoulder:b10,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b19,paddle1:b13,paddle2:b12,rightshoulder:b11,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b3,y:b2,platform:Windows", + "030000000d0f00004900000000000000,Hatsune Miku Sho PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000001008000001e1000000000000,Havit HV G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows", + "030000000d0f00000c00000000000000,HEXT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000d81400000862000000000000,HitBox Edition Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows", + "03000000632500002605000000000000,HJD X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "030000000d0f00000a00000000000000,Hori DOA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f00008500000000000000,Hori Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00002500000000000000,Hori Fighting Commander 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000000d0f00008400000000000000,Hori Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006201000000000000,Hori Fighting Commander Octa,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006401000000000000,Hori Fighting Commander Octa,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f00005100000000000000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00008600000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f0000ba00000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f00008800000000000000,Hori Fighting Stick mini 4 PS3,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows", + "030000000d0f00008700000000000000,Hori Fighting Stick mini 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000000d0f00001000000000000000,Hori Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00003200000000000000,Hori Fightstick 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000c000000000000000,Hori Fightstick 4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f00000d00000000000000,Hori Fightstick EX2,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "030000000d0f00003701000000000000,Hori Fightstick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Windows", + "030000000d0f00004000000000000000,Hori Fightstick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00002100000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00002700000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000a000000000000000,Hori Grip TAC4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b13,x:b0,y:b3,platform:Windows", + "030000000d0f0000a500000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000000d0f0000a600000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000000d0f00000101000000000000,Hori Mini Hatsune Miku FT,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00005400000000000000,Hori Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00000900000000000000,Hori Pad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00004d00000000000000,Hori Pad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00003801000000000000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Windows", + "030000000d0f00009200000000000000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00002301000000000000,Hori PS4 Controller Light,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "030000000d0f00001100000000000000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00002600000000000000,Hori Real Arcade Pro 3P,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00004b00000000000000,Hori Real Arcade Pro 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006a00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006b00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00008a00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00008b00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006f00000000000000,Hori Real Arcade Pro 4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00007000000000000000,Hori Real Arcade Pro 4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00003d00000000000000,Hori Real Arcade Pro N3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b4,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b6,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000ae00000000000000,Hori Real Arcade Pro N4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f00008c00000000000000,Hori Real Arcade Pro P4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f0000aa00000000000000,Hori Real Arcade Pro S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000d800000000000000,Hori Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows", + "030000000d0f00002200000000000000,Hori Real Arcade Pro V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00005b00000000000000,Hori Real Arcade Pro V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00005c00000000000000,Hori Real Arcade Pro V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000af00000000000000,Hori Real Arcade Pro VHS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00001b00000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b000002f5000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Windows", + "030000000d0f00009c00000000000000,Hori TAC Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000c900000000000000,Hori Taiko Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006400000000000000,Horipad 3TP,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00001300000000000000,Horipad 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00005500000000000000,Horipad 4 FPS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006e00000000000000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f00006600000000000000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000000d0f00004200000000000000,Horipad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000ad1b000001f5000000000000,Horipad EXT2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f0000ee00000000000000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000c100000000000000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000000d0f0000f600000000000000,Horipad Nintendo Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000000d0f00000202000000000000,Horipad O Nintendo Switch 2 Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,misc2:b14,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows", + "030000000d0f00006700000000000000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000000d0f00009601000000000000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc2:b2,paddle1:b5,paddle2:b15,paddle3:b18,paddle4:b19,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "030000000d0f0000dc00000000000000,Horipad Switch,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000242e00000b20000000000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Windows", + "03000000242e0000ff0b000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Windows", + "03000000790000004e95000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows", + "03000000242e00006a48000000000000,Hyperkin RetroN Sq,a:b3,b:b7,back:b5,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b0,rightshoulder:b1,start:b4,x:b2,y:b6,platform:Windows", + "03000000242f00000a20000000000000,Hyperkin Scout,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows", + "03000000242e00000a20000000000000,Hyperkin Scout Premium SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows", + "03000000242e00006a38000000000000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Windows", + "03000000f00300008d04000000000000,HyperX Clutch,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:-a2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:+a5,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows", + "03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000d81d00001000000000000000,iBuffalo BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000005c0a00000285000000000000,iDroidCon,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b6,platform:Windows", + "03000000696400006964000000000000,iDroidCon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000511d00000230000000000000,iGUGU Gamecore,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b1,leftstick:b4,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b2,platform:Windows", + "03000000b50700001403000000000000,Impact Black,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows", + "030000006f0e00002401000000000000,Injustice Fightstick PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "03000000830500005130000000000000,InterAct ActionPad,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "03000000ef0500000300000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows", + "03000000fd0500000230000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows", + "03000000fd0500000030000000000000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows", + "03000000fd0500003902000000000000,InterAct Hammerhead,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,rightshoulder:b7,rightstick:b5,righttrigger:b9,start:b10,x:b0,y:b1,platform:Windows", + "03000000fd0500002a26000000000000,InterAct Hammerhead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows", + "03000000fd0500002f26000000000000,InterAct Hammerhead FX,a:b4,b:b5,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b1,y:b2,platform:Windows", + "03000000fd0500005302000000000000,InterAct ProPad,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows", + "03000000ac0500002c02000000000000,Ipega Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000491900000204000000000000,Ipega PG9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000491900000304000000000000,Ipega PG9087,+righty:+a5,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows", + "030000007e0500000620000000000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows", + "030000007e0500000720000000000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows", + "03000000250900000017000000000000,Joypad Adapter,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows", + "03000000bd12000003c0000000000000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000008b0100002301000000000000,Joytech JS-112,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a2,lefty:a3,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a0,righty:a1,start:b9,x:b0,y:b1,platform:Windows", + "03000000ff1100004033000000000000,JPD FFB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a2,start:b15,x:b3,y:b0,platform:Windows", + "03000000242f00002d00000000000000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000242f00008a00000000000000,JYS Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows", + "03000000c4100000c082000000000000,KADE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000828200000180000000000000,Keio,a:b4,b:b5,back:b8,leftshoulder:b2,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b1,platform:Windows", + "03000000c4ac00001c80000000000000,KidzPlay Adventure PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000790000000200000000000000,King PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows", + "03000000bd12000001e0000000000000,Leadership,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "030000006f0e00000103000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e00000104000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000008f0e00001300000000000000,Logic3,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000006d040000d1ca000000000000,Logitech ChillStream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006d040000d2ca000000000000,Logitech Cordless Precision,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006d0400001dc2000000000000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006d04000018c2000000000000,Logitech F510,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006d0400001ec2000000000000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006d04000019c2000000000000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006d0400001ac2000000000000,Logitech Precision,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000006d04000009c2000000000000,Logitech WingMan,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows", + "030000006d0400000bc2000000000000,Logitech WingMan Action Pad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:a5~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:a2~,start:b8,x:b3,y:b4,platform:Windows", + "030000006d04000011c2000000000000,Logitech WingMan Cordless,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows", + "030000006d0400000ac2000000000000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows", + "03000000380700005645000000000000,Lynx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000222200006000000000000000,Macally,a:b1,b:b2,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700003888000000000000,Mad Catz Arcade Fightstick TE S Plus PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700008532000000000000,Mad Catz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700006352000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700006652000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700005032000000000000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700005082000000000000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000380700008031000000000000,Mad Catz FightStick Alpha PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000003807000038b7000000000000,Mad Catz Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700008433000000000000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700008483000000000000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000380700008134000000000000,Mad Catz Fightstick TE2 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700008184000000000000,Mad Catz Fightstick TE2 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000380700006252000000000000,Mad Catz Micro CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700008232000000000000,Mad Catz PlayStation Brawlpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700008731000000000000,Mad Catz PlayStation Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000003807000056a8000000000000,Mad Catz PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700001888000000000000,Mad Catz SFIV Fightstick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000380700008081000000000000,Mad Catz SFV Arcade Fightstick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000380700001847000000000000,Mad Catz Street Fighter 4 Xbox 360 FightStick,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000002a0600001024000000000000,Matricom,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows", + "030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "030000008f0e00001330000000000000,Mayflash Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Windows", + "03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows", + "03000000242f00003700000000000000,Mayflash F101,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "03000000790000003018000000000000,Mayflash F300 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "03000000242f00003900000000000000,Mayflash F300 Elite Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000790000004318000000000000,Mayflash GameCube Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows", + "03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows", + "03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows", + "0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000242f0000f400000000000000,Mayflash N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows", + "03000000242f0000f500000000000000,Mayflash N64 Adapter,a:b2,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows", + "03000000790000007918000000000000,Mayflash N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,righttrigger:b7,rightx:a3,righty:a2,start:b8,platform:Windows", + "030000008f0e00001030000000000000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows", + "03000000790000000318000000000000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows", + "03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000790000002418000000000000,Mega Drive Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b2,start:b9,x:b3,y:b4,platform:Windows", + "0300000079000000ae18000000000000,Mega Drive Controller,a:b0,b:b1,back:b7,dpdown:b14,dpleft:b15,dpright:b13,dpup:b2,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "03000000c0160000990a000000000000,Mega Drive Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,righttrigger:b2,start:b3,platform:Windows", + "030000005e0400002800000000000000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Windows", + "030000005e0400000300000000000000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows", + "030000005e0400000700000000000000,Microsoft SideWinder,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "030000005e0400000e00000000000000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows", + "030000005e0400002700000000000000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Windows", + "03000000280d00000202000000000000,Miller Lite Cantroller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b5,x:b2,y:b3,platform:Windows", + "03000000ad1b000023f0000000000000,MLG,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a6,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "03000000ad1b00003ef0000000000000,MLG Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700006382000000000000,MLG PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000004523000015e0000000000000,Mobapad Chitu HD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000491900000904000000000000,Mobapad Chitu HD,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000ffff00000000000000000000,Mocute M053,a:b3,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b11,leftstick:b7,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b6,righttrigger:b4,rightx:a3,righty:a4,start:b8,x:b1,y:b0,platform:Windows", + "03000000d6200000e589000000000000,Moga 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows", + "03000000d62000007162000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows", + "03000000d6200000ad0d000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000c62400002a89000000000000,Moga XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c62400002b89000000000000,Moga XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c62400001a89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000c62400001b89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000091200004488000000000000,MUSIA PlayStation 2 Input Display,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:b11,rightx:a2,righty:a3,start:b5,x:b1,y:b3,platform:Windows", + "03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows", + "03000000c9110000f055000000000000,Nacon GC100XF,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000c21100000791000000000000,Nacon GC101 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000006b140000010c000000000000,Nacon GC400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000006b1400001106000000000000,Nacon Revolution 3 PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "0300000085320000170d000000000000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "0300000085320000190d000000000000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000006b140000100d000000000000,Nacon Revolution Infinity PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000006b140000080d000000000000,Nacon Revolution Unlimited Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000bd12000001c0000000000000,Nebular,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000eb0300000000000000000000,NeGcon Adapter,a:a2,b:b13,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,lefttrigger:a4,leftx:a1,righttrigger:b11,start:b3,x:a3,y:b12,platform:Windows", + "0300000038070000efbe000000000000,NEO SE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "0300000092120000474e000000000000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Windows", + "03000000921200004b46000000000000,NES Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows", + "03000000000f00000100000000000000,NES Controller,a:b1,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows", + "03000000921200004346000000000000,NES Controller,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows", + "03000000790000004518000000000000,NEXiLUX GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows", + "03000000050b00000045000000000000,Nexus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Windows", + "03000000152000000182000000000000,NGDS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows", + "03000000ec110000e1a7000000000000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000007e0500006920000000000000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Windows", + "030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000007e0500007320000000000000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Windows", + "030000007e0500001920000000000000,NSO N64 Controller,+rightx:b8,+righty:b2,-rightx:b3,-righty:b7,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Windows", + "030000007e0500001720000000000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Windows", + "03000000550900001472000000000000,NVIDIA Controller,a:b11,b:b10,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b5,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b4,righttrigger:a5,rightx:a3,righty:a6,start:b3,x:b9,y:b8,platform:Windows", + "03000000550900001072000000000000,NVIDIA Shield,a:b9,b:b8,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b3,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b2,righttrigger:a4,rightx:a2,righty:a5,start:b0,x:b7,y:b6,platform:Windows", + "030000005509000000b4000000000000,NVIDIA Virtual,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000004b120000014d000000000000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "03000000d62000001d57000000000000,Nyko Airflo PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000120c00000288000000000000,Nyko Airflo Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "03000000791d00000900000000000000,Nyko Playpad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000782300000a10000000000000,Onlive Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,platform:Windows", + "030000000d0f00000401000000000000,Onyx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000008916000001fd000000000000,Onza CE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a3,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000008916000000fd000000000000,Onza TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows", + "0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,righttrigger:-a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000362800000100000000000000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows", + "03000000120c0000f60e000000000000,P4 Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows", + "03000000790000002201000000000000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000006f0e00008501000000000000,PDP Fightpad Pro GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000006f0e00000901000000000000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00008901000000000000,PDP Realmz Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000008f0e00004100000000000000,PlaySega,a:b1,b:b0,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b4,y:b3,platform:Windows", + "03000000d620000011a7000000000000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000dd62000015a7000000000000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000d620000012a7000000000000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000d620000013a7000000000000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000d62000002640000000000000,PowerA OPS Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000d62000003340000000000000,PowerA OPS Pro Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "0300000062060000d570000000000000,PowerA PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000d620000014a7000000000000,PowerA Spectra Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006d04000084ca000000000000,Precision,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "03000000d62000009557000000000000,Pro Elite PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000c62400001a53000000000000,Pro Ex Mini,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000d62000009f31000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000d6200000c757000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000120c0000110e000000000000,Pro5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000100800000100000000000000,PS1 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "030000008f0e00007530000000000000,PS1 Controller,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000100800000300000000000000,PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000250900000088000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000250900006888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b6,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000250900008888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "030000006b1400000303000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000009d0d00001330000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000120a00000100000000000000,PS3 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000120c00001307000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000120c00001cf1000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000120c0000f90e000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000250900000118000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000250900000500000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows", + "030000004c0500006802000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b8,x:b3,y:b0,platform:Windows", + "030000004f1f00000800000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "03000000632500007505000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows", + "03000000888800000804000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows", + "030000008f0e00000300000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows", + "030000008f0e00001431000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000ba2200002010000000000000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Windows", + "03000000120c00000807000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000111e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000121e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000130e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000150e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000180e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000181e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000191e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c00001e0e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000a957000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000aa57000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000f21c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000f31c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000f41c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000f51c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120c0000f70e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000120e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000160e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000001a1e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000004c0500005f0e000000000000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000004c050000e60c000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000004c050000f20d000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000830500005020000000000000,PSX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Windows", + "03000000300f00000111000000000000,Qanba 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000300f00000211000000000000,Qanba 2P,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000300f00000011000000000000,Qanba Arcade Stick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows", + "03000000300f00001611000000000000,Qanba Arcade Stick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows", + "03000000222c00000025000000000000,Qanba Dragon Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000222c00000020000000000000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000300f00001211000000000000,Qanba Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000300f00001210000000000000,Qanba Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows", + "03000000341a00000104000000000000,Qanba Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows", + "03000000222c00000223000000000000,Qanba Obsidian Arcade Stick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000222c00000023000000000000,Qanba Obsidian Arcade Stick PS4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000008a2400006682000000000000,R1 Mobile Controller,a:b3,b:b1,back:b7,leftx:a0,lefty:a1,start:b6,x:b4,y:b0,platform:Windows", + "03000000086700006626000000000000,RadioShack,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows", + "03000000ff1100004733000000000000,Ramox FPS Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows", + "030000009b2800002300000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows", + "030000009b2800006900000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows", + "030000009b2800000800000000000000,Raphnet Dreamcast Adapter,a:b2,b:b1,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,lefttrigger:a2,leftx:a0,righttrigger:a3,righty:a1,start:b3,x:b10,y:b9,platform:Windows", + "030000009b280000d000000000000000,Raphnet Dreamcast Adapter,a:b1,b:b0,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,lefttrigger:+a5,leftx:a0,lefty:a1,righttrigger:+a2,start:b3,x:b5,y:b4,platform:Windows", + "030000009b2800006200000000000000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows", + "030000009b2800003200000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows", + "030000009b2800006000000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows", + "030000009b2800001800000000000000,Raphnet Jaguar Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,platform:Windows", + "030000009b2800003c00000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows", + "030000009b2800006100000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows", + "030000009b2800006300000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows", + "030000009b2800006400000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows", + "030000009b2800000200000000000000,Raphnet NES Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows", + "030000009b2800004400000000000000,Raphnet PlayStation Adapter,a:b1,b:b2,back:b5,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b9,rightx:a3,righty:a4,start:b4,x:b0,y:b3,platform:Windows", + "030000009b2800004300000000000000,Raphnet Saturn,a:b0,b:b1,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows", + "030000009b2800000500000000000000,Raphnet Saturn Adapter 2.0,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows", + "030000009b2800000300000000000000,Raphnet SNES Adapter,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows", + "030000009b2800002600000000000000,Raphnet SNES Adapter,a:b1,b:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows", + "030000009b2800002e00000000000000,Raphnet SNES Adapter,a:b1,b:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows", + "030000009b2800002f00000000000000,Raphnet SNES Adapter,a:b1,b:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows", + "030000009b2800005600000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows", + "030000009b2800005700000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows", + "030000009b2800001e00000000000000,Raphnet Vectrex Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a1,lefty:a2,x:b2,y:b3,platform:Windows", + "030000009b2800002b00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows", + "030000009b2800002c00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows", + "030000009b2800008000000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows", + "03000000790000008f18000000000000,Rapoo Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows", + "0300000032150000a602000000000000,Razer Huntsman V3 Pro,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b12,dpright:b13,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000f8270000bf0b000000000000,Razer Kishi,a:b6,b:b7,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b18,leftshoulder:b12,leftstick:b19,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b13,rightstick:b20,righttrigger:b15,rightx:a3,righty:a4,start:b17,x:b9,y:b10,platform:Windows", + "03000000321500000204000000000000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000321500000104000000000000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000321500000010000000000000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000321500000507000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000321500000707000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000321500000710000000000000,Razer Raiju TE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000321500000a10000000000000,Razer Raiju TE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000321500000410000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000321500000910000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000321500000011000000000000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000321500000009000000000000,Razer Serval,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,leftx:a0,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000921200004547000000000000,Retro Bit Sega Genesis Adapter,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b6,x:b3,y:b4,platform:Windows", + "03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows", + "03000000830500006020000000000000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows", + "03000000632500007805000000000000,Retro Fighters Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "0300000003040000c197000000000000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows", + "03000000bd12000013d0000000000000,Retrolink Sega Saturn Classic Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows", + "03000000bd12000015d0000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows", + "03000000341200000400000000000000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Windows", + "0300000000f000000300000000000000,RetroUSB RetroPad,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows", + "0300000000f00000f100000000000000,RetroUSB Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows", + "03000000830500000960000000000000,Revenger,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b5,platform:Windows", + "030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000006b140000020d000000000000,Revolution Pro Controller 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000006b140000130d000000000000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001f01000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e00004601000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000c6240000fefa000000000000,Rock Candy Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e00008701000000000000,Rock Candy Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00001e01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00002801000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00002f01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000830500000052000000000000,Rockfire CosmoVoyager,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b10,leftshoulder:b6,lefttrigger:b7,misc1:b11,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "03000000830500007030000000000000,Rockfire Space Ranger,a:b0,b:b1,back:b5,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b9,righttrigger:b8,start:b2,x:b3,y:b4,platform:Windows", + "03000000050b0000e318000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows", + "03000000050b0000e518000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows", + "03000000050b00005819000000000000,ROG Chakram Core,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows", + "03000000050b0000181a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows", + "03000000050b00001a1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows", + "03000000050b00001c1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows", + "030000004f04000001d0000000000000,Rumble Force,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows", + "030000000d0f0000ad00000000000000,RX Gamepad,a:b0,b:b4,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b6,start:b9,x:b2,y:b1,platform:Windows", + "030000008916000000fe000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000c6240000045d000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e00001311000000000000,Saffun Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b0,platform:Windows", + "03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000a306000023f6000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000300f00001201000000000000,Saitek Dual Analog,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows", + "03000000a30600000701000000000000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Windows", + "03000000a30600000cff000000000000,Saitek P2500 Force Rumble,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b0,y:b1,platform:Windows", + "03000000a30600000d5f000000000000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows", + "03000000a30600000dff000000000000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b8,x:b0,y:b3,platform:Windows", + "03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows", + "03000000a306000018f5000000000000,Saitek P3200,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000300f00001001000000000000,Saitek P480 Rumble,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows", + "03000000a30600000901000000000000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b5,rightx:a3,righty:a2,x:b0,y:b1,platform:Windows", + "03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows", + "03000000a30600002106000000000000,Saitek PS1000 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000a306000020f6000000000000,Saitek PS2700 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000300f00001101000000000000,Saitek Rumble,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows", + "03000000e804000000a0000000000000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000bd12000010d1000000000000,Sanwa 4Button,a:b0,b:b1,x:b2,y:b3,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,platform:Windows", + "03000000c01100000252000000000000,Sanwa Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "03000000c01100004350000000000000,Sanwa Micro Grip P3,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,x:b3,y:b2,platform:Windows", + "03000000411200004550000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a1,righty:a2,start:b9,x:b1,y:b3,platform:Windows", + "03000000c01100004150000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows", + "03000000c01100004450000000000000,Sanwa Online Grip,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b14,x:b3,y:b4,platform:Windows", + "03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows", + "030000009d0d00001130000000000000,Sanwa PlayStation Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000830500006120000000000000,Sanwa Smart Grip II,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,x:b1,y:b3,platform:Windows", + "03000000630600000201000000000000,Sanwa Virtua Grip,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,x:b0,y:b1,platform:Windows", + "03000000c01100000051000000000000,Satechi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "030000004f04000028b3000000000000,Score A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows", + "03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,leftshoulder:b6,lefttrigger:b7,back:b8,start:b9,x:b3,y:b0,platform:Windows", + "03000000d804000086e6000000000000,Sega Multi Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a2,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows", + "0300000000050000289b000000000000,Sega Saturn Adapter,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows", + "0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows", + "03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", + "03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows", + "030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows", + "03000000632500002705000000000000,ShanWan Q36,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,platform:Windows", + "03000000f82100001900000000000000,Shogun Bros Chameleon X1,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000120c00001c1e000000000000,SnakeByte 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000140300000918000000000000,SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows", + "0300000081170000960a000000000000,SNES Controller,a:b4,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b5,y:b1,platform:Windows", + "03000000811700009d0a000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows", + "030000008b2800000300000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows", + "03000000921200004653000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows", + "030000008f0e00000910000000000000,Sony DualShock 2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows", + "03000000317300000100000000000000,Sony DualShock 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000666600006706000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows", + "03000000d9040000160f000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000e30500009605000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000fe1400002a23000000000000,Sony PlayStation Adapter,a:b0,b:b1,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,x:b2,y:b3,platform:Windows", + "030000004c050000da0c000000000000,Sony PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows", + "03000000632500002306000000000000,Sony PlayStation Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows", + "03000000f0250000c183000000000000,Sony PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000ff000000cb01000000000000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows", + "030000004c0500003713000000000000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows", + "03000000341a00000208000000000000,Speedlink 6555,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows", + "03000000341a00000908000000000000,Speedlink 6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000380700001722000000000000,Speedlink Competition Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,x:b2,y:b3,platform:Windows", + "030000008f0e00000800000000000000,Speedlink Strike FX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000c01100000591000000000000,Speedlink Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000de280000fc11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000de280000ff11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000120c0000160e000000000000,Steel Play Metaltech PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows", + "03000000110100003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows", + "03000000380700003847000000000000,Street Fighter Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows", + "030000001f08000001e4000000000000,Super Famicom Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows", + "03000000790000000418000000000000,Super Famicom Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows", + "03000000341200001300000000000000,Super Racer,a:b2,b:b3,back:b8,leftshoulder:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b7,x:b0,y:b1,platform:Windows", + "03000000457500002211000000000000,Szmy Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "030000004f0400000ab1000000000000,T16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows", + "030000000d0f00007b00000000000000,TAC GEAR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000e40a00000307000000000000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Windows", + "03000000e40a00000207000000000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Windows", + "03000000d814000001a0000000000000,TE Kitty,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows", + "03000000ba2200000701000000000000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b2,platform:Windows", + "03000000c61100001000000000000000,Tencent Xianyou Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows", + "03000000790000001c18000000000000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000790000002601000000000000,TGZ Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows", + "03000000591c00002400000000000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows", + "03000000591c00002600000000000000,THEGamepad,a:b2,b:b1,back:b6,leftx:a0,lefty:a1,start:b7,x:b3,y:b0,platform:Windows", + "030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows", + "030000004f04000023b3000000000000,Thrustmaster Dual Trigger PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000004f0400000ed0000000000000,Thrustmaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows", + "030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows", + "030000004f04000003d0000000000000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:-a3,leftx:a0,lefty:a1,paddle1:b6,paddle2:b7,rightshoulder:b5,rightstick:b11,righttrigger:-a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000004f04000008d0000000000000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000004f04000009d0000000000000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000011000000200000000000000,ThundeRobot G30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "030000006d04000088ca000000000000,Thunderpad,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "03000000666600000288000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "03000000666600000488000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "030000004f04000007d0000000000000,TMini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000571d00002100000000000000,Tomee NES Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Windows", + "03000000571d00002000000000000000,Tomee SNES Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows", + "03000000d62000006000000000000000,Tournament PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000c01100000055000000000000,Tronsmart,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000d60600002a00000000000000,Trust 850F,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,x:b3,y:b4,platform:Windows", + "030000005f140000c501000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000b80500000210000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000005f1400002a01000000000000,Trust Predator GM1200,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,x:b3,y:b4,platform:Windows", + "03000000580400000a10000000000000,Trust Sight Fighter,a:b0,b:b1,x:b3,y:b4,back:b5,start:b2,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,lefttrigger:b8,righttrigger:b9,platform:Windows", + "030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows", + "03000000411200000450000000000000,Twin Shock,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows", + "03000000d90400000200000000000000,TwinShock PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000151900005678000000000000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000101c0000171c000000000000,uRage Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "030000000b0400003065000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows", + "03000000242f00006e00000000000000,USB Controller,a:b1,b:b4,back:b10,leftshoulder:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b3,platform:Windows", + "03000000300f00000701000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000341a00002308000000000000,USB Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000666600000188000000000000,USB Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", + "030000006b1400000203000000000000,USB Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000790000000a00000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows", + "03000000b404000081c6000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows", + "03000000b50700001503000000000000,USB Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b0,y:b1,platform:Windows", + "03000000bd12000012d0000000000000,USB Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows", + "03000000ff1100004133000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000632500002305000000000000,USB Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", + "03000000882800000305000000000000,V5 Game Pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,x:b2,y:b3,platform:Windows", + "03000000790000001a18000000000000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows", + "03000000790000001b18000000000000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000006f0e00000302000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "030000006f0e00000702000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", + "0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:a3,righty:a4,start:b4,x:b2,y:b3,platform:Windows", + "03000000120c0000ab57000000000000,Warrior Joypad JS083,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "030000007e0500003003000000000000,Wii U Pro,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b6,leftstick:b11,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b12,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows", + "0300000032150000030a000000000000,Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "0300000032150000140a000000000000,Wolverine,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000002e160000efbe000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700001647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700002045000000000000,Xbox 360 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", + "03000000380700002644000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a5,start:b8,x:b2,y:b3,platform:Windows", + "03000000380700002647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000003807000026b7000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700003647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a7,righty:a5,start:b7,x:b2,y:b3,platform:Windows", + "030000005e0400001907000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e0400009102000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b000000fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b000001fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b000016f0000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000ad1b00008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000c62400000053000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000c6240000fdfa000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700002847000000000000,Xbox 360 Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000a102000000000000,Xbox 360 Receiver,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000120c00000a88000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "03000000120c00001088000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2~,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5~,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000002a0600002000000000000000,Xbox Controller,a:b0,b:b1,back:b13,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b5,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b15,righttrigger:b7,rightx:a2,righty:a5,start:b12,x:b2,y:b3,platform:Windows", + "03000000380700001645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "03000000380700002645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000380700003645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "03000000380700008645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e0400000202000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "030000005e0400008502000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e0400008702000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "030000005e0400008902000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b8,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b9,righttrigger:b4,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows", + "030000005e0400000c0b000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000fd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000ff02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e0000a802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000006f0e0000c802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000c62400003a54000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000005e040000130b000000000000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "03000000341a00000608000000000000,Xeox,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "03000000450c00002043000000000000,Xeox SL6556BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows", + "030000006f0e00000300000000000000,XGear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows", + "03000000e0ff00000201000000000000,Xiaomi Black Shark (L),back:b0,dpdown:b11,dpleft:b9,dpright:b10,dpup:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,platform:Windows", + "03000000172700004431000000000000,Xiaomi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows", + "03000000172700003350000000000000,Xiaomi XMGP01YM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000bc2000005060000000000000,Xiaomi XMGP01YM,+lefty:+a2,+righty:+a5,-lefty:-a1,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows", + "03000000c0160000e105000000000000,XinMo Dual Arcade,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows", + "030000007d0400000340000000000000,Xterminator Digital Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:-a4,lefttrigger:+a4,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b9,righttrigger:b2,rightx:a3,righty:a5,start:b8,x:b3,y:b4,platform:Windows", + "030000002c3600000100000000000000,Yawman Arrow,+rightx:h0.2,+righty:h0.4,-rightx:h0.8,-righty:h0.1,a:b4,b:b5,back:b6,dpdown:b15,dpleft:b14,dpright:b16,dpup:b13,leftshoulder:b10,leftstick:b0,lefttrigger:-a4,leftx:a0,lefty:a1,paddle1:b11,paddle2:b12,rightshoulder:b8,rightstick:b9,righttrigger:+a4,start:b3,x:b1,y:b2,platform:Windows", + "03000000790000004f18000000000000,ZDT Android Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows", + "03000000073500000400000000000000,Zenaim Arcade Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows", + "03000000120c00000500000000000000,Zeroplus Adapter,a:b2,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows", + "03000000120c0000101e000000000000,Zeroplus P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows", ]; Gamepad.addMappings(mappings); #elseif mac var mappings = [ - "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", - "6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", - "6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", - "6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", - "6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", - "4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X", - "4c05000000000000c405000000000000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X", - "4c05000000000000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X", - "5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", - "891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Mac OS X", - "4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Mac OS X", - "8f0e0000000000000300000000000000,Piranha xtreme,platform:Mac OS X,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2", - "0d0f0000000000004d00000000000000,HORI Gem Pad 3,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7", - "79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Mac OS X", - "4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,platform:Mac OS X,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - - "AD1B00000000000001F9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", - "050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,y:b9,x:b10,start:b6,guide:b8,back:b7,dpup:b2,dpleft:b0,dpdown:b3,dpright:b1,leftx:a0,lefty:a1,lefttrigger:b12,righttrigger:,leftshoulder:b11,platform:Mac OS X", - - "83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X", - "bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X", - "79000000000000001100000000000000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a3,lefty:a4,platform:Mac OS X", - "5e04000000000000dd02000000000000,Xbox One Wired Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4", - - "5e04000000000000ea02000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "5e04000000000000e002000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b10,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,x:b18,y:b17,back:b7,guide:b8,start:b6,leftstick:b23,rightstick:b24,leftshoulder:b19,rightshoulder:b20,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b21,righttrigger:b22,platform:Mac OS X", - "79000000000000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,x:b0,y:b12,back:b32,start:b36,leftstick:b40,rightstick:b44,leftshoulder:b16,rightshoulder:b20,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a4,rightx:a8,righty:a12,lefttrigger:b24,righttrigger:b28,platform:Mac OS X", - "2509000000000000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X", - "351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X", - "b4040000000000000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,x:b3,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X", - "81170000000000007e05000000000000,Sega Saturn,x:b0,a:b2,b:b4,y:b6,start:b13,dpleft:b15,dpdown:b16,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,lefttrigger:b10,rightshoulder:b9,righttrigger:a4,righttrigger:b11,leftx:a0,lefty:a2,platform:Mac OS X", - "10280000000000000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X", - "d814000000000000cecf000000000000,MC Cthulhu,platform:Mac OS X,leftx:,lefty:,rightx:,righty:,lefttrigger:b6,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,righttrigger:b7", - "0d0f0000000000006600000000000000,HORIPAD FPS PLUS 4,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:a4" + "030000008f0e00000300000009010000,2 In 1 Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000c82d00001930000000000000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Mac OS X", + "03000000c82d00001930000000020000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Mac OS X", + "03000000c82d00001930000001000000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Mac OS X", + "03000000c82d00000031000001000000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00000531000000020000,8BitDo Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X", + "03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00006a28000000010000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Mac OS X", + "03000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00001251000000020000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00001151000000020000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000a30c00002400000006020000,8BitDo M30,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,guide:b9,leftshoulder:b6,lefttrigger:b5,rightshoulder:b4,righttrigger:b7,start:b8,x:b3,y:b0,platform:Mac OS X", + "03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00000650000001000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00005106000000010000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,lefttrigger:a5,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00002090000000010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X", + "03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00006928000000010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Mac OS X", + "03000000c82d00002590000000010000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00002590000001000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00002690000000010000,8BitDo NEOGEO,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b10,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000003512000012ab000001000000,8BitDo NES30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d000012ab000001000000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00002028000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000022000000090000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000190000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000660000000020000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000960000000000000,8BitDo Pro 3,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000131000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000231000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000331000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000431000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00003028000000010000,8Bitdo SFC30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000102800000900000000000000,8BitDo SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000351000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00001290000001000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00004028000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000260000001000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001b30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001d30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001530000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001630000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001730000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001130000000020000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001330000000020000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001330000001000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000a00500003232000009010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X", + "03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X", + "0300000008100000e501000019040000,Anbernic Handheld,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b4,y:b3,platform:Mac OS X", + "03000000373500004610000001000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000a30c00002800000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000050b00000579000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b42,paddle1:b9,paddle2:b11,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X", + "03000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b23,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X", + "030000006a0e00001140000001000000,Atari CX Wireless Controller,a:b0,leftx:a0,lefty:a1,platform:Mac OS X", + "03000000503200000110000045010000,Atari VCS Classic,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X", + "03000000503200000110000047010000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X", + "03000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000008a3500000102000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X", + "030000008a3500000201000000010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000008a3500000202000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X", + "030000008a3500000402000000010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000008a3500000302000000010000,Backbone One PlayStation Edition,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X", + "03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X", + "03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "03000000120c0000200e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "03000000120c0000210e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000501d00009e61000001000000,CoreOrbits GamerPad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X", + "03000000d8140000cecf000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X", + "03000000a306000022f6000001030000,Cyborg V3 Rumble Pad PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000791d00000103000009010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "030000006e0500000720000010020000,Elecom JC-W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Mac OS X", + "030000006f0e00008401000003010000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000151900004000000001000000,Flydigi Vader 2,a:b14,b:b15,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Mac OS X", + "03000000b40400001124000001040000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000b40400001224000003030000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000790000004618000000010000,GameCube Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X", + "03000000ac0500001a06000002020000,GameSir T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000373500000411000023000000,GameSir X4A Xbox Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000ad1b000001f9000000000000,Gamestop BB070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000006f0e00000102000000000000,GameStop Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000ff1100003133000007010000,GameWare PC Control Pad,a:b2,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Mac OS X", + "03000000d11800000094000000010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X", + "030000007d0400000540000001010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000280400000140000000020000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000008f0e00000300000007010000,GreenAsia Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X", + "030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00005f00000000010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00005e00000000010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00008400000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00008500000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000341a00000302000014010000,Hori Fighting Stick Mini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00008800000000010000,Hori Fighting Stick mini 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00008700000000010000,Hori Fighting Stick mini 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00004d00000000000000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00003801000008010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Mac OS X", + "030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f0000aa00000072050000,Hori Real Arcade Pro for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "030000000d0f00000002000017010000,Hori Split Pad Fit,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00000002000015010000,Hori Switch Split Pad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00006e00000000010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00006600000000010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000000d0f00006600000000000000,Horipad FPS Plus 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f0000ee00000000010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f0000c100000072050000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000000d0f0000f600000000010000,Horipad Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000242e0000ff0b000000010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Mac OS X", + "03000000790000004e95000000010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Mac OS X", + "03000000830500006020000000000000,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X", + "03000000ef0500000300000000020000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X", + "03000000fd0500000030000010010000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Mac OS X", + "030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000242f00002d00000007010000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "030000006d04000019c2000000000000,Logitech Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000019c2000000020000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000016c2000000000000,Logitech F310,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000018c2000000000000,Logitech F510,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000019c2000005030000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000006d0400001ac2000004000000,Logitech Precision,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006d04000018c2000000010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000380700005032000000010000,Mad Catz PS3 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000380700008433000000010000,Mad Catz PS3 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000380700005082000000010000,Mad Catz PS4 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "03000000380700008483000000010000,Mad Catz PS4 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "0300000049190000020400001b010000,Manba One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "030000008f0e00001330000011010000,Mayflash Adapter,a:b2,b:b4,back:b16,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b12,lefttrigger:b16,leftx:a0,lefty:a2,rightshoulder:b14,rightx:a6~,righty:a4,start:b18,x:b0,y:b6,platform:Mac OS X", + "03000000790000004318000000010000,Mayflash GameCube Adapter,a:b4,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X", + "03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000242f00007300000000020000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X", + "0300000079000000d218000026010000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000d620000010a7000003010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000008f0e00001030000011010000,Mayflash Saturn Adapter,a:b0,b:b2,dpdown:b28,dpleft:b30,dpright:b26,dpup:b24,leftshoulder:b10,lefttrigger:b14,rightshoulder:b12,righttrigger:b4,start:b18,x:b6,y:b8,platform:Mac OS X", + "0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X", + "03000000790000000318000000010000,Mayflash Wii DolphinBar,a:b8,b:b12,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b44,leftshoulder:b16,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b4,platform:Mac OS X", + "03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X", + "03000000790000000018000000010000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X", + "030000005e0400002800000002010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Mac OS X", + "030000005e0400000300000006010000,Microsoft SideWinder,a:b0,b:b1,back:b9,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Mac OS X", + "030000005e0400000700000006010000,Microsoft SideWinder,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Mac OS X", + "030000005e0400002700000001010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Mac OS X", + "030000004523000015e0000072050000,Mobapad Chitu HD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X", + "03000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c62400002b89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000853200008906000000010000,Nacon Revolution X Unlimited,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000632500007505000000020000,NeoGeo mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000921200004b46000003020000,NES Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X", + "030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000ec110000e1a7000001010000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "030000007e0500006920000001010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Mac OS X", + "030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "030000007e0500000920000010020000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:Mac OS X", + "050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:Mac OS X", + "030000007e0500007320000001010000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Mac OS X", + "030000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Mac OS X", + "030000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000550900001472000025050000,NVIDIA Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X", + "030000004b120000014d000000010000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Mac OS X", + "0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,righttrigger:a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000006f0e00000901000002010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000008f0e00000300000000000000,Piranha Xtreme PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000100800000300000006010000,PlayStation Adapter,a:b2,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000d620000011a7000000020000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X", + "03000000d620000011a7000010050000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000d62000006dca000000010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X", + "030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X", + "030000004c0500006802000072050000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X", + "030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "0300004b4c0500005f0e000000010000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "050000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000005e040000e002000001000000,PXN P30 Pro Mobile,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X", + "03000000222c00000225000000010000,Qanba Dragon Arcade Joystick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000222c00000020000000010000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000009b2800005600000020020000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Mac OS X", + "030000009b2800008000000022020000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Mac OS X", + "030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000321500000204000000010000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000321500000104000000010000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "03000000321500000010000000010000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000321500000507000001010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000321500000011000000010000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "03000000321500000009000000020000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X", + "030000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X", + "0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000632500008005000000010000,Redgear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000632500002305000000010000,Redragon Saturn,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000921200004547000000020000,Retro Bit Sega Genesis Adapter,a:b0,b:b2,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,lefttrigger:b14,rightshoulder:b10,righttrigger:b4,start:b12,x:b6,y:b8,platform:Mac OS X", + "03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000790000001100000005010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000830500006020000000010000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Mac OS X", + "0300000003040000c197000000000000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Mac OS X", + "03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000341200000400000000000000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Mac OS X", + "030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000006b140000130d000000010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000004c0500006802000002100000,Rii RK707,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b3,righttrigger:b9,rightx:a2,righty:a3,start:b1,x:b15,y:b12,platform:Mac OS X", + "030000006f0e00008701000005010000,Rock Candy Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000c6240000fefa000000000000,Rock Candy PS3,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000e804000000a000001b010000,Samsung EIGP20,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b11,leftx:a1,lefty:a3,rightshoulder:b12,rightx:a4,righty:a5,start:b16,x:b7,y:b9,platform:Mac OS X", + "03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Mac OS X", + "03000000a30c00002500000006020000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Mac OS X", + "03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X", + "03000000b40400000a01000000000000,Sega Saturn,a:b0,b:b1,back:b5,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X", + "030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X", + "0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X", + "030000004c050000a00b000000000000,Sony DualShock 4 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "03000000666600006706000088020000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Mac OS X", + "030000004c050000da0c000000010000,Sony PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X", + "030000004c0500003713000000010000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000005e0400008e02000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X", + "03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X", + "03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X", + "05000000484944204465766963650000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X", + "050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X", + "03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X", + "03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X", + "03000000457500002211000000010000,SZMY Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000e40a00000307000001000000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X", + "03000000e40a00000207000001000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X", + "03000000790000001c18000000010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000790000001c18000003100000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000591c00002400000021000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X", + "03000000591c00002600000021000000,THEGamepad,a:b2,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Mac OS X", + "030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X", + "030000004f0400000ed0000000020000,Thrustmaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X", + "03000000571d00002100000021000000,Tomee NES Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Mac OS X", + "03000000bd12000015d0000000010000,Tomee Retro Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000571d00002000000021000000,Tomee SNES Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X", + "03000000bd12000015d0000000000000,Tomee SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X", + "030000005f140000c501000000020000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X", + "03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X", + "03000000632500002605000000010000,Uberwith Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000c0160000e105000000040000,Ultimate Atari Fight Stick,a:b2,b:b4,back:b18,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,rightshoulder:b8,righttrigger:b10,start:b16,x:b0,y:b6,platform:Mac OS X", + "03000000151900005678000010010000,Uniplay U6,a:b3,b:b6,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,leftstick:b31,lefttrigger:b21,leftx:a1,lefty:a3,rightshoulder:b19,rightstick:b33,righttrigger:b23,rightx:a4,righty:a5,start:b27,x:b11,y:b13,platform:Mac OS X", + "030000006f0e00000302000025040000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "030000006f0e00000702000003060000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X", + "050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X", + "050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X", + "030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4~,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000006f0e00000104000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "03000000c6240000045d000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e040000050b000003090000,Xbox Elite Controller Series 2,a:b0,b:b1,back:b31,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b53,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000011050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000200b000011050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000200b000013050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000200b000015050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X", + "030000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X", + "030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X", + "03000000c62400003a54000000000000,Xbox One PowerA Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X", + "030000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000007050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000130b000022050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000220b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "030000005e040000220b000021050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X", + "03000000120c0000100e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", + "03000000120c0000101e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X", ]; Gamepad.addMappings(mappings); #elseif linux var mappings = [ - "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", - "03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux", - "030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", - "030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", - "030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux", - "030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", - "030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", - "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c82d00001930000011010000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux", + "05000000c82d00001930000001000000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux", + "03000000c82d00000031000011010000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00000631000000010000,8BitDo Adapter 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux", + "03000000021000000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00006a28000000010000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Linux", + "03000000c82d00001251000011010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00001151000011010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00000650000011010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00000a20000000020000,8BitDo M30 Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux", + "03000000c82d00002090000011010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00002090000000010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux", + "03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00006928000011010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux", + "05000000c82d00006928000000010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux", + "05000000c82d00002590000001000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "03000000c82d00000310000011010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux", + "05000000c82d00008010000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux", + "03000000022000000090000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000190000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00002038000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00001030000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000020000000000000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "06000000c82d00000020000006010000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c82d00000960000011010000,8BitDo Pro 3,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000131000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000231000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000331000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000431000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Linux", + "03000000c82d00000060000011010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00000061000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "030000003512000012ab000010010000,8BitDo SFC30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux", + "030000003512000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux", + "05000000102800000900000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00003028000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00000351000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00001290000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00006228000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000260000011010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00000631000010010000,8BitDo Ultimate,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c82d00000631000014010000,8BitDo Ultimate,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c82d00000760000011010000,8BitDo Ultimate,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c82d00001130000011010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00001230000011010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00001330000011010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00000a31000014010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c82d00001d30000011010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000c82d00001b30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00001530000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00001630000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00001730000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00000121000011010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000c82d00000121000000010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux", + "05000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux", + "03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux", + "05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux", + "03000000c01100000355000011010000,Acrux Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00008801000011010000,Afterglow Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00003901000000430000,Afterglow Prismatic Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00003901000013020000,Afterglow Prismatic Controller 048-007-NA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00001302000000010000,Afterglow Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00003901000020060000,Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000100000008200000011010000,Akishop Customs PS360,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "030000007c1800000006000010010000,Alienware Dual Compatible Game PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Linux", + "05000000491900000204000021000000,Amazon Fire Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000491900001904000011010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux", + "05000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux", + "0300000008100000e501000001010000,Anbernic Handheld,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b3,y:b4,platform:Linux", + "03000000020500000913000010010000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000373500000710000010010000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000373500004610000001000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000190e00000110000010010000,Aquaplus Piece,a:b1,b:b0,back:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b2,platform:Linux", + "03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux", + "03000000a30c00002800000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux", + "05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux", + "05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux", + "03000000050b00000579000011010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b36,paddle1:b52,paddle2:b53,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b21,paddle1:b22,paddle2:b23,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000006a0e00001140000010010000,Atari CX Controller,a:b0,leftx:a0,lefty:a1,platform:Linux", + "03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux", + "03000000503200000110000011010000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux", + "05000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux", + "05000000503200000110000044010000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux", + "05000000503200000110000046010000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux", + "03000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux", + "03000000503200000210000011010000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux", + "05000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux", + "05000000503200000210000045010000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux", + "05000000503200000210000046010000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux", + "05000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:-a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux", + "030000008a3500000201000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000008a3500000202000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000008a3500000302000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000008a3500000402000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000c62400001b89000011010000,BDA MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000c21100000791000011010000,Be1 GC101 Controller 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000c31100000791000011010000,Be1 GC101 Controller 1.03,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000005e0400008e02000003030000,Be1 GC101 Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000bc2000004d50000011010000,Beitong A1T2 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000000d0500000308000010010000,Belkin Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux", + "05000000bc2000000055000001000000,Betop AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000bc2000006412000011010000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b30,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "030000006b1400000209000011010000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000120c0000300e000011010000,Brook Audio Fighting Board PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000120c0000310e000011010000,Brook Audio Fighting Board PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000120c0000200e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000120c0000210e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "03000000d81d00000b00000010010000,Buffalo BSGP1601,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Linux", + "03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000af1e00002400000010010000,Clockwork Pi DevTerm,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b9,x:b3,y:b0,platform:Linux", + "030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux", + "03000000632500007a05000001020000,Cosmic Byte Ares Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux", + "03000000a306000022f6000011010000,Cyborg V3 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux", + "03000000791d00000103000010010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000c11100000191000011010000,EasySMX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000242f00009100000000010000,EasySMX ESM-9101,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006e0500000320000010010000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux", + "030000006e0500000720000010010000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux", + "030000007d0400000640000010010000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Linux", + "03000000430b00000300000000010000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Linux", + "030000006f0e00008401000011010000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00008101000011010000,Faceoff Deluxe Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00008001000011010000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000852100000201000010010000,FF GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "05000000b40400001224000001010000,Flydigi APEX 4,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b20,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000b40400001224000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000defa000001c0000000000000,Flydigi Vader 5 Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,misc2:b12,misc3:b13,misc4:b14,misc5:b19,paddle1:b15,paddle2:b16,paddle3:b17,paddle4:b18,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000007e0500003703000000000000,GameCube Adapter,a:b0,b:b1,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux", + "19000000030000000300000002030000,GameForce Controller,a:b1,b:b0,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "03000000373500000b10000019010000,GameSir Cyclone 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000ac0500005b05000010010000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000558500001b06000010010000,GameSir G4 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000ac0500002d0200001b010000,GameSir G4s,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b33,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000ac0500007a05000011010000,GameSir G5,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000373500009710000001020000,GameSir Kaleid Flux,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000ac0500001a06000011010000,GameSir T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000373500000410000044010000,GameSir T4 Kaleid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000bc2000005656000011010000,GameSir T4w,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000373500009410000010010000,GameSir Tegenaria Lite,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000008f0e00000800000010010000,Gasia PlayStation Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000451300000010000010010000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "03000000f025000021c1000010010000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000f0250000c283000010010000,Gioteck VX2 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "190000004b4800000010000000010000,GO-Advance Controller,a:b1,b:b0,back:b10,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,leftshoulder:b4,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b13,start:b15,x:b2,y:b3,platform:Linux", + "190000004b4800000010000001010000,GO-Advance Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b13,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b16,righttrigger:b15,start:b17,x:b2,y:b3,platform:Linux", + "190000004b4800000011000000010000,GO-Super Gamepad,a:b0,b:b1,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b3,y:b2,platform:Linux", + "03000000f0250000c183000010010000,Goodbetterbest Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000d11800000094000011010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux", + "05000000d11800000094000000010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux", + "0300000079000000d418000000010000,GPD Win 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000001010000,GPD Win Max 2 6800U Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000007d0400000540000000010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "03000000280400000140000000010000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "030000008f0e00000610000000010000,GreenAsia Electronics Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux", + "030000008f0e00001200000010010000,GreenAsia Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "0500000047532067616d657061640000,GS Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "03000000f0250000c383000010010000,GT VX2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "030000008a2e0000dd10000011010000,Hand Held Legend GC Ultimate,a:b0,b:b2,back:b17,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b18,leftshoulder:b10,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b19,misc2:b24,paddle1:b13,paddle2:b12,rightshoulder:b11,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b1,y:b3,platform:Linux", + "030000008a2e0000df10000011010000,Hand Held Legend ProGCC,a:b1,b:b0,back:b17,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b18,leftshoulder:b10,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b19,paddle1:b13,paddle2:b12,rightshoulder:b11,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b3,y:b2,platform:Linux", + "06000000adde0000efbe000002010000,Hidromancer Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d81400000862000011010000,HitBox PS3 PC Analog Mode,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux", + "03000000c9110000f055000011010000,HJC Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "030000000d0f00006d00000020010000,Hori EDGE 301,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:+a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000000d0f00008400000011010000,Hori Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00005f00000011010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00005e00000011010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000000d0f00005001000009040000,Hori Fighting Commander Octa Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000000d0f00008500000010010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00008600000002010000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "030000000d0f00003701000013010000,Hori Fighting Stick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b3,y:b2,platform:Linux", + "030000000d0f00008800000011010000,Hori Fighting Stick mini 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00008700000011010000,Hori Fighting Stick mini 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,rightstick:b11,righttrigger:a4,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000000d0f00001000000011010000,Hori Fightstick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "03000000ad1b000003f5000033050000,Hori Fightstick VX,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b8,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux", + "030000000d0f00004d00000011010000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000000d0f00003801000011010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Linux", + "030000000d0f00009200000011010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00001100000011010000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00002200000011010000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00006a00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00006b00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00001600000000010000,Hori Real Arcade Pro EXSE,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux", + "030000000d0f0000aa00000011010000,Hori Real Arcade Pro for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "030000000d0f00008501000017010000,Hori Split Pad Fit,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000000d0f00008501000015010000,Hori Switch Split Pad Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000000d0f00006e00000011010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00006600000011010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000000d0f0000ee00000011010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f0000c100000011010000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000000d0f00006700000001010000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000000d0f0000ab01000011010000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc2:b2,paddle1:b19,paddle2:b18,paddle3:b15,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000000d0f00009601000091000000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc2:b2,paddle1:b19,paddle2:b18,paddle3:b15,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000000d0f0000f600000001000000,Horipad Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "03000000341a000005f7000010010000,HuiJia GameCube Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux", + "05000000242e00000b20000001000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Linux", + "03000000242e0000ff0b000011010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Linux", + "03000000242e00006a38000010010000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Linux", + "03000000242e00008816000001010000,Hyperkin X91,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000f00300008d03000011010000,HyperX Clutch,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000f00300008d04000000010000,HyperX Clutch,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000830500006020000010010000,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux", + "03000000d80400004aea000011010000,icedragon.io STAC Dance Pad,a:b0,b:b1,back:b4,x:b2,y:b3,platform:Linux", + "03000000d80400004bea000011010000,icedragon.io STAC Dance Pad,a:b0,b:b1,back:b4,x:b2,y:b3,platform:Linux", + "030000008a2e0000d910000011010000,icedragon.io STAC2 Dance Pad,a:b0,b:b1,back:b4,x:b2,y:b3,platform:Linux", + "030000008a2e0000e910000011010000,icedragon.io STAC2 Dance Pad,a:b8,b:b9,back:b12,x:b10,y:b11,platform:Linux", + "030000008f0e00001330000001010000,iCode Retro Adapter,b:b3,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b1,start:b7,x:b2,y:b0,platform:Linux", + "050000006964726f69643a636f6e0000,idroidcon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000b50700001503000010010000,Impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux", + "03000000d80400008200000003000000,IMS PCU0,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux", + "03000000120c00000500000010010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux", + "03000000ef0500000300000000010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux", + "03000000fd0500000030000000010000,InterAct GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Linux", + "03000000fd0500002a26000000010000,InterAct HammerHead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux", + "0500000049190000020400001b010000,Ipega PG 9069,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b161,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000632500007505000011010000,Ipega PG 9099,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "0500000049190000030400001b010000,Ipega PG9099,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000491900000204000000000000,Ipega PG9118,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000300f00001101000010010000,Jess Tech Colour Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux", + "03000000300f00001001000010010000,Jess Tech Dual Analog Rumble,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux", + "03000000300f00000b01000010010000,Jess Tech GGE909 PC Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux", + "03000000ba2200002010000001010000,Jess Technology Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux", + "030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux", + "050000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux", + "030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux", + "050000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux", + "03000000bd12000003c0000010010000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000242f00002d00000011010000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000242f00008a00000011010000,JYS Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux", + "03000000314100001935000000010000,LeadJoy Xeno Plus,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:+a5,rightx:a4,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006d040000d1ca000000000000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006d040000d1ca000011010000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006d0400001dc2000014400000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006d0400001ec2000019200000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006d0400001ec2000020200000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006d04000019c2000011010000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006d0400001fc2000005030000,Logitech F710,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006d04000019c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006d0400000ac2000010010000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux", + "030000006d04000011c2000010010000,Logitech WingMan RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux", + "05000000380700006652000025010000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700008532000010010000,Mad Catz Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700005032000011010000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700005082000011010000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux", + "03000000380700008031000011010000,Mad Catz FightStick Alpha PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700008081000011010000,Mad Catz FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700008034000011010000,Mad Catz Fightstick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700008084000011010000,Mad Catz Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000380700008433000011010000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700008483000011010000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000380700001888000010010000,Mad Catz Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700003888000010010000,Mad Catz Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000380700001647000010040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000380700003847000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000120c00000500000000010000,Manta DualShock 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "030000008f0e00001330000010010000,Mayflash Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Linux", + "03000000790000004318000010010000,Mayflash GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "03000000242f00007300000011010000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux", + "0300000079000000d218000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000d620000010a7000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000242f0000f700000001010000,Mayflash Magic S Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000008f0e00001030000010010000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux", + "0300000025090000e803000001010000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux", + "03000000790000000318000011010000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux", + "03000000790000000018000011010000,Mayflash Wii U Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000b50700001203000010010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux", + "03000000b50700004f00000000010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux", + "03000000780000000600000010010000,Microntek Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux", + "030000005e0400002800000000010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Linux", + "030000005e0400000300000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux", + "030000005e0400000700000000010000,Microsoft SideWinder,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux", + "030000005e0400000e00000000010000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux", + "030000005e0400002700000000010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Linux", + "030000005e0400008502000000010000,Microsoft Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux", + "030000005e0400008902000021010000,Microsoft Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux", + "030000005e0400008e02000001000000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.1,dpleft:h0.2,dpright:h0.8,dpup:h0.4,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000004010000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000056210000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000062230000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000d102000001010000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000d102000003020000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000dd02000003020000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000ea02000008040000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000ea0200000f050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000120b000009050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000120b000014050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000e302000003020000,Microsoft Xbox One Elite,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000000b000007040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000000b000008040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "050000005e040000050b000003090000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e0400008e02000030110000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b00000b050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000016050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000017050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000120b000001050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux", + "03000000790000001c18000010010000,Mobapad Chitu HD,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000004d4f435554452d3035335800,Mocute 053X,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "05000000e80400006e0400001b010000,Mocute 053X M59,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000004d4f435554452d3035305800,Mocute 054X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000d6200000e589000001000000,Moga 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux", + "05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux", + "05000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux", + "03000000c62400002b89000011010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000c62400001a89000000010000,MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000250900006688000000010000,MP8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux", + "030000005e0400008e02000010020000,MSI GC20 V2,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000f70600000100000000010000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Linux", + "030000006b1400000906000014010000,Nacon Asymmetric PS4 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "0300000085320000030c000011010000,Nacon GC100,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000853200000706000012010000,Nacon GC100,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006b140000010c000010010000,Nacon GC400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "05000000853200000503000000010000,Nacon MGX Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "0300000085320000170d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "0300000085320000190d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "0300000085320000180d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "0300000085320000160d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000004f1f00000800000011010000,NeoGeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "0300000092120000474e000000010000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Linux", + "03000000790000004518000010010000,NEXiLUX GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Linux", + "060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux", + "03000000790000004618000010010000,Nintendo GameCube Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux", + "03000000ec110000e1a7000010010000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "030000007e0500006920000011010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Linux", + "060000004e696e74656e646f20537700,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux", + "060000007e0500000620000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux", + "060000007e0500000820000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux", + "050000004c69632050726f20436f6e00,Nintendo Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "050000007e0500000620000001800000,Nintendo Switch Left Joy-Con,a:b16,b:b15,back:b4,leftshoulder:b6,leftstick:b12,leftx:a1,lefty:a0~,rightshoulder:b8,start:b9,x:b14,y:b17,platform:Linux", + "030000007e0500000920000000026803,Nintendo Switch Pro Controller,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Linux", + "030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux", + "050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux", + "050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux", + "05000000010000000100000003000000,Nintendo Wii Remote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "050000007e0500003003000001000000,Nintendo Wii U Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux", + "050000005a1d00000218000003000000,Nokia GC 5000,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000007e0500007320000011010000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Linux", + "030000007e0500001920000011810000,NSO N64 Controller,+rightx:b2,+righty:b3,-rightx:b4,-righty:b10,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b9,start:b11,platform:Linux", + "050000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Linux", + "050000007e0500001920000001800000,NSO N64 Controller,+rightx:b2,+righty:b3,-rightx:b4,-righty:b10,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b9,start:b11,platform:Linux", + "030000007e0500001e20000011810000,NSO Sega Genesis Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,misc1:b3,rightshoulder:b2,righttrigger:b4,start:b5,platform:Linux", + "030000007e0500001720000011810000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux", + "050000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b8,start:b10,x:b3,y:b2,platform:Linux", + "050000007e0500001720000001800000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux", + "03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux", + "03000000550900001472000011010000,NVIDIA Controller,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux", + "05000000550900001472000001000000,NVIDIA Controller,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux", + "030000004b120000014d000000010000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "03000000451300000830000010010000,Nyko CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "19000000010000000100000001010000,ODROID Go 2,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux", + "19000000010000000200000011000000,ODROID Go 2,a:b1,b:b0,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b12,leftshoulder:b4,leftstick:b14,lefttrigger:b13,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b16,start:b17,x:b2,y:b3,platform:Linux", + "05000000362800000100000002010000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux", + "05000000362800000100000003010000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux", + "05000000362800000100000004010000,OUYA Controller,a:b0,b:b3,back:b14,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,start:b16,x:b1,y:b2,platform:Linux", + "03000000830500005020000010010000,Padix Rockfire PlayStation Bridge,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Linux", + "03000000ff1100003133000010010000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "030000006f0e0000b802000001010000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e0000b802000013020000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e0000d702000006640000,PDP Black Camo Wired Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b13,dpup:b14,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00003101000000010000,PDP EA Sports Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00008501000011010000,PDP Fightpad Pro Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "030000006f0e0000c802000012010000,PDP Kingdom Hearts Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00002801000011010000,PDP PS3 Rock Candy Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00000901000011010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00002f01000011010000,PDP Wired PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000ad1b000004f9000000010000,PDP Xbox 360 Versus Fighting,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e0000f102000000000000,PDP Xbox Atomic,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e0000a802000023020000,PDP Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "030000006f0e0000a702000023020000,PDP Xbox One Raven Black,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e0000d802000006640000,PDP Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e0000ef02000007640000,PDP Xbox Series Kinetic Wired Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d62000000540000001010000,PowerA Advantage Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d620000011a7000011010000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000dd62000015a7000011010000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000d620000012a7000011010000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000d62000000140000001010000,PowerA Fusion Pro 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000c62400001a53000000010000,PowerA Mini Pro Ex,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d620000013a7000011010000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000d62000006dca000011010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000d620000014a7000011010000,PowerA Spectra Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000c62400001a58000001010000,PowerA Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d62000000220000001010000,PowerA Xbox One Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux", + "03000000d62000000228000001010000,PowerA Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c62400001a54000001010000,PowerA Xbox One Mini Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d62000000240000001010000,PowerA Xbox One Spectra Infinity,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d62000000520000050010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d62000000b20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000d62000000f20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000250900000017000010010000,PS SS N64 Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b5,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2~,righty:a3,start:b8,platform:Linux", + "03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux", + "03000000120c0000160e000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux", + "030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", "030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux", - "030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux", - "050000004c050000c405000000010000,Sony DualShock 4 BT,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", - "030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux", - "050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux", - "030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux", - "030000006f0e00003001000001010000,EA Sports PS3 Controller,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7", - "03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", - "030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", - "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", - "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", - "03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux", - "03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Linux", - "030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux", - "030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5", - "030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2", - "030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2", - "030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux", - "030000006d04000016c2000010010000,Logitech Logitech Dual Action,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux", - "030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,platform:Linux", - "030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "05000000d6200000ad0d000001000000,Moga Pro,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4", - "030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7", - "030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7", - "0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux", - "0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux", - "030000006f0e00001f01000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "03000000280400000140000000010000,Gravis GamePad Pro USB ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1", - "030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "030000005e0400008502000000010000,Microsoft X-Box pad (Japan),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2", - "03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,platform:Linux,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5", - "030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux", - "030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux", - "03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux", - "060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux", - "050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux", - "03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a3,rightx:a1,righty:a4", - "03000000666600000488000000010000,Super Joy Box 5 Pro,platform:Linux,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13", - "05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2", - "05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2", - "030000008916000001fd000024010000,Razer Onza Classic Edition,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "030000005e040000d102000001010000,Microsoft X-Box One pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "030000005e040000dd02000003020000,Microsoft X-Box One pad v2,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux", - "03000000790000001100000010010000,RetroLink Saturn Classic Controller,platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1", - "050000007e0500003003000001000000,Nintendo Wii U Pro Controller,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,guide:b10,leftshoulder:b4,rightshoulder:b5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16", - "030000005e0400008e02000004010000,Microsoft X-Box 360 pad,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2", - "030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1", - "030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7", - "03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux", - "030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "030000006f0e00001304000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:a0,rightstick:a3,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux", - "03000000bd12000015d0000010010000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux", - "03000000790000001100000010010000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux", - "03000000c9110000f055000011010000,HJC Game GAMEPAD,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b2,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:h0.2,righttrigger:b7,b:b1,platform:Linux", - "03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux", - "03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,y:b3,x:b0,start:b9,guide:,back:,leftstick:,rightstick:,leftshoulder:,dpleft:b15,dpdown:b14,dpright:b13,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,rightshoulder:b7,dpup:b12,platform:Linux", - "030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,platform:Linux,x:b0,a:b2,b:b3,y:b1,back:b10,guide:b12,start:b11,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3", - "030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,platform:Linux,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,guide:b8,leftstick:b9,rightstick:b10,lefttrigger:a2,righttrigger:a5,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux", - "030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,platform:Linux,a:b0,b:b2,x:b1,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7", - "05000000102800000900000000010000,8Bitdo SFC30 GamePad,platform:Linux,x:b4,a:b1,b:b0,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1", - - "03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,leftx:a0,lefty:a1", - "030000000d0f00000d00000000010000,hori,platform:Linux,a:b0,b:b6,y:b2,x:b1,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,start:b9,guide:b10,back:b8,leftshoulder:b3,rightshoulder:b7,leftx:b4,lefty:b5", - - "03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5", - "03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,platform:Linux,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7", - "03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),platform:Linux,a:b3,b:b4,y:b1,x:b0,start:b7,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5", - "05000000010000000100000003000000,Nintendo Wiimote,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7", - - "030000005e0400008e02000062230000,Microsoft X-Box 360 pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,y:b1,x:b0,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,platform:Linux", - "030000006f0e00000103000000020000,Logic3 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "05000000380700006652000025010000,Mad Catz C.T.R.L.R ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3", - - "030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4", - "03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:a2,righttrigger:a5", - - "05000000a00500003232000001000000,8Bitdo Zero GamePad,platform:Linux,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1", - "030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Linux", - "03000000100800000300000010010000,USB Gamepad,platform:Linux,a:b2,b:b1,x:b3,y:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5", - "05000000ac0500003232000001000000,VR-BOX,platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5", - - "03000000780000000600000010010000,Microntek USB Joystick,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftx:a0,lefty:a1" + "030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "030000005f1400003102000010010000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "030000006f0e00001402000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000008f0e00000300000010010000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "050000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux", + "050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux", + "050000004c0500006802000000800000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "05000000504c415953544154494f4e00,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux", + "060000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux", + "030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "030000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "03000000c01100000140000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "050000004c050000c405000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "0300004b4c0500005f0e000011010000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000004c050000e60c000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "030000004c050000f20d000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000004c050000f20d000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "050000004c050000e60c000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "050000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "050000004c050000f20d000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux", + "03000000300f00001211000011010000,Qanba Arcade Joystick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux", + "03000000222c00000225000011010000,Qanba Dragon Arcade Joystick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000222c00000025000011010000,Qanba Dragon Arcade Joystick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000222c00001220000011010000,Qanba Drone 2 Arcade Joystick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000222c00001020000011010000,Qanba Drone 2 Arcade Joystick PS5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000222c00000020000011010000,Qanba Drone Arcade PS4 Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000300f00001210000010010000,Qanba Joystick Plus,a:b0,b:b1,back:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,start:b9,x:b2,y:b3,platform:Linux", + "03000000222c00000223000011010000,Qanba Obsidian Arcade Joystick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000222c00000023000011010000,Qanba Obsidian Arcade Joystick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000009b2800000300000001010000,Raphnet 4nes4snes,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux", + "030000009b2800004200000001010000,Raphnet Dual NES Adapter,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Linux", + "030000009b2800006500000000000000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux", + "030000009b2800006500000001010000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux", + "03000000401700007f05000001010000,Raphnet GC and N64 Adapter,a:b5,b:b3,back:b8,dpdown:b10,dpleft:b12,dpright:b11,dpup:b9,leftshoulder:b6,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:-a5,rightx:a2,righty:a3,start:b1,x:b4,y:b2,platform:Linux", + "030000009b2800003200000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux", + "030000009b2800006000000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux", + "030000009b2800003c00000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux", + "030000009b2800006100000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux", + "030000009b2800006300000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux", + "030000009b2800006400000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux", + "030000009b2800008000000020020000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux", + "030000009b2800008000000001010000,Raphnet Wii Classic Adapter V3,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux", + "03000000f8270000bf0b000011010000,Razer Kishi,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000321500000204000011010000,Razer Panthera PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000321500000104000011010000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000321500000810000011010000,Razer Panthera PS4 Evo Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000321500000010000011010000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000321500000507000000010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000321500000a10000001000000,Razer Raiju Tournament Edition,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000321500000011000011010000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000008916000000fe000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c6240000045d000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux", + "050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux", + "0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000321500000b10000011010000,Razer Wolverine PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "0300000032150000140a000001010000,Razer Wolverine Ultimate Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000000d0f0000c100000010010000,Retro Bit Legacy16,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b12,leftshoulder:b4,lefttrigger:b6,misc1:b13,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux", + "03000000790000001100000010010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Linux", + "0300000003040000c197000011010000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux", + "190000004b4800000111000000010000,RetroGame Joypad,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "0300000081170000990a000001010000,Retronic Adapter,a:b0,leftx:a0,lefty:a1,platform:Linux", + "0300000000f000000300000000010000,RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux", + "00000000526574726f53746f6e653200,RetroStone 2 Controller,a:b1,b:b0,back:b10,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,start:b11,x:b4,y:b3,platform:Linux", + "03000000341200000400000000010000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Linux", + "030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000006b140000130d000011010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00001f01000000010000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00008701000011010000,Rock Candy Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00001e01000011010000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000c6240000fefa000000010000,Rock Candy Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00004601000001010000,Rock Candy Xbox One Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00001311000011010000,Saffun Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b0,platform:Linux", + "03000000a306000023f6000011010000,Saitek Cyborg PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux", + "03000000a30600001005000000010000,Saitek P150,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b2,righttrigger:b5,x:b3,y:b4,platform:Linux", + "03000000a30600000701000000010000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Linux", + "03000000a30600000cff000010010000,Saitek P2500 Force Rumble,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b0,y:b1,platform:Linux", + "03000000a30600000d5f000010010000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux", + "03000000a30600000c04000011010000,Saitek P2900,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux", + "03000000a306000018f5000010010000,Saitek P3200 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux", + "03000000300f00001201000010010000,Saitek P380,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux", + "03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux", + "03000000a30600000b04000000010000,Saitek P990 Dual Analog,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux", + "03000000a306000020f6000011010000,Saitek PS2700 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux", + "05000000e804000000a000001b010000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000d81d00000e00000010010000,Savior,a:b0,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b9,x:b4,y:b5,platform:Linux", + "03000000952e00004b43000011010000,Scuf Envision,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux", + "03000000952e00004d43000011010000,Scuf Envision,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux", + "03000000952e00004e43000011010000,Scuf Envision,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux", + "03000000a30c00002500000011010000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Linux", + "03000000790000001100000011010000,Sega Saturn,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux", + "03000000b40400000a01000000010000,Sega Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux", + "03000000632500002305000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000632500002605000010010000,ShanWan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000632500007505000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000bc2000000055000010010000,ShanWan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000341a00000908000010010000,SL6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "03000000250900000500000000010000,SmartJoy PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux", + "030000004b2900000430000011000000,Snakebyte Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000790000002601000011010000,SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux", + "050000004c050000cc09000001000000,Sony DualShock 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "03000000666600006706000000010000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux", + "03000000d9040000160f000000010000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux", + "030000004c050000da0c000011010000,Sony PlayStation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux", + "03000000ff000000cb01000010010000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux", + "030000004c0500003713000011010000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux", + "030000005e0400008e02000073050000,Speedlink Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000020200000,SpeedLink Xeox Pro Analog,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "05000000381000001214000001000000,SteelSeries Free,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a2,righttrigger:a3,platform:Linux", + "050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b10,guide:b11,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Linux", + "03000000381000003014000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000381000003114000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000ad1b000038f0000090040000,Street Fighter IV Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000003b07000004a1000000010000,Suncom SFX Plus,a:b0,b:b2,back:b7,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux", + "030000001f08000001e4000010010000,Super Famicom Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux", + "03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux", + "0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux", + "030000008f0e00000d31000010010000,SZMY Power 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000457500000401000011010000,SZMY Power DS4 Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000457500002211000010010000,SZMY Power Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "030000008f0e00001431000010010000,SZMY Power PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000e40a00000307000011010000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux", + "03000000e40a00000207000011010000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux", + "03000000ba2200000701000001010000,Technology Innovation PlayStation Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux", + "03000000790000001c18000011010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000591c00002400000010010000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux", + "03000000591c00002600000010010000,THEGamepad,a:b2,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux", + "030000004f04000015b3000001010000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux", + "030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux", + "030000004f04000020b3000010010000,Thrustmaster Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux", + "030000004f04000023b3000000010000,Thrustmaster Dual Trigger PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000004f0400000ed0000011010000,Thrustmaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000b50700000399000000010000,Thrustmaster Firestorm Digital 2,a:b2,b:b4,back:b11,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b0,righttrigger:b9,start:b1,x:b3,y:b5,platform:Linux", + "030000004f04000003b3000010010000,Thrustmaster Firestorm Dual Analog 2,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b9,rightx:a2,righty:a3,x:b1,y:b3,platform:Linux", + "030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux", + "030000004f04000004b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux", + "030000004f04000026b3000002040000,Thrustmaster GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c6240000025b000002020000,Thrustmaster GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000004f04000008d0000000010000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000004f04000009d0000000010000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000004f04000007d0000000010000,Thrustmaster T Mini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "030000004f04000012b3000010010000,Thrustmaster Vibrating Gamepad,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux", + "03000000571d00002000000010010000,Tomee SNES Adapter,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux", + "03000000bd12000015d0000010010000,Tomee SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux", + "03000000d814000007cd000011010000,Toodles 2008 Chimp PC PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux", + "030000005e0400008e02000070050000,Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000c01100000591000011010000,Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "03000000680a00000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux", + "03000000780300000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux", + "03000000e00d00000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux", + "03000000f00600000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux", + "030000005f140000c501000010010000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux", + "06000000f51000000870000003010000,Turtle Beach Recon,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000f51000001370000000010000,Turtle Beach ReactR,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux", + "03000000f51000001370000000000000,Turtle Beach ReactR,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux", + "03000000100800000100000010010000,Twin PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux", + "03000000c0160000e105000010010000,Ultimate Atari Fight Stick,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,platform:Linux", + "03000000151900005678000010010000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux", + "03000000790000000600000007010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux", + "03000000790000001100000000010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux", + "03000000de2800000112000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux", + "03000000de2800000112000011010000,Valve Steam Controller,a:b2,b:b3,back:b10,dpdown:+a5,dpleft:-a4,dpright:+a4,dpup:-a5,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux", + "03000000de2800000211000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux", + "03000000de2800000211000011010000,Valve Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux", + "03000000de2800004211000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux", + "03000000de2800004211000011010000,Valve Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux", + "03000000de280000fc11000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "05000000de2800000212000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux", + "05000000de2800000511000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux", + "05000000de2800000611000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux", + "03000000de2800000512000010010000,Valve Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,platform:Linux", + "03000000de2800000512000011010000,Valve Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,misc1:b2,paddle1:b21,paddle2:b20,paddle3:b23,paddle4:b22,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,platform:Linux", + "03000000790000001a18000011010000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux", + "03000000790000001b18000011010000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "030000006f0e00000302000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "030000006f0e00000702000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux", + "05000000ac0500003232000001000000,VR Box Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux", + "05000000434f4d4d414e440000000000,VX Gaming Command Series,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "0000000058626f782033363020576900,Xbox 360 Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux", + "030000005e0400001907000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000002010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000014010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000047010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400008e02000072050000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400009102000007010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000a102000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000a102000007010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000a102000030060000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000006f0e00001503000000020000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000a102000014010000,Xbox 360 Receiver,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "0000000058626f782047616d65706100,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux", + "030000005e0400000202000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux", + "030000006f0e00001304000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000ffff0000ffff000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux", + "030000005e0400000a0b000005040000,Xbox One Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux", + "030000005e040000d102000002010000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000ea02000001030000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "050000005e040000200b000013050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000200b000017050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000200b000023050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000220b000017050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "050000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000fd02000030110000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000dd02000003020000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "050000005e040000e302000002090000,Xbox One Elite,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "030000005e040000ea02000011050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000ea02000015050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000ea02000017050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000ea0200000b050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000ea0200000d050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000ea02000016050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000001050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000005050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000009050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000011050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000014050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000120b000015050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000007050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000011050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "050000005e040000130b000017050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "060000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "060000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "050000005e040000130b000022050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux", + "060000005e040000120b000011050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000450c00002043000010010000,XEOX SL6556 BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + "05000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux", + "03000000c0160000e105000001010000,XinMo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux", + "030000005e0400008e02000020010000,XInput Adapter,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux", + "03000000120c0000100e000011010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000120c0000101e000011010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000120c0000182e000011010000,Zeroplus PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux", + "03000000790000002201000011010000,ZhiXu GuliKit D,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux", + ]; + Gamepad.addMappings(mappings); + #elseif android + var mappings = [ + "38653964633230666463343334313533,8BitDo Adapter,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "36666264316630653965636634386234,8BitDo Adapter 2,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "38426974446f20417263616465205374,8BitDo Arcade Stick,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b5,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "61393962646434393836356631636132,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android", + "64323139346131306233636562663738,8BitDo Arcade Stick,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android", + "64643565386136613265663236636564,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android", + "33313433353539306634656436353432,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "38426974446f20446f67626f6e65204d,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android", + "34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android", + "38426974446f204e4743204d6f646b69,8BitDo GameCube,a:b0,b:b2,back:b4,dpdown:b12,dpleft:b13,dpright:b14,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b18,paddle2:b17,rightshoulder:b15,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b1,y:b3,platform:Android", + "38426974446f2038426974446f204c69,8BitDo Lite,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "30643332373663313263316637356631,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974446f204c6974652032000000,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "62656331626461363634633735353032,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38393936616436383062666232653338,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974446f204c6974652053450000,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "39356430616562366466646636643435,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "05000000c82d000006500000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a5,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android", + "05000000c82d000051060000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,platform:Android", + "32323161363037623637326438643634,8BitDo M30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "33656266353630643966653238646264,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,start:b10,x:b19,y:b2,platform:Android", + "38426974446f204d3330204d6f646b69,8BitDo M30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "39366630663062373237616566353437,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,start:b6,x:b2,y:b3,platform:Android", + "64653533313537373934323436343563,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,start:b6,x:b2,y:b3,platform:Android", + "66356438346136366337386437653934,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,start:b18,x:b19,y:b2,platform:Android", + "66393064393162303732356665666366,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,platform:Android", + "38426974446f204d6963726f2067616d,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android", + "61653365323561356263373333643266,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android", + "62613137616239666338343866326336,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android", + "33663431326134333366393233616633,8BitDo N30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android", + "38426974446f204e3330204d6f646b69,8BitDo N30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android", + "05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "05000000c82d000065280000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38323035343766666239373834336637,8BitDo N64,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,platform:Android", + "38426974446f204e3634204d6f646b69,8BitDo N64,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,platform:Android", + "32363135613966656338666638666237,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "35363534633333373639386466346631,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "38426974446f204e454f47454f204750,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "39383963623932353561633733306334,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000000220000000900000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38313433643131656262306631373166,8BitDo P30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "38326536643339353865323063616339,8BitDo P30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "38426974446f2050333020636c617373,8BitDo P30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "35376664343164386333616535333434,8BitDo Pro 2,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,start:b10,x:b19,y:b2,platform:Android", + "38426974446f2038426974446f205072,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974446f2050726f203200000000,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "61333362366131643730353063616330,8BitDo Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "62373739366537363166326238653463,8BitDo Pro 2,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b3,y:b2,platform:Android", + "38386464613034326435626130396565,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974446f2038426974446f205265,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "66303230343038613365623964393766,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974446f20533330204d6f646b69,8BitDo S30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "66316462353561376330346462316137,8BitDo S30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974646f20534633302050726f00,8BitDo SF30 Pro,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b17,platform:Android", + "61623334636338643233383735326439,8BitDo SFC30,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b31,start:b5,x:b30,y:b2,platform:Android", + "05000000c82d000012900000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android", + "05000000c82d000062280000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android", + "38316230613931613964356666353839,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974446f20534e3330204d6f646b,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "65323563303231646531383162646335,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "35383531346263653330306238353131,8BitDo SN30 PP,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "05000000c82d000002600000ffff0f00,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "36653638656632326235346264663661,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android", + "38303232393133383836366330346462,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android", + "38346630346135363335366265656666,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38426974446f20534e33302050726f2b,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "536f6e7920436f6d707574657220456e,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "66306331643531333230306437353936,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "050000002028000009000000ffff3f00,8BitDo SNES30,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "050000003512000020ab000000780f00,8BitDo SNES30,a:b21,b:b20,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b24,y:b23,platform:Android", + "33666663316164653937326237613331,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android", + "38426974646f205a65726f2047616d65,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android", + "05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android", + "05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android", + "33663434393362303033616630346337,8BitDo Zero 2,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android", + "34656330626361666438323266633963,8BitDo Zero 2,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android", + "63396666386564393334393236386630,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android", + "63633435623263373466343461646430,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android", + "32333634613735616163326165323731,Amazon Luna Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android", + "4c696e757820342e31392e3137322077,Anbernic Handheld,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Android", + "417374726f2063697479206d696e6920,Astro City Mini,a:b23,b:b22,back:b29,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android", + "35643263313264386134376362363435,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,start:b6,platform:Android", + "32353831643566306563643065356239,Atari VCS Modern Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "4f64696e20436f6e74726f6c6c657200,AYN Odin,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b14,dpright:b13,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:+a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "32303165626138343962363666346165,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "38383337343564366131323064613561,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "34313430343161653665353737323365,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android", + "4875694a6961204a432d573031550000,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android", + "30363230653635633863366338623265,Evo VR,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,x:b2,y:b3,platform:Android", + "05000000b404000011240000dfff3f00,Flydigi Vader 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "34323662653333636330306631326233,Google Nexus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "35383633353935396534393230616564,Google Stadia Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "476f6f676c65204c4c43205374616469,Google Stadia Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "5374616469614e3848532d6532633400,Google Stadia Controller,a:b0,b:b1,back:b15,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "05000000d6020000e5890000dfff3f00,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android", + "05000000d6020000e5890000dfff3f80,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,platform:Android", + "66633030656131663837396562323935,Hori Battle,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android", + "35623466343433653739346434636330,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "484f524920434f2e2c4c54442e203130,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "484f524920434f2e2c4c544420205041,Hori Gem Pad 3,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android", + "65656436646661313232656661616130,Hori PC Engine Mini Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,start:b18,platform:Android", + "31303433326562636431653534636633,Hori Real Arcade Pro 3,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "32656664353964393561366362333636,Hori Switch Split Pad Pro,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android", + "30306539356238653637313730656134,Horipad Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android", + "48797065726b696e2050616400000000,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android", + "62333331353131353034386136626636,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android", + "31306635363562663834633739396333,Hyperkin N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android", + "5368616e57616e202020202048797065,Hyperkin N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android", + "0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b2,y:b3,platform:Android", + "5553422c322d6178697320382d627574,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b17,rightshoulder:b18,start:b10,x:b3,y:b2,platform:Android", + "64306137363261396266353433303531,InterAct GoPad,a:b24,b:b25,leftshoulder:b23,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,x:b21,y:b22,platform:Android", + "532e542e442e20496e74657261637420,InterAct HammerHead FX,a:b23,b:b24,back:b30,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,leftstick:b22,lefttrigger:b28,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b25,righttrigger:b29,rightx:a2,righty:a3,start:b31,x:b20,y:b21,platform:Android", + "65346535636333663931613264643164,Joy-Con,a:b21,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b23,y:b24,platform:Android", + "33346566643039343630376565326335,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android", + "35313531613435623366313835326238,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android", + "4a6f792d436f6e20284c290000000000,Joy-Con (L),a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android", + "38383665633039363066383334653465,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android", + "39363561613936303237333537383931,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android", + "39373064396565646338333134303131,Joy-Con (R),a:b1,b:b2,back:b5,leftstick:b8,leftx:a1~,lefty:a0,start:b6,x:b0,y:b3,platform:Android", + "4a6f792d436f6e202852290000000000,Joy-Con (R),a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android", + "39656136363638323036303865326464,JYS Aapter,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "63316564383539663166353034616434,JYS Adapter,a:b1,b:b3,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android", + "64623163333561643339623235373232,Logitech F310,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "35623364393661626231343866613337,Logitech F710,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "4c6f6769746563682047616d65706164,Logitech F710,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "64396331333230326333313330336533,Logitech F710,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "39653365373864633935383236363438,Logitech G Cloud,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "33373336396634316434323337666361,Logitech RumblePad 2,a:b22,b:b23,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b24,platform:Android", + "416d617a6f6e2047616d6520436f6e74,Luna Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android", + "4c756e612047616d6570616400000000,Luna Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "30363066623539323534363639323363,Magic NS,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "31353762393935386662336365626334,Magic NS,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "39623565346366623931666633323530,Magic NS,a:b1,b:b3,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android", + "6d6179666c617368206c696d69746564,Mayflash GameCube Adapter,a:b22,b:b21,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a5,righty:a2,start:b30,x:b23,y:b24,platform:Android", + "436f6e74726f6c6c6572000000000000,Mayflash N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android", + "65666330633838383061313633326461,Mayflash N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android", + "37316565396364386635383230353365,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android", + "4875694a696120205553422047616d65,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android", + "535a4d792d706f776572204c54442043,Mayflash Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b31,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android", + "30653962643666303631376438373532,Mayflash Wii DolphinBar,a:b23,b:b24,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b0,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android", + "39346131396233376535393665363161,Mayflash Wii U Pro Adapter,a:b22,b:b23,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,leftstick:b31,lefttrigger:b27,rightshoulder:b26,rightstick:b0,righttrigger:b28,rightx:a0,righty:a1,start:b30,x:b21,y:b24,platform:Android", + "31323564663862633234646330373138,Mega Drive,a:b23,b:b22,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android", + "37333564393261653735306132613061,Mega Drive,a:b21,b:b22,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android", + "64363363336633363736393038313464,Mega Drive,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,start:b9,x:b2,y:b3,platform:Android", + "33323763323132376537376266393366,Microsoft Dual Strike,a:b24,b:b23,back:b25,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b29,rightshoulder:b78,rightx:a0,righty:a1~,start:b26,x:b22,y:b21,platform:Android", + "30306461613834333439303734316539,Microsoft SideWinder Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b20,lefttrigger:b9,rightshoulder:b19,righttrigger:b10,start:b17,x:b2,y:b3,platform:Android", + "32386235353630393033393135613831,Microsoft Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "4d4f42415041442050726f2d48440000,Mobapad Chitu HD,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "4d4f435554452d303533582d4d35312d,Mocute 053X,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "33343361376163623438613466616531,Mocute M053,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "39306635663061636563316166303966,Mocute M053,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "7573622067616d657061642020202020,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Android", + "050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b17,y:b2,platform:Android", + "31316661666466633938376335383661,Nintendo Switch Pro Controller,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,start:b6,x:b3,y:b2,platform:Android", + "34323437396534643531326161633738,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "50726f20436f6e74726f6c6c65720000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b2,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b10,rightx:a2,righty:a3,start:b18,y:b3,platform:Android", + "36326533353166323965623661303933,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android", + "4e363420436f6e74726f6c6c65720000,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android", + "534e455320436f6e74726f6c6c657200,NSO SNES Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android", + "64623863346133633561626136366634,NSO SNES Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android", + "050000005509000003720000cf7f3f00,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005509000010720000ffff3f00,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005509000014720000df7f3f00,NVIDIA Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android", + "050000005509000014720000df7f3f80,NVIDIA Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,platform:Android", + "37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "39383335313438623439373538343266,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b16,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,x:b1,y:b19,platform:Android", + "4f5559412047616d6520436f6e74726f,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b6,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b19,platform:Android", + "506572666f726d616e63652044657369,PDP PS3 Rock Candy Controller,a:b1,b:b17,back:h0.2,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android", + "61653962353232366130326530363061,Pokken,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,rightshoulder:b20,righttrigger:b10,start:b18,x:b0,y:b2,platform:Android", + "32666633663735353234363064386132,PS2 Controller,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a3,righty:a2,start:b30,x:b24,y:b21,platform:Android", + "050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "536f6e7920504c415953544154494f4e,PS3 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "61363034663839376638653463633865,PS3 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "66366539656564653432353139356536,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "66383132326164626636313737373037,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000004c050000c405000000783f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000004c050000c4050000fffe3f00,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android", + "050000004c050000c4050000fffe3f80,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a3,rightx:a4,righty:a5,start:b16,x:b0,y:b2,platform:Android", + "050000004c050000c4050000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000004c050000cc090000fffe3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000004c050000cc090000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "30303839663330346632363232623138,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android", + "31326235383662333266633463653332,PS4 Controller,a:b1,b:b16,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b17,x:b0,y:b2,platform:Android", + "31373231336561636235613666323035,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "31663838336334393132303338353963,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "34613139376634626133336530386430,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android", + "37626233336235343937333961353732,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "37626464343430636562316661643863,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "38393161636261653636653532386639,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "63313733393535663339656564343962,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "63393662363836383439353064663939,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "65366465656364636137653363376531,PS4 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "66613532303965383534396638613230,PS4 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android", + "050000004c050000e60c0000fffe3f00,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android", + "050000004c050000e60c0000fffe3f80,PS5 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a3,rightx:a4,righty:a5,start:b16,x:b2,y:b17,platform:Android", + "050000004c050000e60c0000ffff3f00,PS5 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "32346465346533616263386539323932,PS5 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "32633532643734376632656664383733,PS5 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android", + "37363764353731323963323639666565,PS5 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android", + "61303162353165316365336436343139,PS5 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android", + "64336263393933626535303339616332,Qanba 4RAF,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android", + "36626666353861663864336130363137,Razer Junglecat,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "05000000f8270000bf0b0000ffff3f00,Razer Kishi,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "62653861643333663663383332396665,Razer Kishi,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000003215000005070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000003215000007070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000003215000000090000bf7f3f00,Razer Serval,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android", + "5a6869587520526574726f2042697420,Retro Bit Saturn Controller,a:b21,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b26,rightshoulder:b27,righttrigger:b28,start:b30,x:b23,y:b24,platform:Android", + "32417865732031314b6579732047616d,Retro Bit SNES Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android", + "36313938306539326233393732613361,Retro Bit SNES Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android", + "526574726f466c616720576972656420,Retro Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b17,rightshoulder:b18,start:b10,x:b2,y:b3,platform:Android", + "61343739353764363165343237303336,Retro Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b17,lefttrigger:b18,leftx:a0,lefty:a1,start:b10,x:b2,y:b3,platform:Android", + "526574726f696420506f636b65742043,Retroid Pocket,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "582d426f7820436f6e74726f6c6c6572,Retroid Pocket,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "64633735616665613536653363336132,Retroid Pocket,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b19,paddle2:b20,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38653130373365613538333235303036,Retroid Pocket 2,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "64363363336633363736393038313463,Retrolink,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,start:b6,platform:Android", + "37393234373533633333323633646531,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android", + "5365616c6965436f6d707574696e6720,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android", + "526574726f5553422e636f6d20534e45,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android", + "64643037633038386238303966376137,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android", + "37656564346533643138636436356230,Rock Candy Switch Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android", + "36363537303435333566386638366333,Samsung EIGP20,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "53616d73756e672047616d6520506164,Samsung EIGP20,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "66386565396238363534313863353065,Sanwa PlayOnline Mobile,a:b21,b:b22,back:b23,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b24,platform:Android", + "32383165316333383766336338373261,Saturn,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android", + "38613865396530353338373763623431,Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b10,rightshoulder:b20,righttrigger:b19,start:b17,x:b2,y:b3,platform:Android", + "61316232336262373631343137633631,Saturn,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android", + "30353835333338613130373363646337,SG H510,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android", + "66386262366536653765333235343634,SG H510,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android", + "66633132393363353531373465633064,SG H510,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android", + "62653761636366393366613135366338,SN30 PP,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android", + "38376662666661636265313264613039,SNES,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android", + "5346432f555342205061640000000000,SNES Adapter,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android", + "5553422047616d657061642000000000,SNES Controller,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android", + "62653335326261303663356263626339,Sony PlayStation Classic Controller,a:b19,b:b1,back:b17,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b3,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android", + "536f6e7920496e746572616374697665,Sony PlayStation Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "576972656c65737320436f6e74726f6c,Sony PlayStation Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "63303964303462366136616266653561,Sony PSP,a:b21,b:b22,back:b27,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b23,y:b24,platform:Android", + "63376637643462343766333462383235,Sony Vita,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,platform:Android", + "0500000011010000201400000f7e0f00,SteelSeries Nimbus,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,x:b19,y:b2,platform:Android", + "35306436396437373135383665646464,SteelSeries Nimbus Plus,a:b0,b:b1,leftshoulder:b3,leftstick:b17,lefttrigger:b9,leftx:a0,rightshoulder:b20,rightstick:b18,righttrigger:b10,rightx:a2,x:b19,y:b2,platform:Android", + "33313930373536613937326534303931,Taito Egret II Mini Control Panel,a:b25,b:b23,back:b27,guide:b30,leftx:a0,lefty:a1,rightshoulder:b21,righttrigger:b22,start:b28,x:b29,y:b24,platform:Android", + "54475a20436f6e74726f6c6c65720000,TGZ Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "62363434353532386238336663643836,TGZ Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "37323236633763666465316365313236,THEC64 Joystick,a:b21,b:b22,back:b27,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b27,x:b23,y:b24,platform:Android", + "38346162326232346533316164363336,THEGamepad,a:b23,b:b22,back:b27,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b24,y:b21,platform:Android", + "050000004f0400000ed00000fffe3f00,Thrustmaster eSwap Pro Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "5477696e20555342204a6f7973746963,Twin Joystick,a:b22,b:b21,back:b28,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android", + "05000000de2800000511000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android", + "05000000de2800000611000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android", + "30623739343039643830333266346439,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "31643365666432386133346639383937,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "30386438313564306161393537333663,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android", + "33333034646336346339646538643633,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android", + "050000005e0400008e02000000783f00,Xbox 360 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "30396232393162346330326334636566,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "38313038323730383864666463383533,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "58626f782033363020576972656c6573,Xbox 360 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "65353331386662343338643939643636,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "65613532386633373963616462363038,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "47656e6572696320582d426f78207061,Xbox Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "4d6963726f736f667420582d426f7820,Xbox Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "64633436313965656664373634323364,Xbox Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e04000091020000ff073f00,Xbox One Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android", + "050000005e04000091020000ff073f80,Xbox One Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000e00200000ffe3f00,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android", + "050000005e040000e00200000ffe3f80,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a2,righty:a3,start:b10,x:b17,y:b2,platform:Android", + "050000005e040000e0020000ffff3f00,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b4,leftshoulder:b3,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android", + "050000005e040000e0020000ffff3f80,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b4,leftshoulder:b3,leftstick:b8,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b7,righttrigger:a5,rightx:a2,righty:a3,start:b10,x:b17,y:b2,platform:Android", + "050000005e040000fd020000ffff3f00,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "33356661323266333733373865656366,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "34356136633366613530316338376136,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android", + "35623965373264386238353433656138,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "36616131643361333337396261666433,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "58626f7820576972656c65737320436f,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "65316262316265373335666131623538,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000000b000000783f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000000b000000783f80,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000050b0000ffff3f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000e002000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000ea02000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000fd020000ff7f3f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000120b000000783f00,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000120b000000783f80,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000005e040000130b0000ffff3f00,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "65633038363832353634653836396239,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android", + "050000001727000044310000ffff3f00,XiaoMi Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android", ]; Gamepad.addMappings(mappings); #elseif (ios || tvos) var mappings = [ + "05000000ac0500000100000000006d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,", + "05000000ac050000010000004f066d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,", + "05000000ac05000001000000cf076d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,", + "05000000ac05000001000000df076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", + "05000000ac05000001000000ff076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", + "05000000ac0500000200000000006d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,", + "05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,", + "05000000ac05000004000000a8986d04,8BitDo Micro,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,lefttrigger:b12,rightshoulder:b13,righttrigger:b14,start:b3,x:b6,y:b5,", + "05000000ac05000004000000fd216d04,8BitDo Pro 2,a:b3,b:b2,back:b6,dpdown:b9,dpleft:b10,dpright:b11,dpup:b12,guide:b4,leftshoulder:b13,leftstick:b14,lefttrigger:+a2,leftx:a0,lefty:a1~,paddle1:b1,paddle2:b0,rightshoulder:b16,rightstick:b17,righttrigger:+a5,rightx:a3,righty:a4~,start:b5,x:b8,y:b7,", + "05000000ac05000004000000209f6d04,8Bitdo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,leftstick:b12,lefttrigger:b13,leftx:a0,lefty:a1~,rightshoulder:b14,rightstick:b15,righttrigger:b16,rightx:a2,righty:a3~,start:b3,x:b6,y:b5,", + "05000000ac050000040000003b8a6d04,8BitDo SN30 Pro+,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,leftstick:b12,lefttrigger:b13,leftx:a0,lefty:a1~,rightshoulder:b14,rightstick:b15,righttrigger:b16,rightx:a2,righty:a3~,start:b3,x:b6,y:b5,", + "050000008a35000003010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", + "050000008a35000004010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", "4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,", "4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,", + "050000007e050000062000000f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,", + "050000007e050000062000004f060000,Nintendo Switch Joy-Con (L),+leftx:h0.1,+lefty:h0.2,-leftx:h0.4,-lefty:h0.8,dpdown:b2,dpleft:b0,dpright:b3,dpup:b1,leftshoulder:b4,misc1:b6,rightshoulder:b5,", + "050000007e05000008200000df070000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,", + "050000007e0500000e200000df070000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,", + "050000007e050000072000000f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,", + "050000007e050000072000004f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,", + "050000007e05000009200000df870000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,", + "050000007e05000009200000ff870000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,", + "05000000ac050000040000008e586d04,PlayStation VR2 Sense Controller (L),+leftx:+a3,+lefty:+a1,-leftx:+a2,-lefty:+a4,back:b2,leftstick:b4,lefttrigger:+a7,paddle2:b3,x:b0,y:b1,", + "05000000ac050000040000000eb86d04,PlayStation VR2 Sense Controller (R),+rightx:+a3,+righty:+a1,-rightx:+a2,-righty:+a4,a:b0,b:b1,paddle1:b3,rightstick:b4,righttrigger:+a7,start:b2,", + "050000004c050000cc090000df070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", + "050000004c050000cc090000df870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", + "050000004c050000cc090000ff070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", + "050000004c050000cc090000ff870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,", + "050000004c050000cc090000ff876d01,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", + "050000004c050000e60c0000df870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,touchpad:b10,x:b2,y:b3,", + "050000004c050000e60c0000ff870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,", + "05000000ac0500000300000000006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,", + "05000000ac0500000300000043006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,", + "05000000de2800000511000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,", + "05000000de2800000611000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,", + "050000005e040000050b0000df070001,Xbox Elite Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b10,paddle2:b12,paddle3:b11,paddle4:b13,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", + "050000005e040000050b0000ff070001,Xbox Elite Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", + "050000005e040000e0020000df070000,Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", + "050000005e040000e0020000ff070000,Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", + "050000005e040000130b0000df870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", + "050000005e040000130b0000ff870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", "4d466947616d65706164030000000000,MFi Apple TV Remote,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,", ]; diff --git a/src/lime/ui/WindowAttributes.hx b/src/lime/ui/WindowAttributes.hx index 5568cd6448..96d5fbe6e7 100644 --- a/src/lime/ui/WindowAttributes.hx +++ b/src/lime/ui/WindowAttributes.hx @@ -32,6 +32,7 @@ typedef WindowAttributes = shared application frame profile. **/ @:optional public var frameProfile:FrameProfile; + @:optional public var fullscreen:Bool; @:optional public var height:Int; @:optional public var hidden:Bool; @@ -40,6 +41,7 @@ typedef WindowAttributes = @:optional public var parameters:Dynamic; @:optional public var resizable:Bool; @:optional public var skipTaskbar:Bool; + @:optional public var transparent:Bool; @:optional public var utility:Bool; @:optional public var popupMenu:Bool; @:optional public var tooltip:Bool; diff --git a/src/lime/utils/ArrayBufferView.hx b/src/lime/utils/ArrayBufferView.hx index 8b25a82c79..aa429a1277 100644 --- a/src/lime/utils/ArrayBufferView.hx +++ b/src/lime/utils/ArrayBufferView.hx @@ -46,6 +46,7 @@ class ArrayBufferView } // new // Constructor helpers + @:allow(lime.utils) #if !no_typedarray_inline inline @@ -138,7 +139,8 @@ class ArrayBufferView { if (view != null && array == null) { - if (offset + view.length > this.length) { + if (offset + view.length > this.length) + { throw TAError.RangeError; } if (bytesPerElement == view.bytesPerElement) @@ -296,12 +298,13 @@ class ArrayBufferView // Non-spec #if !no_typedarray_inline #end - function copyFromArray(array:Array<#if hl Dynamic #else Float #end>, offset:Int = 0) + function copyFromArray(array:Array< #if hl Dynamic #else Float #end>, offset:Int = 0) { // Ideally, native semantics could be used, like cpp.NativeArray.blit var i = 0, len = array.length; - if (offset + len > this.length) { + if (offset + len > this.length) + { throw TAError.RangeError; } @@ -471,7 +474,6 @@ class ArrayBufferView throw "transferElement on a base type ArrayBuffer"; } } - } // ArrayBufferView #end // !js diff --git a/src/lime/utils/AssetLibrary.hx b/src/lime/utils/AssetLibrary.hx index 146d9a7191..ea3c287098 100644 --- a/src/lime/utils/AssetLibrary.hx +++ b/src/lime/utils/AssetLibrary.hx @@ -381,8 +381,11 @@ class AssetLibrary return switch (cast(type, AssetType)) { case null: - cachedBytes.exists(id) || cachedText.exists(id) || cachedImages.exists(id) - || cachedAudioBuffers.exists(id) || cachedFonts.exists(id); + cachedBytes.exists(id) + || cachedText.exists(id) + || cachedImages.exists(id) + || cachedAudioBuffers.exists(id) + || cachedFonts.exists(id); case IMAGE: cachedImages.exists(id); @@ -393,8 +396,7 @@ class AssetLibrary case FONT: cachedFonts.exists(id); - default: - cachedBytes.exists(id) || cachedText.exists(id); + default: cachedBytes.exists(id) || cachedText.exists(id); } #end } diff --git a/src/lime/utils/Assets.hx b/src/lime/utils/Assets.hx index 2f43d1327f..8ddeceb16b 100644 --- a/src/lime/utils/Assets.hx +++ b/src/lime/utils/Assets.hx @@ -15,8 +15,8 @@ import lime.utils.Log; #if !macro import haxe.Json; #end -@:access(lime.media.AudioBuffer) +@:access(lime.media.AudioBuffer) /** *

The Assets class provides a cross-platform interface to access * embedded images, fonts, sounds and other resource files.

diff --git a/src/lime/utils/ObjectPool.hx b/src/lime/utils/ObjectPool.hx index a023128f02..0b10868c89 100644 --- a/src/lime/utils/ObjectPool.hx +++ b/src/lime/utils/ObjectPool.hx @@ -2,10 +2,9 @@ package lime.utils; import haxe.ds.ObjectMap; - /** - A generic object pool for reusing objects. - **/ + A generic object pool for reusing objects. +**/ #if !lime_debug @:fileXml('tags="haxe,release"') @:noDebug @@ -13,18 +12,18 @@ import haxe.ds.ObjectMap; #if !js @:generic #end class ObjectPool { /** - The number of active objects in the pool. - **/ + The number of active objects in the pool. + **/ public var activeObjects(default, null):Int; /** - The number of inactive objects in the pool. - **/ + The number of inactive objects in the pool. + **/ public var inactiveObjects(default, null):Int; /** - The total size of the object pool (both active and inactive objects). - **/ + The total size of the object pool (both active and inactive objects). + **/ public var size(get, set):Null; @:noCompletion private var __inactiveObject0:T; @@ -34,12 +33,12 @@ import haxe.ds.ObjectMap; @:noCompletion private var __size:Null; /** - Creates a new ObjectPool instance. - - @param create A function that creates a new instance of type T. - @param clean A function that cleans up an instance of type T before it is reused. - @param size The maximum size of the object pool. - **/ + Creates a new ObjectPool instance. + + @param create A function that creates a new instance of type T. + @param clean A function that cleans up an instance of type T before it is reused. + @param size The maximum size of the object pool. + **/ public function new(create:Void->T = null, clean:T->Void = null, size:Null = null) { __pool = cast new ObjectMap(); @@ -64,11 +63,12 @@ import haxe.ds.ObjectMap; this.size = size; } } + /** - Adds an object to the object pool. - - @param object The object to add to the pool. - **/ + Adds an object to the object pool. + + @param object The object to add to the pool. + **/ public function add(object:T):Void { if (object != null && !__pool.exists(object)) @@ -82,15 +82,15 @@ import haxe.ds.ObjectMap; /** Dynamic function. - Cleans up an object before returning it to the pool. - - @param object The object to clean up. - **/ + Cleans up an object before returning it to the pool. + + @param object The object to clean up. + **/ public dynamic function clean(object:T):Void {} /** - Clears the object pool, removing all objects. - **/ + Clears the object pool, removing all objects. + **/ public function clear():Void { __pool = cast new ObjectMap(); @@ -106,18 +106,18 @@ import haxe.ds.ObjectMap; /** Dynamic function. - Creates a new Object. - **/ + Creates a new Object. + **/ public dynamic function create():T { return null; } /** - Creates a new object and adds it to the pool, or returns an existing inactive object from the pool. - - @return The object retrieved from the pool, or null if the pool is full and no new objects can be created. - **/ + Creates a new object and adds it to the pool, or returns an existing inactive object from the pool. + + @return The object retrieved from the pool, or null if the pool is full and no new objects can be created. + **/ public function get():T { var object = null; @@ -141,10 +141,10 @@ import haxe.ds.ObjectMap; } /** - Releases an active object back into the pool. - - @param object The object to release. - **/ + Releases an active object back into the pool. + + @param object The object to release. + **/ public function release(object:T):Void { #if debug @@ -172,10 +172,10 @@ import haxe.ds.ObjectMap; } /** - Removes an object from the pool. - - @param object The object to remove from the pool. - **/ + Removes an object from the pool. + + @param object The object to remove from the pool. + **/ public function remove(object:T):Void { if (object != null && __pool.exists(object)) diff --git a/src/lime/utils/PackedAssetLibrary.hx b/src/lime/utils/PackedAssetLibrary.hx index 5a7a98f10a..42021c954d 100644 --- a/src/lime/utils/PackedAssetLibrary.hx +++ b/src/lime/utils/PackedAssetLibrary.hx @@ -174,7 +174,7 @@ import flash.media.Sound; // TODO: Do not preload bytes on native, if we can read from it instead (all non-Android targets?) assetsLoaded = 0; - assetsTotal = 2; //for our initial __assetLoaded(null) call and __assetLoaded(this.id) + assetsTotal = 2; // for our initial __assetLoaded(null) call and __assetLoaded(this.id) for (id in preload.keys()) { @@ -252,7 +252,7 @@ import flash.media.Sound; } else { - var basePath = rootPath == null || rootPath == "" ? "" : Path.addTrailingSlash(rootPath); + var basePath = rootPath == null || rootPath == "" ? "" : Path.addTrailingSlash(rootPath); var libPath = getPath(id); if (libPath == null) libPath = id; @@ -261,7 +261,10 @@ import flash.media.Sound; var packedData_onProgress = load_onProgress.bind(this.id); - Bytes.loadFromFile(path).onProgress(packedData_onProgress).onError(promise.error).onComplete(packedData_onComplete); + Bytes.loadFromFile(path) + .onProgress(packedData_onProgress) + .onError(promise.error) + .onComplete(packedData_onComplete); } } @@ -431,9 +434,9 @@ import flash.media.Sound; var length = Reflect.field(asset, "length"); lengths.set(id, length); - //for individual packed assets, the size represents the work done unpacking them - //since this is likely to be much faster than downloading, set it to something - //small like the packed length / 10. + // for individual packed assets, the size represents the work done unpacking them + // since this is likely to be much faster than downloading, set it to something + // small like the packed length / 10. sizes.set(id, Math.floor(length / 10)); packedBytesTotal += length; @@ -444,7 +447,7 @@ import flash.media.Sound; bytesTotal += sizes.get(id); } } - + sizes.set(this.id, packedBytesTotal); bytesTotal += packedBytesTotal; } diff --git a/src/lime/utils/Preloader.hx b/src/lime/utils/Preloader.hx index d9f309aeff..f74c35c25d 100644 --- a/src/lime/utils/Preloader.hx +++ b/src/lime/utils/Preloader.hx @@ -26,8 +26,7 @@ import flash.Lib; @:access(lime.utils.AssetLibrary) #if !lime_debug -@:fileXml('tags="haxe,release"') -@:noDebug +@:fileXml('tags="haxe,release"') @:noDebug #end class Preloader #if flash extends Sprite #end { @@ -36,12 +35,12 @@ class Preloader #if flash extends Sprite #end public var onProgress = new EventInt->Void>(); @:noCompletion private var bytesLoaded:Int; - @:noCompletion private var bytesLoadedCache = new ObjectMap<#if !disable_preloader_assets AssetLibrary #else Dynamic #end, Int>(); + @:noCompletion private var bytesLoadedCache = new ObjectMap< #if !disable_preloader_assets AssetLibrary #else Dynamic #end, Int>(); @:noCompletion private var bytesLoadedCache2 = new Map(); @:noCompletion private var bytesTotal:Int; @:noCompletion private var bytesTotalCache = new Map(); @:noCompletion private var initLibraryNames:Bool; - @:noCompletion private var libraries:Array<#if !disable_preloader_assets AssetLibrary #else Dynamic #end>; + @:noCompletion private var libraries:Array< #if !disable_preloader_assets AssetLibrary #else Dynamic #end>; @:noCompletion private var libraryNames:Array; @:noCompletion private var loadedLibraries:Int; @:noCompletion private var loadedStage:Bool; @@ -60,7 +59,7 @@ class Preloader #if flash extends Sprite #end bytesLoaded = 0; bytesTotal = 0; - libraries = new Array<#if !disable_preloader_assets AssetLibrary #else Dynamic #end>(); + libraries = new Array< #if !disable_preloader_assets AssetLibrary #else Dynamic #end>(); libraryNames = new Array(); onProgress.add(update); @@ -296,8 +295,7 @@ class Preloader #if flash extends Sprite #end } #end - if (!simulateProgress #if flash && loadedStage #end - && loadedLibraries == (libraries.length + libraryNames.length)) + if (!simulateProgress #if flash && loadedStage #end && loadedLibraries == (libraries.length + libraryNames.length)) { if (!preloadComplete) { diff --git a/templates/android/template/app/src/main/AndroidManifest.xml b/templates/android/template/app/src/main/AndroidManifest.xml index ed3640a1f5..c435998b5d 100644 --- a/templates/android/template/app/src/main/AndroidManifest.xml +++ b/templates/android/template/app/src/main/AndroidManifest.xml @@ -1,7 +1,11 @@ + ::if ANDROID_VULKAN:: + + ::else:: + ::end:: ::foreach ANDROID_PERMISSIONS:: diff --git a/templates/cpp/static/BuildMain.xml b/templates/cpp/static/BuildMain.xml index dd135172ce..33c486449b 100644 --- a/templates/cpp/static/BuildMain.xml +++ b/templates/cpp/static/BuildMain.xml @@ -17,6 +17,7 @@ + ::foreach ndlls:: diff --git a/templates/haxe/ApplicationMain.hx b/templates/haxe/ApplicationMain.hx index 422fbcb030..66c445d16f 100644 --- a/templates/haxe/ApplicationMain.hx +++ b/templates/haxe/ApplicationMain.hx @@ -49,6 +49,7 @@ import ::APP_MAIN::; parameters: ::parameters::, resizable: ::resizable::, title: "::title::", + transparent: ::transparent::, width: ::width::, x: ::x::, y: ::y::, @@ -62,7 +63,7 @@ import ::APP_MAIN::; depth: ::depthBuffer::, hardware: ::hardware::, stencil: ::stencilBuffer::, - type: null, + type: ::if renderType::"::renderType::"::else::null::end::, vsync: ::vsync:: }; diff --git a/templates/ios/template/{{app.file}}.xcodeproj/project.pbxproj b/templates/ios/template/{{app.file}}.xcodeproj/project.pbxproj index 001a200690..58b6be5022 100644 --- a/templates/ios/template/{{app.file}}.xcodeproj/project.pbxproj +++ b/templates/ios/template/{{app.file}}.xcodeproj/project.pbxproj @@ -214,6 +214,7 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { + BuildIndependentTargetsInParallel = YES; LastUpgradeCheck = 0920; TargetAttributes = { 1D6058900D05DD3D006BFB54 = { @@ -272,23 +273,39 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = ::CURRENT_ARCHS::; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ::if (OBJC_ARC):: CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ::end:: + CURRENT_PROJECT_VERSION = "::APP_BUILD_NUMBER::"; + INFOPLIST_KEY_CFBundleDisplayName = "::APP_TITLE::"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.games"; + MARKETING_VERSION = "::APP_VERSION::"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "::config.ios.identity::"; ::if (IOS_PROVISIONING_PROFILE)::PROVISIONING_PROFILE = "::IOS_PROVISIONING_PROFILE::";::end:: COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -306,6 +323,7 @@ IPHONEOS_DEPLOYMENT_TARGET = ::DEPLOYMENT::; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; TARGETED_DEVICE_FAMILY = "::TARGET_DEVICES::"; ::THUMB_SUPPORT:: VALID_ARCHS = "::VALID_ARCHS::"; @@ -317,23 +335,39 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = ::CURRENT_ARCHS::; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ::if (OBJC_ARC):: CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ::end:: + CURRENT_PROJECT_VERSION = "::APP_BUILD_NUMBER::"; + INFOPLIST_KEY_CFBundleDisplayName = "::APP_TITLE::"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.games"; + MARKETING_VERSION = "::APP_VERSION::"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "::config.ios.identity::"; ::if (IOS_PROVISIONING_PROFILE)::PROVISIONING_PROFILE = "::IOS_PROVISIONING_PROFILE::";::end:: /* COMPRESS_PNG_FILES = NO; */ COPY_PHASE_STRIP = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -346,6 +380,8 @@ OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; /* PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = YES; */ SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_COMPILATION_MODE = wholemodule; TARGETED_DEVICE_FAMILY = "::TARGET_DEVICES::"; ::THUMB_SUPPORT:: VALID_ARCHS = "::VALID_ARCHS::"; @@ -356,6 +392,7 @@ 1D6058940D05DD3E006BFB54 /* Debug */ = {/* Build configuration list for PBXNativeTarget "::APP_TITLE::" */ isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ::if (IOS_LAUNCH_STORYBOARD == null)::ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;::end:: CODE_SIGN_ENTITLEMENTS = "::APP_FILE::/::APP_FILE::.entitlements"; @@ -407,6 +444,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = "::APP_PACKAGE::"; PRODUCT_NAME = "$(TARGET_NAME)"; + INFOPLIST_KEY_CFBundleDisplayName = "::APP_TITLE::"; WRAPPER_EXTENSION = app; }; name = Debug; @@ -460,6 +498,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = "::APP_PACKAGE::"; PRODUCT_NAME = "$(TARGET_NAME)"; + INFOPLIST_KEY_CFBundleDisplayName = "::APP_TITLE::"; WRAPPER_EXTENSION = app; }; name = Release; diff --git a/templates/windows/resource/ApplicationMain.rc b/templates/windows/resource/ApplicationMain.rc index 2d12ca8ef6..2b36d4781f 100644 --- a/templates/windows/resource/ApplicationMain.rc +++ b/templates/windows/resource/ApplicationMain.rc @@ -1,5 +1,7 @@ #include "winres.h" +::if (HAS_ICON)::IDI_ICON1 ICON "ApplicationMain.ico"::end:: + LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK VS_VERSION_INFO VERSIONINFO diff --git a/tests/unit/src/TestMain.hx b/tests/unit/src/TestMain.hx index 6978eb8d6c..dae8fda9c3 100644 --- a/tests/unit/src/TestMain.hx +++ b/tests/unit/src/TestMain.hx @@ -2,11 +2,14 @@ import utest.Runner; import utest.ui.Report; import lime.app.Application; -class TestMain extends Application { - public function new() { +class TestMain extends Application +{ + public function new() + { super(); var runner = new Runner(); + runner.addCase(new app.EventTest()); runner.addCase(new utils.ArrayBufferTest()); runner.addCase(new utils.UInt8ArrayTest()); runner.addCase(new utils.UInt16ArrayTest()); @@ -15,4 +18,4 @@ class TestMain extends Application { Report.create(runner); runner.run(); } -} \ No newline at end of file +} diff --git a/tests/unit/src/app/EventTest.hx b/tests/unit/src/app/EventTest.hx new file mode 100644 index 0000000000..87d7c07f0c --- /dev/null +++ b/tests/unit/src/app/EventTest.hx @@ -0,0 +1,68 @@ +package app; + +import lime.app.Event; +import lime.system.System; +import utest.Assert; +import utest.Test; + +class EventTest extends Test +{ + public function new() + { + super(); + } + + public function testTimestampUsesDispatchTime():Void + { + var event = new EventVoid>(); + var observed = -1; + var before = System.getTimer(); + + event.add(function(_) + { + observed = event.timestamp; + }); + + event.dispatch(1); + var after = System.getTimer(); + + Assert.isTrue(observed >= before); + Assert.isTrue(observed <= after); + } + + public function testExplicitTimestampIsVisible():Void + { + var event = new EventVoid>(); + var observed = -1; + + event.add(function(_) + { + observed = event.timestamp; + }); + + @:privateAccess event.__dispatchWithTimestamp(1234, 1); + Assert.equals(1234, observed); + } + + public function testNestedDispatchRestoresTimestamp():Void + { + var event = new EventVoid>(); + var timestamps:Array = []; + var nested = false; + + event.add(function(_) + { + timestamps.push(event.timestamp); + + if (!nested) + { + nested = true; + @:privateAccess event.__dispatchWithTimestamp(200, 2); + Assert.equals(100, event.timestamp); + } + }); + + @:privateAccess event.__dispatchWithTimestamp(100, 1); + Assert.same([100, 200], timestamps); + } +} diff --git a/tests/unit/src/utils/ArrayBufferTest.hx b/tests/unit/src/utils/ArrayBufferTest.hx index 32dda5e2cf..8981b1b080 100644 --- a/tests/unit/src/utils/ArrayBufferTest.hx +++ b/tests/unit/src/utils/ArrayBufferTest.hx @@ -6,17 +6,21 @@ import lime.utils.ArrayBuffer; import utest.Assert; import utest.Test; -class ArrayBufferTest extends Test { - public function new() { +class ArrayBufferTest extends Test +{ + public function new() + { super(); } - public function testByteLength():Void { + public function testByteLength():Void + { var buffer = new ArrayBuffer(4); Assert.equals(4, buffer.byteLength); } - public function testSubarray():Void { + public function testSubarray():Void + { var buffer = new ArrayBuffer(4); var array = new UInt8Array(buffer); array[0] = 0xca; @@ -66,4 +70,4 @@ class ArrayBufferTest extends Test { Assert.equals(0xba, beyondLengthArray[2]); Assert.equals(0xbe, beyondLengthArray[3]); } -} \ No newline at end of file +} diff --git a/tests/unit/src/utils/DataViewTest.hx b/tests/unit/src/utils/DataViewTest.hx index 3fb397dfa2..ad2fcfa8bb 100644 --- a/tests/unit/src/utils/DataViewTest.hx +++ b/tests/unit/src/utils/DataViewTest.hx @@ -6,62 +6,61 @@ import lime.utils.ArrayBuffer; import utest.Assert; import utest.Test; -class DataViewTest extends Test { - public function new() { +class DataViewTest extends Test +{ + public function new() + { super(); } - public function testInt8():Void { - var values:Array = [0, 1, 2, 127, 128, 255, -1, -2, -128, -129]; - var result:Array = [0, 1, 2, 127, -128, -1, -1, -2, -128, 127]; + public function testInt8():Void + { + var values:Array = [0, 1, 2, 127, 128, 255, -1, -2, -128, -129]; + var result:Array = [0, 1, 2, 127, -128, -1, -1, -2, -128, 127]; Assert.equals(values.length, result.length); var count = values.length; var buffer = new ArrayBuffer(count); var dataView = new DataView(buffer); - for (i in 0...count) { + for (i in 0...count) + { var value = values[i]; dataView.setInt8(i, value); } - for (i in 0...count) { + for (i in 0...count) + { var value = dataView.getInt8(i); var expected = result[i]; Assert.equals(expected, value, 'Int8: expected $expected but got $value at index $i'); } } - public function testUint8():Void { - var values:Array = [0, 1, 2, 255, 256, -1, -2, -255]; - var result:Array = [0, 1, 2, 255, 0, 255, 254, 1]; + public function testUint8():Void + { + var values:Array = [0, 1, 2, 255, 256, -1, -2, -255]; + var result:Array = [0, 1, 2, 255, 0, 255, 254, 1]; Assert.equals(values.length, result.length); var count = values.length; var buffer = new ArrayBuffer(count); var dataView = new DataView(buffer); - for (i in 0...count) { + for (i in 0...count) + { var value = values[i]; dataView.setUint8(i, value); } - for (i in 0...count) { + for (i in 0...count) + { var value = dataView.getUint8(i); var expected = result[i]; Assert.equals(expected, value, 'Uint8: expected $expected but got $value at index $i'); } } - public function testInt16():Void { - var values:Array = [0, 1, 2, 32767, 32768, 65535, -1, -2, -32768, -32769]; - var result:Array = [0, 1, 2, 32767, -32768, -1, -1, -2, -32768, 32767]; + public function testInt16():Void + { + var values:Array = [0, 1, 2, 32767, 32768, 65535, -1, -2, -32768, -32769]; + var result:Array = [0, 1, 2, 32767, -32768, -1, -1, -2, -32768, 32767]; var resultBytesLE:Array> = [ - [0x00, 0x00], - [0x01, 0x00], - [0x02, 0x00], - [0xff, 0x7f], - [0x00, 0x80], - [0xff, 0xff], - [0xff, 0xff], - [0xfe, 0xff], - [0x00, 0x80], - [0xff, 0x7f] - ]; + [0x00, 0x00], [0x01, 0x00], [0x02, 0x00], [0xff, 0x7f], [0x00, 0x80], [0xff, 0xff], [0xff, 0xff], [0xfe, 0xff], [0x00, 0x80], [0xff, 0x7f]]; Assert.equals(values.length, result.length); Assert.equals(values.length, resultBytesLE.length); var count = values.length; @@ -69,52 +68,55 @@ class DataViewTest extends Test { var dataView = new DataView(buffer); // little endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = values[i]; dataView.setInt16(byteIndex, value); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = dataView.getInt16(byteIndex); var expected = result[i]; Assert.equals(expected, value, 'Int16 little endian: expected $expected but got $value at index $i'); - var valueBytes = [ - dataView.getUint8(byteIndex), - dataView.getUint8(byteIndex + 1) - ]; + var valueBytes = [dataView.getUint8(byteIndex), dataView.getUint8(byteIndex + 1)]; var expectedBytesLE = resultBytesLE[i]; Assert.equals(2, expectedBytesLE.length); - Assert.equals(expectedBytesLE[0], valueBytes[0], 'Int16 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesLE[1], valueBytes[1], 'Int16 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesLE[0], valueBytes[0], + 'Int16 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesLE[1], valueBytes[1], + 'Int16 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); } // big endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = values[i]; dataView.setInt16(byteIndex, value, false); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = dataView.getInt16(byteIndex, false); var expected = result[i]; Assert.equals(expected, value, 'Int16 big endian: expected $expected but got $value at index $i'); - var valueBytes = [ - dataView.getUint8(byteIndex), - dataView.getUint8(byteIndex + 1) - ]; + var valueBytes = [dataView.getUint8(byteIndex), dataView.getUint8(byteIndex + 1)]; var expectedBytesBE = resultBytesLE[i].copy(); expectedBytesBE.reverse(); // big endian is little endian reversed Assert.equals(2, expectedBytesBE.length); - Assert.equals(expectedBytesBE[0], valueBytes[0], 'Int16 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesBE[1], valueBytes[1], 'Int16 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesBE[0], valueBytes[0], + 'Int16 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesBE[1], valueBytes[1], + 'Int16 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); } } - public function testUint16():Void { - var values:Array = [0, 1, 2, 65535, 65536, -1, -2, -65535]; - var result:Array = [0, 1, 2, 65535, 0, 65535, 65534, 1]; + public function testUint16():Void + { + var values:Array = [0, 1, 2, 65535, 65536, -1, -2, -65535]; + var result:Array = [0, 1, 2, 65535, 0, 65535, 65534, 1]; var resultBytesLE:Array> = [ [0x00, 0x00], [0x01, 0x00], @@ -132,50 +134,53 @@ class DataViewTest extends Test { var dataView = new DataView(buffer); // little endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = values[i]; dataView.setUint16(byteIndex, value); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = dataView.getUint16(byteIndex); var expected = result[i]; Assert.equals(expected, value, 'Uint16 little endian: expected $expected but got $value at index $i'); - var valueBytes = [ - dataView.getUint8(byteIndex), - dataView.getUint8(byteIndex + 1) - ]; + var valueBytes = [dataView.getUint8(byteIndex), dataView.getUint8(byteIndex + 1)]; var expectedBytesLE = resultBytesLE[i]; Assert.equals(2, expectedBytesLE.length); - Assert.equals(expectedBytesLE[0], valueBytes[0], 'Uint16 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesLE[1], valueBytes[1], 'Uint16 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesLE[0], valueBytes[0], + 'Uint16 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesLE[1], valueBytes[1], + 'Uint16 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); } // big endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = values[i]; dataView.setUint16(byteIndex, value, false); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 2; var value = dataView.getUint16(byteIndex, false); var expected = result[i]; Assert.equals(expected, value, 'Uint16 big endian: expected $expected but got $value at index $i'); - var valueBytes = [ - dataView.getUint8(byteIndex), - dataView.getUint8(byteIndex + 1) - ]; + var valueBytes = [dataView.getUint8(byteIndex), dataView.getUint8(byteIndex + 1)]; var expectedBytesBE = resultBytesLE[i].copy(); expectedBytesBE.reverse(); // big endian is little endian reversed Assert.equals(2, expectedBytesBE.length); - Assert.equals(expectedBytesBE[0], valueBytes[0], 'Uint16 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesBE[1], valueBytes[1], 'Uint16 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesBE[0], valueBytes[0], + 'Uint16 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesBE[1], valueBytes[1], + 'Uint16 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); } } - public function testInt32():Void { + public function testInt32():Void + { var values:Array = [0, 1, 2, 2147483647, -1, -2, -2147483648]; var result:Array = [0, 1, 2, 2147483647, -1, -2, -2147483648]; var resultBytesLE:Array> = [ @@ -194,12 +199,14 @@ class DataViewTest extends Test { var dataView = new DataView(buffer); // little endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var value = values[i]; dataView.setInt32(byteIndex, value); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var value = dataView.getInt32(byteIndex); var expected = result[i]; @@ -213,19 +220,25 @@ class DataViewTest extends Test { ]; var expectedBytesLE = resultBytesLE[i]; Assert.equals(4, expectedBytesLE.length); - Assert.equals(expectedBytesLE[0], valueBytes[0], 'Int32 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesLE[1], valueBytes[1], 'Int32 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); - Assert.equals(expectedBytesLE[2], valueBytes[2], 'Int32 little endian: expected byte 2 to be ${StringTools.hex(expectedBytesLE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); - Assert.equals(expectedBytesLE[3], valueBytes[3], 'Int32 little endian: expected byte 3 to be ${StringTools.hex(expectedBytesLE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); + Assert.equals(expectedBytesLE[0], valueBytes[0], + 'Int32 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesLE[1], valueBytes[1], + 'Int32 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesLE[2], valueBytes[2], + 'Int32 little endian: expected byte 2 to be ${StringTools.hex(expectedBytesLE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); + Assert.equals(expectedBytesLE[3], valueBytes[3], + 'Int32 little endian: expected byte 3 to be ${StringTools.hex(expectedBytesLE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); } // big endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var value = values[i]; dataView.setInt32(byteIndex, value, false); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var value = dataView.getInt32(byteIndex, false); var expected = result[i]; @@ -240,14 +253,19 @@ class DataViewTest extends Test { var expectedBytesBE = resultBytesLE[i].copy(); expectedBytesBE.reverse(); // big endian is little endian reversed Assert.equals(4, expectedBytesBE.length); - Assert.equals(expectedBytesBE[0], valueBytes[0], 'Int32 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesBE[1], valueBytes[1], 'Int32 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); - Assert.equals(expectedBytesBE[2], valueBytes[2], 'Int32 big endian: expected byte 2 to be ${StringTools.hex(expectedBytesBE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); - Assert.equals(expectedBytesBE[3], valueBytes[3], 'Int32 big endian: expected byte 3 to be ${StringTools.hex(expectedBytesBE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); + Assert.equals(expectedBytesBE[0], valueBytes[0], + 'Int32 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesBE[1], valueBytes[1], + 'Int32 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesBE[2], valueBytes[2], + 'Int32 big endian: expected byte 2 to be ${StringTools.hex(expectedBytesBE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); + Assert.equals(expectedBytesBE[3], valueBytes[3], + 'Int32 big endian: expected byte 3 to be ${StringTools.hex(expectedBytesBE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); } } - public function testUint32():Void { + public function testUint32():Void + { var values:Array = [0, 1, 2, 0xffffffff, 0xdeadbeef, 0xcafebabe, 0xdecafbad]; var resultBytesLE:Array> = [ [0x00, 0x00, 0x00, 0x00], @@ -264,12 +282,14 @@ class DataViewTest extends Test { var dataView = new DataView(buffer); // little endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var value = values[i]; dataView.setUint32(byteIndex, value); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var valueBytes = [ dataView.getUint8(byteIndex), @@ -279,19 +299,25 @@ class DataViewTest extends Test { ]; var expectedBytesLE = resultBytesLE[i]; Assert.equals(4, expectedBytesLE.length); - Assert.equals(expectedBytesLE[0], valueBytes[0], 'Uint32 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesLE[1], valueBytes[1], 'Uint32 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); - Assert.equals(expectedBytesLE[2], valueBytes[2], 'Uint32 little endian: expected byte 2 to be ${StringTools.hex(expectedBytesLE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); - Assert.equals(expectedBytesLE[3], valueBytes[3], 'Uint32 little endian: expected byte 3 to be ${StringTools.hex(expectedBytesLE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); + Assert.equals(expectedBytesLE[0], valueBytes[0], + 'Uint32 little endian: expected byte 0 to be ${StringTools.hex(expectedBytesLE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesLE[1], valueBytes[1], + 'Uint32 little endian: expected byte 1 to be ${StringTools.hex(expectedBytesLE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesLE[2], valueBytes[2], + 'Uint32 little endian: expected byte 2 to be ${StringTools.hex(expectedBytesLE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); + Assert.equals(expectedBytesLE[3], valueBytes[3], + 'Uint32 little endian: expected byte 3 to be ${StringTools.hex(expectedBytesLE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); } // big endian - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var value = values[i]; dataView.setUint32(byteIndex, value, false); } - for (i in 0...count) { + for (i in 0...count) + { var byteIndex = i * 4; var valueBytes = [ dataView.getUint8(byteIndex), @@ -302,10 +328,14 @@ class DataViewTest extends Test { var expectedBytesBE = resultBytesLE[i].copy(); expectedBytesBE.reverse(); // big endian is little endian reversed Assert.equals(4, expectedBytesBE.length); - Assert.equals(expectedBytesBE[0], valueBytes[0], 'Uint32 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); - Assert.equals(expectedBytesBE[1], valueBytes[1], 'Uint32 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); - Assert.equals(expectedBytesBE[2], valueBytes[2], 'Uint32 big endian: expected byte 2 to be ${StringTools.hex(expectedBytesBE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); - Assert.equals(expectedBytesBE[3], valueBytes[3], 'Uint32 big endian: expected byte 3 to be ${StringTools.hex(expectedBytesBE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); + Assert.equals(expectedBytesBE[0], valueBytes[0], + 'Uint32 big endian: expected byte 0 to be ${StringTools.hex(expectedBytesBE[0])} but got ${StringTools.hex(valueBytes[0])} at index $i'); + Assert.equals(expectedBytesBE[1], valueBytes[1], + 'Uint32 big endian: expected byte 1 to be ${StringTools.hex(expectedBytesBE[1])} but got ${StringTools.hex(valueBytes[1])} at index $i'); + Assert.equals(expectedBytesBE[2], valueBytes[2], + 'Uint32 big endian: expected byte 2 to be ${StringTools.hex(expectedBytesBE[2])} but got ${StringTools.hex(valueBytes[2])} at index $i'); + Assert.equals(expectedBytesBE[3], valueBytes[3], + 'Uint32 big endian: expected byte 3 to be ${StringTools.hex(expectedBytesBE[3])} but got ${StringTools.hex(valueBytes[3])} at index $i'); } } -} \ No newline at end of file +} diff --git a/tests/unit/src/utils/UInt16ArrayTest.hx b/tests/unit/src/utils/UInt16ArrayTest.hx index 84200f99f4..6f3d1ae8cf 100644 --- a/tests/unit/src/utils/UInt16ArrayTest.hx +++ b/tests/unit/src/utils/UInt16ArrayTest.hx @@ -7,19 +7,23 @@ import lime.utils.ArrayBuffer; import utest.Assert; import utest.Test; -class UInt16ArrayTest extends Test { - public function new() { +class UInt16ArrayTest extends Test +{ + public function new() + { super(); } - public function testByteLength():Void { + public function testByteLength():Void + { var buffer = new ArrayBuffer(8); var array = new UInt16Array(buffer); Assert.equals(4, array.length); Assert.equals(8, array.byteLength); } - public function testValues():Void { + public function testValues():Void + { var buffer = new ArrayBuffer(8); var array = new UInt16Array(buffer); Assert.equals(0x0, array[0]); @@ -36,7 +40,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0xfbad, array[3]); } - public function testSubarray():Void { + public function testSubarray():Void + { var buffer = new ArrayBuffer(8); var array = new UInt16Array(buffer); array[0] = 0xcafe; @@ -81,12 +86,13 @@ class UInt16ArrayTest extends Test { Assert.equals(0xfbad, beyondLength[3]); } - public function testSetArrayOfInts():Void { + public function testSetArrayOfInts():Void + { var array1:Array = [0xcafe, 0xbabe, 0xdeca, 0xfbad]; var buffer2 = new ArrayBuffer(16); var array2 = new UInt16Array(buffer2); - + array2.set(array1); Assert.equals(0xcafe, array2[0]); Assert.equals(0xbabe, array2[1]); @@ -97,7 +103,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -111,11 +118,13 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); Assert.equals(0x0, array2[0]); @@ -128,7 +137,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt8Array():Void { + public function testSetUInt8Array():Void + { var buffer1 = new ArrayBuffer(4); var array1 = new UInt8Array(buffer1); array1[0] = 0xca; @@ -150,7 +160,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -164,12 +175,14 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -183,7 +196,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt16Array():Void { + public function testSetUInt16Array():Void + { var buffer1 = new ArrayBuffer(8); var array1 = new UInt16Array(buffer1); array1[0] = 0xcafe; @@ -205,7 +219,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -219,12 +234,14 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -238,7 +255,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt32Array():Void { + public function testSetUInt32Array():Void + { var buffer1 = new ArrayBuffer(16); var array1 = new UInt32Array(buffer1); array1[0] = 0xcafebabe; @@ -260,7 +278,8 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -274,12 +293,14 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -292,4 +313,4 @@ class UInt16ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); } -} \ No newline at end of file +} diff --git a/tests/unit/src/utils/UInt32ArrayTest.hx b/tests/unit/src/utils/UInt32ArrayTest.hx index 5e3c88a42a..882ff52efb 100644 --- a/tests/unit/src/utils/UInt32ArrayTest.hx +++ b/tests/unit/src/utils/UInt32ArrayTest.hx @@ -7,19 +7,23 @@ import lime.utils.ArrayBuffer; import utest.Assert; import utest.Test; -class UInt32ArrayTest extends Test { - public function new() { +class UInt32ArrayTest extends Test +{ + public function new() + { super(); } - public function testByteLength():Void { + public function testByteLength():Void + { var buffer = new ArrayBuffer(16); var array = new UInt32Array(buffer); Assert.equals(4, array.length); Assert.equals(16, array.byteLength); } - public function testValues():Void { + public function testValues():Void + { var buffer = new ArrayBuffer(16); var array = new UInt32Array(buffer); Assert.equals(0x0, array[0]); @@ -44,7 +48,8 @@ class UInt32ArrayTest extends Test { #end } - public function testSubarray():Void { + public function testSubarray():Void + { var buffer = new ArrayBuffer(16); var array = new UInt32Array(buffer); array[0] = 0xcafebabe; @@ -113,12 +118,13 @@ class UInt32ArrayTest extends Test { #end } - public function testSetArrayOfInts():Void { + public function testSetArrayOfInts():Void + { var array1:Array = [0xcafebabe, 0xdecafbad, 0xffffffff, 0xdeadbeef]; var buffer2 = new ArrayBuffer(32); var array2 = new UInt32Array(buffer2); - + array2.set(array1); #if js Assert.equals(untyped #if haxe4 js.Syntax.code #else __js__ #end ('0xcafebabe'), array2[0]); @@ -136,7 +142,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -165,7 +172,8 @@ class UInt32ArrayTest extends Test { var buffer2 = new ArrayBuffer(32); var array2 = new UInt32Array(buffer2); - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); Assert.equals(0x0, array2[0]); @@ -178,7 +186,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt8Array():Void { + public function testSetUInt8Array():Void + { var buffer1 = new ArrayBuffer(4); var array1 = new UInt8Array(buffer1); array1[0] = 0xca; @@ -200,7 +209,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -215,7 +225,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt8ArrayRangeError():Void { + public function testSetUInt8ArrayRangeError():Void + { var buffer1 = new ArrayBuffer(4); var array1 = new UInt8Array(buffer1); array1[0] = 0xca; @@ -227,7 +238,8 @@ class UInt32ArrayTest extends Test { var array2 = new UInt32Array(buffer2); // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -241,7 +253,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt16Array():Void { + public function testSetUInt16Array():Void + { var buffer1 = new ArrayBuffer(8); var array1 = new UInt16Array(buffer1); array1[0] = 0xcafe; @@ -263,7 +276,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -278,7 +292,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt16ArrayRangeError():Void { + public function testSetUInt16ArrayRangeError():Void + { var buffer1 = new ArrayBuffer(8); var array1 = new UInt16Array(buffer1); array1[0] = 0xcafe; @@ -290,7 +305,8 @@ class UInt32ArrayTest extends Test { var array2 = new UInt32Array(buffer2); // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -304,7 +320,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt32Array():Void { + public function testSetUInt32Array():Void + { var buffer1 = new ArrayBuffer(16); var array1 = new UInt32Array(buffer1); array1[0] = 0xcafebabe; @@ -333,7 +350,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -355,7 +373,8 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt32ArrayRangeError():Void { + public function testSetUInt32ArrayRangeError():Void + { var buffer1 = new ArrayBuffer(16); var array1 = new UInt32Array(buffer1); array1[0] = 0xcafebabe; @@ -367,7 +386,8 @@ class UInt32ArrayTest extends Test { var array2 = new UInt32Array(buffer2); // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -380,4 +400,4 @@ class UInt32ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); } -} \ No newline at end of file +} diff --git a/tests/unit/src/utils/UInt8ArrayTest.hx b/tests/unit/src/utils/UInt8ArrayTest.hx index 04a87afd8c..9503481fc9 100644 --- a/tests/unit/src/utils/UInt8ArrayTest.hx +++ b/tests/unit/src/utils/UInt8ArrayTest.hx @@ -7,19 +7,23 @@ import lime.utils.UInt8Array; import utest.Assert; import utest.Test; -class UInt8ArrayTest extends Test { - public function new() { +class UInt8ArrayTest extends Test +{ + public function new() + { super(); } - public function testByteLength():Void { + public function testByteLength():Void + { var buffer = new ArrayBuffer(4); var array = new UInt8Array(buffer); Assert.equals(4, array.length); Assert.equals(4, array.byteLength); } - public function testValues():Void { + public function testValues():Void + { var buffer = new ArrayBuffer(4); var array = new UInt8Array(buffer); Assert.equals(0x0, array[0]); @@ -36,7 +40,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0xbe, array[3]); } - public function testSubarray():Void { + public function testSubarray():Void + { var buffer = new ArrayBuffer(4); var array = new UInt8Array(buffer); array[0] = 0xca; @@ -81,12 +86,13 @@ class UInt8ArrayTest extends Test { Assert.equals(0xbe, beyondLength[3]); } - public function testSetArrayOfInts():Void { + public function testSetArrayOfInts():Void + { var array1:Array = [0xca, 0xfe, 0xba, 0xbe]; var buffer2 = new ArrayBuffer(8); var array2 = new UInt8Array(buffer2); - + array2.set(array1); Assert.equals(0xca, array2[0]); Assert.equals(0xfe, array2[1]); @@ -97,7 +103,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -111,11 +118,13 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); Assert.equals(0x0, array2[0]); @@ -128,7 +137,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt8Array():Void { + public function testSetUInt8Array():Void + { var buffer1 = new ArrayBuffer(4); var array1 = new UInt8Array(buffer1); array1[0] = 0xca; @@ -150,7 +160,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -164,12 +175,14 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -183,7 +196,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt16Array():Void { + public function testSetUInt16Array():Void + { var buffer1 = new ArrayBuffer(8); var array1 = new UInt16Array(buffer1); array1[0] = 0xcafe; @@ -205,7 +219,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -219,12 +234,14 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -238,7 +255,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[7]); } - public function testSetUInt32Array():Void { + public function testSetUInt32Array():Void + { var buffer1 = new ArrayBuffer(16); var array1 = new UInt32Array(buffer1); array1[0] = 0xcafebabe; @@ -260,7 +278,8 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[7]); // reset the array to all zeros - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } @@ -274,12 +293,14 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); - for (i in 0...array2.length) { + for (i in 0...array2.length) + { array2[i] = 0x0; } // if the array can't fit, it throws - Assert.raises(function():Void { + Assert.raises(function():Void + { array2.set(array1, 6); }); // in that case, none of the values should have been updated @@ -292,4 +313,4 @@ class UInt8ArrayTest extends Test { Assert.equals(0x0, array2[6]); Assert.equals(0x0, array2[7]); } -} \ No newline at end of file +} diff --git a/tests/vulkan-smoke/Assets/shaders/cube.frag.spv b/tests/vulkan-smoke/Assets/shaders/cube.frag.spv new file mode 100644 index 0000000000..f55655e156 Binary files /dev/null and b/tests/vulkan-smoke/Assets/shaders/cube.frag.spv differ diff --git a/tests/vulkan-smoke/Assets/shaders/cube.vert.spv b/tests/vulkan-smoke/Assets/shaders/cube.vert.spv new file mode 100644 index 0000000000..6021a00526 Binary files /dev/null and b/tests/vulkan-smoke/Assets/shaders/cube.vert.spv differ diff --git a/tests/vulkan-smoke/Assets/shaders/quad.frag.spv b/tests/vulkan-smoke/Assets/shaders/quad.frag.spv new file mode 100644 index 0000000000..5d26e006e4 Binary files /dev/null and b/tests/vulkan-smoke/Assets/shaders/quad.frag.spv differ diff --git a/tests/vulkan-smoke/Assets/shaders/quad.vert.spv b/tests/vulkan-smoke/Assets/shaders/quad.vert.spv new file mode 100644 index 0000000000..50c4bd2594 Binary files /dev/null and b/tests/vulkan-smoke/Assets/shaders/quad.vert.spv differ diff --git a/tests/vulkan-smoke/Source/Main.hx b/tests/vulkan-smoke/Source/Main.hx new file mode 100644 index 0000000000..d0ca0048ac --- /dev/null +++ b/tests/vulkan-smoke/Source/Main.hx @@ -0,0 +1,988 @@ +package; + +import haxe.Int64; +import haxe.Timer; +import haxe.io.Bytes; +import lime.app.Application; +import lime.graphics.RenderContext; +import lime.graphics.RenderContextType; +import lime.graphics.VulkanRenderContext; +import lime.graphics.vulkan.VK; +import lime.graphics.vulkan.VKBuffer; +import lime.graphics.vulkan.VKCommandBuffer; +import lime.graphics.vulkan.VKCommandPool; +import lime.graphics.vulkan.VKDescriptorPool; +import lime.graphics.vulkan.VKDescriptorPoolSize; +import lime.graphics.vulkan.VKDescriptorSet; +import lime.graphics.vulkan.VKDescriptorSetLayout; +import lime.graphics.vulkan.VKDescriptorSetLayoutBinding; +import lime.graphics.vulkan.VKDevice; +import lime.graphics.vulkan.VKFence; +import lime.graphics.vulkan.VKFramebuffer; +import lime.graphics.vulkan.VKGraphicsPipelineInfo; +import lime.graphics.vulkan.VKImage; +import lime.graphics.vulkan.VKImageView; +import lime.graphics.vulkan.VKInstance; +import lime.graphics.vulkan.VKPhysicalDevice; +import lime.graphics.vulkan.VKPipeline; +import lime.graphics.vulkan.VKPipelineLayout; +import lime.graphics.vulkan.VKQueueFamilyInfo; +import lime.graphics.vulkan.VKRenderPass; +import lime.graphics.vulkan.VKSampler; +import lime.graphics.vulkan.VKSemaphore; +import lime.graphics.vulkan.VKShaderModule; +import lime.graphics.vulkan.VKSurface; +import lime.graphics.vulkan.VKSwapchain; +import lime.graphics.vulkan.VKVertexAttribute; +import lime.graphics.vulkan.VKVertexBinding; +import lime.system.System; +import lime.utils.Assets; + +class Main extends Application +{ + private static inline var DEPTH_FORMAT = VK.FORMAT_D32_SFLOAT; + private static inline var OFFSCREEN_FORMAT = VK.FORMAT_R8G8B8A8_UNORM; + private static inline var OFFSCREEN_SIZE = 256; + private static inline var REQUESTED_MSAA_SAMPLES = VK.SAMPLE_COUNT_4_BIT; + + private var colorImage:VKImage; + private var colorView:VKImageView; + private var commandBuffer:VKCommandBuffer; + private var commandPool:VKCommandPool; + private var cubeDescriptorSet:VKDescriptorSet; + private var cubeDescriptorSetLayout:VKDescriptorSetLayout; + private var cubeFragmentShader:VKShaderModule; + private var cubeIndexBuffer:VKBuffer; + private var cubePipeline:VKPipeline; + private var cubePipelineLayout:VKPipelineLayout; + private var cubeVertexBuffer:VKBuffer; + private var cubeVertexShader:VKShaderModule; + private var depthImage:VKImage; + private var depthView:VKImageView; + private var descriptorPool:VKDescriptorPool; + private var device:VKDevice; + private var fence:VKFence; + private var finished:Bool; + private var framebuffers:Array = []; + private var imageAvailable:VKSemaphore; + private var imageViews:Array = []; + private var instance:VKInstance; + private var offscreenDescriptorSet:VKDescriptorSet; + private var offscreenDescriptorSetLayout:VKDescriptorSetLayout; + private var offscreenFramebuffer:VKFramebuffer; + private var offscreenImage:VKImage; + private var offscreenPipeline:VKPipeline; + private var offscreenPipelineLayout:VKPipelineLayout; + private var offscreenRenderPass:VKRenderPass; + private var offscreenSampler:VKSampler; + private var offscreenView:VKImageView; + private var physicalDevice:VKPhysicalDevice; + private var preloadComplete:Bool; + private var quadFragmentShader:VKShaderModule; + private var quadIndexBuffer:VKBuffer; + private var quadVertexBuffer:VKBuffer; + private var quadVertexShader:VKShaderModule; + private var queueFamily:VKQueueFamilyInfo; + private var renderFinished:VKSemaphore; + private var renderPass:VKRenderPass; + private var msaaSamples:Int = VK.SAMPLE_COUNT_1_BIT; + private var sourceTextureImage:VKImage; + private var sourceTextureSampler:VKSampler; + private var sourceTextureView:VKImageView; + private var surface:VKSurface; + private var swapchain:VKSwapchain; + private var uniformBuffer:VKBuffer; + private var windowCreated:Bool; + + public function new() + { + super(); + } + + override public function onWindowCreate():Void + { + super.onWindowCreate(); + + if (window == null) + { + fail("Missing primary window"); + return; + } + + if (window.context == null || window.context.type != RenderContextType.VULKAN || window.context.vulkan == null) + { + fail("Primary window was not created with a Vulkan context"); + return; + } + + windowCreated = true; + tryCreateRenderer(); + } + + override public function onPreloadComplete():Void + { + super.onPreloadComplete(); + + preloadComplete = true; + tryCreateRenderer(); + } + + override public function onWindowResize(width:Int, height:Int):Void + { + super.onWindowResize(width, height); + + if (!finished && device != null && device.isValid() && width > 0 && height > 0) + { + recreateSwapchain(width, height); + } + } + + override public function render(context:RenderContext):Void + { + super.render(context); + + if (finished || device == null) + { + return; + } + + if (!drawFrame()) + { + return; + } + + finished = true; + Timer.delay(complete, 50); + } + + private function createRenderer(context:VulkanRenderContext):Void + { + var extensions = context.getInstanceExtensions(); + if (extensions == null || extensions.length == 0) + { + fail("No Vulkan instance extensions were reported"); + return; + } + + var procAddr = context.getInstanceProcAddr(); + if (!isNonZero(procAddr)) + { + fail("vkGetInstanceProcAddr was not available"); + return; + } + + instance = VK.createInstance(context, "LimeVulkanSmoke"); + if (instance == null || !instance.isValid()) + { + fail("Failed to create Vulkan instance: " + VK.getLastError()); + return; + } + + surface = instance.createSurface(); + if (surface == null || !surface.isValid()) + { + fail("Failed to create Vulkan surface"); + return; + } + + physicalDevice = instance.pickPhysicalDevice(surface); + if (physicalDevice == null || !physicalDevice.hasQueueFamily(true, true)) + { + fail("No present-capable graphics queue family was found"); + return; + } + msaaSamples = physicalDevice.supportsSampleCount(REQUESTED_MSAA_SAMPLES, true) ? REQUESTED_MSAA_SAMPLES : VK.SAMPLE_COUNT_1_BIT; + + queueFamily = physicalDevice.getQueueFamily(true, true); + device = physicalDevice.createDevice(queueFamily); + if (device == null || !device.isValid() || device.graphicsQueue == null || !device.graphicsQueue.isValid()) + { + fail("Failed to create Vulkan logical device: " + VK.getLastError()); + return; + } + + commandPool = device.createCommandPool(queueFamily); + commandBuffer = commandPool != null ? commandPool.allocateCommandBuffer() : null; + imageAvailable = device.createSemaphore(); + renderFinished = device.createSemaphore(); + fence = device.createFence(true); + + if (commandPool == null || commandBuffer == null || imageAvailable == null || renderFinished == null || fence == null) + { + fail("Failed to create Vulkan frame synchronization resources: " + VK.getLastError()); + return; + } + + swapchain = device.createSwapchain(surface, window.width, window.height); + if (swapchain == null || !swapchain.isValid() || swapchain.images.length == 0) + { + fail("Failed to create Vulkan swapchain: " + VK.getLastError()); + return; + } + + if (!createSourceTexture() + || !createGeometry() + || !createDescriptorLayouts() + || !createOffscreenPass() + || !createOnscreenPass()) + { + return; + } + } + + private function tryCreateRenderer():Void + { + if (device != null || !windowCreated || !preloadComplete || window == null || window.context == null || window.context.vulkan == null) + { + return; + } + + createRenderer(window.context.vulkan); + } + + private function createSourceTexture():Bool + { + sourceTextureImage = device.createImage(2, 2, OFFSCREEN_FORMAT, VK.IMAGE_USAGE_TRANSFER_DST_BIT | VK.IMAGE_USAGE_SAMPLED_BIT); + if (sourceTextureImage == null || sourceTextureImage.allocateMemory(VK.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == null) + { + fail("Failed to create Vulkan texture image: " + VK.getLastError()); + return false; + } + + var pixels = Bytes.alloc(16); + var values = [ + 0xFF, 0x90, 0x20, 0xFF, + 0x10, 0xD8, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x20, 0x40, 0xFF, 0xFF + ]; + for (i in 0...values.length) + { + pixels.set(i, values[i]); + } + + var staging = device.createStagingBuffer(Int64.ofInt(pixels.length), pixels); + if (staging == null) + { + fail("Failed to create Vulkan texture staging buffer: " + VK.getLastError()); + return false; + } + + if (!commandBuffer.reset() + || !commandBuffer.begin(VK.COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) + || !commandBuffer.pipelineBarrierImage(sourceTextureImage, VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK.PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK.PIPELINE_STAGE_TRANSFER_BIT, 0, VK.ACCESS_TRANSFER_WRITE_BIT, VK.IMAGE_ASPECT_COLOR_BIT) + || !commandBuffer.copyBufferToImage(staging, sourceTextureImage, 2, 2) + || !commandBuffer.pipelineBarrierImage(sourceTextureImage, VK.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK.PIPELINE_STAGE_TRANSFER_BIT, VK.PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK.ACCESS_TRANSFER_WRITE_BIT, VK.ACCESS_SHADER_READ_BIT, + VK.IMAGE_ASPECT_COLOR_BIT) + || !commandBuffer.end()) + { + staging.dispose(true); + fail("Failed to record Vulkan texture upload commands: " + VK.getLastError()); + return false; + } + + if (!fence.waitForever() || !fence.reset() || !device.graphicsQueue.submit(commandBuffer, fence) || !fence.waitForever()) + { + staging.dispose(true); + fail("Failed to submit Vulkan texture upload: " + VK.getLastError()); + return false; + } + + staging.dispose(true); + + sourceTextureView = sourceTextureImage.createView(OFFSCREEN_FORMAT); + sourceTextureSampler = device.createSampler(VK.FILTER_NEAREST, VK.SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK.SAMPLER_MIPMAP_MODE_NEAREST); + + if (sourceTextureView == null || sourceTextureSampler == null) + { + fail("Failed to create Vulkan texture view/sampler: " + VK.getLastError()); + return false; + } + + return true; + } + + private function createGeometry():Bool + { + if (!createQuadGeometry() || !createCubeGeometry()) + { + return false; + } + + uniformBuffer = device.createUniformBuffer(Int64.ofInt(64), VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT); + if (uniformBuffer == null) + { + fail("Failed to create Vulkan uniform buffer: " + VK.getLastError()); + return false; + } + + return true; + } + + private function createQuadGeometry():Bool + { + var vertices = Bytes.alloc(4 * 32); + var data = [ + -0.72, -0.72, 0.0, 1.0, 1.0, 1.0, 1.0, 0.86, + 0.72, -0.72, 1.0, 1.0, 1.0, 1.0, 1.0, 0.86, + 0.72, 0.72, 1.0, 0.0, 1.0, 1.0, 1.0, 0.86, + -0.72, 0.72, 0.0, 0.0, 1.0, 1.0, 1.0, 0.86 + ]; + for (i in 0...data.length) + { + vertices.setFloat(i * 4, data[i]); + } + + var indices = Bytes.alloc(6 * 2); + var indexData = [0, 1, 2, 2, 3, 0]; + for (i in 0...indexData.length) + { + indices.setUInt16(i * 2, indexData[i]); + } + + quadVertexBuffer = device.createVertexBuffer(Int64.ofInt(vertices.length), VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, + vertices); + quadIndexBuffer = device.createIndexBuffer(Int64.ofInt(indices.length), VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, + indices); + + if (quadVertexBuffer == null || quadIndexBuffer == null) + { + fail("Failed to create Vulkan quad buffers: " + VK.getLastError()); + return false; + } + + return true; + } + + private function createCubeGeometry():Bool + { + var vertexData = [ + -1.0, -1.0, 1.0, 0.0, 1.0, 1.0, 0.85, 0.55, 1.0, + 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 0.85, 0.55, 1.0, + 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.85, 0.55, 1.0, + -1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.85, 0.55, 1.0, + 1.0, -1.0, -1.0, 0.0, 1.0, 0.55, 0.8, 1.0, 1.0, + -1.0, -1.0, -1.0, 1.0, 1.0, 0.55, 0.8, 1.0, 1.0, + -1.0, 1.0, -1.0, 1.0, 0.0, 0.55, 0.8, 1.0, 1.0, + 1.0, 1.0, -1.0, 0.0, 0.0, 0.55, 0.8, 1.0, 1.0, + -1.0, -1.0, -1.0, 0.0, 1.0, 0.75, 1.0, 0.65, 1.0, + -1.0, -1.0, 1.0, 1.0, 1.0, 0.75, 1.0, 0.65, 1.0, + -1.0, 1.0, 1.0, 1.0, 0.0, 0.75, 1.0, 0.65, 1.0, + -1.0, 1.0, -1.0, 0.0, 0.0, 0.75, 1.0, 0.65, 1.0, + 1.0, -1.0, 1.0, 0.0, 1.0, 1.0, 0.75, 0.6, 1.0, + 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 0.75, 0.6, 1.0, + 1.0, 1.0, -1.0, 1.0, 0.0, 1.0, 0.75, 0.6, 1.0, + 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.75, 0.6, 1.0, + -1.0, 1.0, 1.0, 0.0, 1.0, 0.65, 0.95, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 0.65, 0.95, 1.0, 1.0, + 1.0, 1.0, -1.0, 1.0, 0.0, 0.65, 0.95, 1.0, 1.0, + -1.0, 1.0, -1.0, 0.0, 0.0, 0.65, 0.95, 1.0, 1.0, + -1.0, -1.0, -1.0, 0.0, 1.0, 1.0, 0.65, 0.75, 1.0, + 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 0.65, 0.75, 1.0, + 1.0, -1.0, 1.0, 1.0, 0.0, 1.0, 0.65, 0.75, 1.0, + -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.65, 0.75, 1.0 + ]; + + var indexData = [ + 0, 1, 2, 2, 3, 0, + 4, 5, 6, 6, 7, 4, + 8, 9, 10, 10, 11, 8, + 12, 13, 14, 14, 15, 12, + 16, 17, 18, 18, 19, 16, + 20, 21, 22, 22, 23, 20 + ]; + + var vertices = Bytes.alloc(vertexData.length * 4); + for (i in 0...vertexData.length) + { + vertices.setFloat(i * 4, vertexData[i]); + } + + var indices = Bytes.alloc(indexData.length * 2); + for (i in 0...indexData.length) + { + indices.setUInt16(i * 2, indexData[i]); + } + + cubeVertexBuffer = device.createVertexBuffer(Int64.ofInt(vertices.length), VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, + vertices); + cubeIndexBuffer = device.createIndexBuffer(Int64.ofInt(indices.length), VK.MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK.MEMORY_PROPERTY_HOST_COHERENT_BIT, + indices); + + if (cubeVertexBuffer == null || cubeIndexBuffer == null) + { + fail("Failed to create Vulkan cube buffers: " + VK.getLastError()); + return false; + } + + return true; + } + + private function createDescriptorLayouts():Bool + { + offscreenDescriptorSetLayout = device.createDescriptorSetLayout([ + new VKDescriptorSetLayoutBinding(0, VK.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK.SHADER_STAGE_FRAGMENT_BIT) + ]); + cubeDescriptorSetLayout = device.createDescriptorSetLayout([ + new VKDescriptorSetLayoutBinding(0, VK.DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK.SHADER_STAGE_VERTEX_BIT), + new VKDescriptorSetLayoutBinding(1, VK.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK.SHADER_STAGE_FRAGMENT_BIT) + ]); + descriptorPool = device.createDescriptorPool(2, [ + new VKDescriptorPoolSize(VK.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2), + new VKDescriptorPoolSize(VK.DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1) + ]); + + if (offscreenDescriptorSetLayout == null || cubeDescriptorSetLayout == null || descriptorPool == null) + { + fail("Failed to create Vulkan descriptor layouts: " + VK.getLastError()); + return false; + } + + return true; + } + + private function createOffscreenPass():Bool + { + offscreenRenderPass = device.createRenderPass(OFFSCREEN_FORMAT, VK.FORMAT_UNDEFINED, VK.SAMPLE_COUNT_1_BIT, VK.ATTACHMENT_LOAD_OP_CLEAR, + VK.ATTACHMENT_STORE_OP_STORE, VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + offscreenImage = device.createImage(OFFSCREEN_SIZE, OFFSCREEN_SIZE, OFFSCREEN_FORMAT, + VK.IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK.IMAGE_USAGE_SAMPLED_BIT | VK.IMAGE_USAGE_TRANSFER_SRC_BIT); + + if (offscreenRenderPass == null + || offscreenImage == null + || offscreenImage.allocateMemory(VK.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == null) + { + fail("Failed to create Vulkan offscreen render target: " + VK.getLastError()); + return false; + } + + offscreenView = offscreenImage.createView(OFFSCREEN_FORMAT); + offscreenSampler = device.createSampler(VK.FILTER_LINEAR, VK.SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK.SAMPLER_MIPMAP_MODE_LINEAR); + offscreenFramebuffer = offscreenView != null ? device.createFramebuffer(offscreenRenderPass, [offscreenView], OFFSCREEN_SIZE, OFFSCREEN_SIZE) : null; + + offscreenDescriptorSet = descriptorPool.allocate(offscreenDescriptorSetLayout); + offscreenPipelineLayout = device.createPipelineLayout([offscreenDescriptorSetLayout]); + quadVertexShader = device.createShaderModule(Assets.getBytes("Assets/shaders/quad.vert.spv")); + quadFragmentShader = device.createShaderModule(Assets.getBytes("Assets/shaders/quad.frag.spv")); + + if (offscreenView == null + || offscreenSampler == null + || offscreenFramebuffer == null + || offscreenDescriptorSet == null + || offscreenPipelineLayout == null + || quadVertexShader == null + || quadFragmentShader == null + || !offscreenDescriptorSet.updateImage(0, sourceTextureView, sourceTextureSampler)) + { + fail("Failed to create Vulkan offscreen pipeline resources: " + VK.getLastError()); + return false; + } + + var info = new VKGraphicsPipelineInfo(); + info.blend = true; + info.cullMode = VK.CULL_MODE_NONE; + info.vertexBindings.push(new VKVertexBinding(0, 32, VK.VERTEX_INPUT_RATE_VERTEX)); + info.vertexAttributes.push(new VKVertexAttribute(0, 0, VK.FORMAT_R32G32_SFLOAT, 0)); + info.vertexAttributes.push(new VKVertexAttribute(1, 0, VK.FORMAT_R32G32_SFLOAT, 8)); + info.vertexAttributes.push(new VKVertexAttribute(2, 0, VK.FORMAT_R32G32B32A32_SFLOAT, 16)); + + offscreenPipeline = device.createGraphicsPipeline(offscreenRenderPass, offscreenPipelineLayout, quadVertexShader, quadFragmentShader, info); + if (offscreenPipeline == null) + { + fail("Failed to create Vulkan offscreen graphics pipeline: " + VK.getLastError()); + return false; + } + + return true; + } + + private function createOnscreenPass():Bool + { + if (msaaSamples != VK.SAMPLE_COUNT_1_BIT) + { + renderPass = device.createRenderPass(swapchain.format, DEPTH_FORMAT, msaaSamples, VK.ATTACHMENT_LOAD_OP_CLEAR, VK.ATTACHMENT_STORE_OP_DONT_CARE, + VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK.IMAGE_LAYOUT_UNDEFINED, + VK.IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK.ATTACHMENT_LOAD_OP_CLEAR, VK.ATTACHMENT_STORE_OP_DONT_CARE, swapchain.format, + VK.ATTACHMENT_LOAD_OP_DONT_CARE, VK.ATTACHMENT_STORE_OP_STORE, VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_PRESENT_SRC_KHR); + } + else + { + renderPass = device.createRenderPass(swapchain.format, DEPTH_FORMAT, VK.SAMPLE_COUNT_1_BIT, VK.ATTACHMENT_LOAD_OP_CLEAR, + VK.ATTACHMENT_STORE_OP_STORE, VK.IMAGE_LAYOUT_UNDEFINED, VK.IMAGE_LAYOUT_PRESENT_SRC_KHR); + } + + if (renderPass == null || !createColorResources() || !createDepthResources() || !createFramebuffers()) + { + fail("Failed to create Vulkan onscreen render pass resources: " + VK.getLastError()); + return false; + } + + cubeDescriptorSet = descriptorPool.allocate(cubeDescriptorSetLayout); + cubePipelineLayout = device.createPipelineLayout([cubeDescriptorSetLayout]); + cubeVertexShader = device.createShaderModule(Assets.getBytes("Assets/shaders/cube.vert.spv")); + cubeFragmentShader = device.createShaderModule(Assets.getBytes("Assets/shaders/cube.frag.spv")); + + if (cubeDescriptorSet == null + || cubePipelineLayout == null + || cubeVertexShader == null + || cubeFragmentShader == null + || !cubeDescriptorSet.updateBuffer(0, uniformBuffer, 64) + || !cubeDescriptorSet.updateImage(1, offscreenView, offscreenSampler)) + { + fail("Failed to create Vulkan cube descriptor resources: " + VK.getLastError()); + return false; + } + + var info = new VKGraphicsPipelineInfo(); + info.depthTest = true; + info.depthWrite = true; + info.depthCompareOp = VK.COMPARE_OP_LESS; + info.cullMode = VK.CULL_MODE_BACK_BIT; + info.frontFace = VK.FRONT_FACE_CLOCKWISE; + info.rasterizationSamples = msaaSamples; + info.vertexBindings.push(new VKVertexBinding(0, 36, VK.VERTEX_INPUT_RATE_VERTEX)); + info.vertexAttributes.push(new VKVertexAttribute(0, 0, VK.FORMAT_R32G32B32_SFLOAT, 0)); + info.vertexAttributes.push(new VKVertexAttribute(1, 0, VK.FORMAT_R32G32_SFLOAT, 12)); + info.vertexAttributes.push(new VKVertexAttribute(2, 0, VK.FORMAT_R32G32B32A32_SFLOAT, 20)); + + cubePipeline = device.createGraphicsPipeline(renderPass, cubePipelineLayout, cubeVertexShader, cubeFragmentShader, info); + if (cubePipeline == null) + { + fail("Failed to create Vulkan cube graphics pipeline: " + VK.getLastError()); + return false; + } + + return true; + } + + private function createColorResources():Bool + { + disposeColorResources(); + + if (msaaSamples == VK.SAMPLE_COUNT_1_BIT) + { + return true; + } + + colorImage = device.createImage(swapchain.width, swapchain.height, swapchain.format, + VK.IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK.IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, 1, 1, 1, VK.IMAGE_TYPE_2D, VK.IMAGE_TILING_OPTIMAL, msaaSamples); + if (colorImage == null || colorImage.allocateMemory(VK.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == null) + { + return false; + } + + colorView = colorImage.createView(swapchain.format); + return colorView != null; + } + + private function createDepthResources():Bool + { + disposeDepthResources(); + + depthImage = device.createImage(swapchain.width, swapchain.height, DEPTH_FORMAT, VK.IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 1, 1, 1, + VK.IMAGE_TYPE_2D, VK.IMAGE_TILING_OPTIMAL, msaaSamples); + if (depthImage == null || depthImage.allocateMemory(VK.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == null) + { + return false; + } + + depthView = depthImage.createView(DEPTH_FORMAT, VK.IMAGE_ASPECT_DEPTH_BIT); + return depthView != null; + } + + private function createFramebuffers():Bool + { + disposeSwapchainFramebuffers(); + + for (image in swapchain.images) + { + var imageView = image.createView(swapchain.format); + if (imageView == null) + { + fail("Failed to create Vulkan swapchain image view: " + VK.getLastError()); + return false; + } + + var attachments = msaaSamples != VK.SAMPLE_COUNT_1_BIT ? [colorView, depthView, imageView] : [imageView, depthView]; + var framebuffer = device.createFramebuffer(renderPass, attachments, swapchain.width, swapchain.height); + if (framebuffer == null) + { + imageView.dispose(); + fail("Failed to create Vulkan framebuffer: " + VK.getLastError()); + return false; + } + + imageViews.push(imageView); + framebuffers.push(framebuffer); + } + + return true; + } + + private function drawFrame():Bool + { + if (!fence.waitForever()) + { + fail("Failed to wait for Vulkan frame fence: " + VK.getLastError()); + return false; + } + + var acquired = swapchain.acquireNextImage(imageAvailable); + if (acquired.result == VK.ERROR_OUT_OF_DATE_KHR) + { + return recreateSwapchain(window.width, window.height); + } + if (!acquired.isSuccess()) + { + fail("Failed to acquire Vulkan swapchain image: " + VK.getLastError()); + return false; + } + + var framebuffer = framebuffers[acquired.imageIndex]; + if (framebuffer == null) + { + fail("Swapchain image did not have a framebuffer"); + return false; + } + + if (!updateCubeUniform()) + { + fail("Failed to update Vulkan uniform buffer: " + VK.getLastError()); + return false; + } + + if (!commandBuffer.reset() + || !commandBuffer.begin(VK.COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) + || !commandBuffer.beginRenderPass(offscreenRenderPass, offscreenFramebuffer, OFFSCREEN_SIZE, OFFSCREEN_SIZE, 0.02, 0.04, 0.07, 1.0) + || !commandBuffer.setViewport(0, 0, OFFSCREEN_SIZE, OFFSCREEN_SIZE) + || !commandBuffer.setScissor(0, 0, OFFSCREEN_SIZE, OFFSCREEN_SIZE) + || !commandBuffer.bindPipeline(offscreenPipeline) + || !commandBuffer.bindDescriptorSet(offscreenPipelineLayout, offscreenDescriptorSet) + || !commandBuffer.bindVertexBuffer(quadVertexBuffer) + || !commandBuffer.bindIndexBuffer(quadIndexBuffer) + || !commandBuffer.drawIndexed(6) + || !commandBuffer.endRenderPass() + || !commandBuffer.pipelineBarrierImage(offscreenImage, VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK.PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK.PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK.ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK.ACCESS_SHADER_READ_BIT, VK.IMAGE_ASPECT_COLOR_BIT) + || !commandBuffer.beginRenderPass(renderPass, framebuffer, swapchain.width, swapchain.height, 0.07, 0.08, 0.09, 1.0, 1.0) + || !commandBuffer.setViewport(0, 0, swapchain.width, swapchain.height) + || !commandBuffer.setScissor(0, 0, swapchain.width, swapchain.height) + || !commandBuffer.bindPipeline(cubePipeline) + || !commandBuffer.bindDescriptorSet(cubePipelineLayout, cubeDescriptorSet) + || !commandBuffer.bindVertexBuffer(cubeVertexBuffer) + || !commandBuffer.bindIndexBuffer(cubeIndexBuffer) + || !commandBuffer.drawIndexed(36) + || !commandBuffer.endRenderPass() + || !commandBuffer.end()) + { + fail("Failed to record Vulkan draw commands: " + VK.getLastError()); + return false; + } + + if (!fence.reset() + || !device.graphicsQueue.submitSynced(commandBuffer, imageAvailable, renderFinished, fence) + || !fence.waitForever()) + { + fail("Failed to submit Vulkan draw commands: " + VK.getLastError()); + return false; + } + + var presentResult = device.graphicsQueue.present(swapchain, acquired.imageIndex, renderFinished); + if (presentResult == VK.ERROR_OUT_OF_DATE_KHR) + { + return recreateSwapchain(window.width, window.height); + } + if (presentResult != VK.SUCCESS && presentResult != VK.SUBOPTIMAL_KHR) + { + fail("Failed to present Vulkan swapchain image: " + VK.getLastError()); + return false; + } + + return true; + } + + private function updateCubeUniform():Bool + { + var aspect = swapchain.height > 0 ? swapchain.width / swapchain.height : 1.0; + var angle = Timer.stamp(); + var model = multiply(rotationY(angle), rotationX(angle * 0.61)); + var view = translation(0, 0, -4.25); + var projection = perspective(Math.PI / 3, aspect, 0.1, 100); + var mvp = multiply(projection, multiply(view, model)); + var bytes = Bytes.alloc(64); + + for (i in 0...16) + { + bytes.setFloat(i * 4, mvp[i]); + } + + return uniformBuffer.upload(bytes); + } + + private function recreateSwapchain(width:Int, height:Int):Bool + { + if (width <= 0 || height <= 0 || swapchain == null) + { + return false; + } + + if (!device.waitIdle()) + { + fail("Failed to idle Vulkan device before swapchain recreation: " + VK.getLastError()); + return false; + } + + disposeSwapchainResources(); + var oldSwapchain = swapchain; + swapchain = oldSwapchain.recreate(width, height); + oldSwapchain.dispose(); + + if (swapchain == null || !swapchain.isValid() || swapchain.images.length == 0) + { + fail("Failed to recreate Vulkan swapchain: " + VK.getLastError()); + return false; + } + + return createColorResources() && createDepthResources() && createFramebuffers(); + } + + private function disposeSwapchainResources():Void + { + disposeSwapchainFramebuffers(); + disposeColorResources(); + disposeDepthResources(); + } + + private function disposeSwapchainFramebuffers():Void + { + for (framebuffer in framebuffers) + { + if (framebuffer != null) + { + framebuffer.dispose(); + } + } + framebuffers = []; + + for (imageView in imageViews) + { + if (imageView != null) + { + imageView.dispose(); + } + } + imageViews = []; + } + + private function disposeColorResources():Void + { + if (colorView != null) + { + colorView.dispose(); + colorView = null; + } + if (colorImage != null) + { + colorImage.dispose(true); + colorImage = null; + } + } + + private function disposeDepthResources():Void + { + if (depthView != null) + { + depthView.dispose(); + depthView = null; + } + if (depthImage != null) + { + depthImage.dispose(true); + depthImage = null; + } + } + + private function complete():Void + { + disposeRenderer(); + + if (window != null) + { + window.close(); + } + System.exit(0); + } + + private function disposeRenderer():Void + { + if (device != null && device.isValid()) + { + device.waitIdle(); + } + + disposeSwapchainResources(); + if (offscreenFramebuffer != null) offscreenFramebuffer.dispose(); + if (offscreenView != null) offscreenView.dispose(); + if (offscreenImage != null) offscreenImage.dispose(true); + if (offscreenSampler != null) offscreenSampler.dispose(); + if (cubeIndexBuffer != null) cubeIndexBuffer.dispose(true); + if (cubeVertexBuffer != null) cubeVertexBuffer.dispose(true); + if (quadIndexBuffer != null) quadIndexBuffer.dispose(true); + if (quadVertexBuffer != null) quadVertexBuffer.dispose(true); + if (uniformBuffer != null) uniformBuffer.dispose(true); + if (cubePipeline != null) cubePipeline.dispose(); + if (cubePipelineLayout != null) cubePipelineLayout.dispose(); + if (offscreenPipeline != null) offscreenPipeline.dispose(); + if (offscreenPipelineLayout != null) offscreenPipelineLayout.dispose(); + if (descriptorPool != null) descriptorPool.dispose(); + if (cubeDescriptorSetLayout != null) cubeDescriptorSetLayout.dispose(); + if (offscreenDescriptorSetLayout != null) offscreenDescriptorSetLayout.dispose(); + if (sourceTextureSampler != null) sourceTextureSampler.dispose(); + if (sourceTextureView != null) sourceTextureView.dispose(); + if (sourceTextureImage != null) sourceTextureImage.dispose(true); + if (cubeFragmentShader != null) cubeFragmentShader.dispose(); + if (cubeVertexShader != null) cubeVertexShader.dispose(); + if (quadFragmentShader != null) quadFragmentShader.dispose(); + if (quadVertexShader != null) quadVertexShader.dispose(); + if (renderPass != null) renderPass.dispose(); + if (offscreenRenderPass != null) offscreenRenderPass.dispose(); + if (fence != null) fence.dispose(); + if (renderFinished != null) renderFinished.dispose(); + if (imageAvailable != null) imageAvailable.dispose(); + if (commandBuffer != null) commandBuffer.dispose(); + if (commandPool != null) commandPool.dispose(); + if (swapchain != null) swapchain.dispose(); + if (device != null) device.dispose(); + if (surface != null) surface.dispose(); + if (instance != null) instance.dispose(); + + commandBuffer = null; + commandPool = null; + colorImage = null; + colorView = null; + cubeDescriptorSet = null; + cubeDescriptorSetLayout = null; + cubeFragmentShader = null; + cubeIndexBuffer = null; + cubePipeline = null; + cubePipelineLayout = null; + cubeVertexBuffer = null; + cubeVertexShader = null; + descriptorPool = null; + device = null; + fence = null; + imageAvailable = null; + instance = null; + offscreenDescriptorSet = null; + offscreenDescriptorSetLayout = null; + offscreenFramebuffer = null; + offscreenImage = null; + offscreenPipeline = null; + offscreenPipelineLayout = null; + offscreenRenderPass = null; + offscreenSampler = null; + offscreenView = null; + quadFragmentShader = null; + quadIndexBuffer = null; + quadVertexBuffer = null; + quadVertexShader = null; + renderFinished = null; + renderPass = null; + sourceTextureImage = null; + sourceTextureSampler = null; + sourceTextureView = null; + surface = null; + swapchain = null; + uniformBuffer = null; + } + + private function fail(message:String):Void + { + trace("Vulkan smoke failed: " + message); + disposeRenderer(); + System.exit(1); + } + + private static function identity():Array + { + return [ + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 + ]; + } + + private static inline function isNonZero(value:Int64):Bool + { + return value.high != 0 || value.low != 0; + } + + private static function multiply(a:Array, b:Array):Array + { + var result = []; + + for (column in 0...4) + { + for (row in 0...4) + { + var value = 0.0; + for (i in 0...4) + { + value += a[i * 4 + row] * b[column * 4 + i]; + } + result[column * 4 + row] = value; + } + } + + return result; + } + + private static function perspective(fovY:Float, aspect:Float, near:Float, far:Float):Array + { + var f = 1.0 / Math.tan(fovY * 0.5); + var result = [ + f / aspect, 0.0, 0.0, 0.0, + 0.0, -f, 0.0, 0.0, + 0.0, 0.0, far / (near - far), -1.0, + 0.0, 0.0, (far * near) / (near - far), 0.0 + ]; + return result; + } + + private static function rotationX(angle:Float):Array + { + var c = Math.cos(angle); + var s = Math.sin(angle); + var result = identity(); + result[5] = c; + result[6] = s; + result[9] = -s; + result[10] = c; + return result; + } + + private static function rotationY(angle:Float):Array + { + var c = Math.cos(angle); + var s = Math.sin(angle); + var result = identity(); + result[0] = c; + result[2] = -s; + result[8] = s; + result[10] = c; + return result; + } + + private static function translation(x:Float, y:Float, z:Float):Array + { + var result = identity(); + result[12] = x; + result[13] = y; + result[14] = z; + return result; + } +} diff --git a/tests/vulkan-smoke/project.xml b/tests/vulkan-smoke/project.xml new file mode 100644 index 0000000000..ef66f4b29a --- /dev/null +++ b/tests/vulkan-smoke/project.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/tools/CommandLineTools.hx b/tools/CommandLineTools.hx index 0d3e63f448..67f27f7920 100644 --- a/tools/CommandLineTools.hx +++ b/tools/CommandLineTools.hx @@ -420,8 +420,7 @@ class CommandLineTools publishProject(); case "installer", "copy-if-newer": - - // deprecated? + // deprecated? default: Log.error("'" + command + "' is not a valid command"); @@ -511,7 +510,7 @@ class CommandLineTools case LINUX: var arguments = Sys.args(); - if (System.hostArchitecture == ARMV7 ) + if (System.hostArchitecture == ARMV7) { untyped $loader.path = $array(path + "LinuxArm/", $loader.path); } @@ -600,19 +599,16 @@ class CommandLineTools platform = new AndroidPlatform(command, project, targetFlags); case BLACKBERRY: - - // platform = new BlackBerryPlatform (command, project, targetFlags); + // platform = new BlackBerryPlatform (command, project, targetFlags); case IOS: platform = new IOSPlatform(command, project, targetFlags); case TIZEN: - - // platform = new TizenPlatform (command, project, targetFlags); + // platform = new TizenPlatform (command, project, targetFlags); case WEBOS: - - // platform = new WebOSPlatform (command, project, targetFlags); + // platform = new WebOSPlatform (command, project, targetFlags); case WINDOWS: platform = new WindowsPlatform(command, project, targetFlags); @@ -788,14 +784,22 @@ class CommandLineTools { var commands = [ - "config" => "Display or set command-line configuration values", "create" => "Create a new project or extension using templates", - "clean" => "Clean the specified project and target", "update" => "Copy assets for the specified project and target", - "build" => "Compile and package for the specified project and target", "run" => "Install and run for the specified project and target", - "test" => "Update, build and run in one command", "help" => "Show this information", - "trace" => "Trace output for the specifed project and target", "deploy" => "Archive and upload builds", - "display" => "Display information for the specified project and target", "rebuild" => "Recompile native binaries for libraries", - "install" => "Install a library from haxelib, plus dependencies", "remove" => "Remove a library from haxelib", - "upgrade" => "Upgrade a library from haxelib", "setup" => "Setup " + defaultLibraryName + " or a specific platform" + "config" => "Display or set command-line configuration values", + "create" => "Create a new project or extension using templates", + "clean" => "Clean the specified project and target", + "update" => "Copy assets for the specified project and target", + "build" => "Compile and package for the specified project and target", + "run" => "Install and run for the specified project and target", + "test" => "Update, build and run in one command", + "help" => "Show this information", + "trace" => "Trace output for the specifed project and target", + "deploy" => "Archive and upload builds", + "display" => "Display information for the specified project and target", + "rebuild" => "Recompile native binaries for libraries", + "install" => "Install a library from haxelib, plus dependencies", + "remove" => "Remove a library from haxelib", + "upgrade" => "Upgrade a library from haxelib", + "setup" => "Setup " + defaultLibraryName + " or a specific platform" ]; @@ -1841,7 +1845,9 @@ class CommandLineTools var projectDirectory = Path.directory(projectFile); var localRepository = Path.combine(projectDirectory, ".haxelib"); - if (FileSystem.exists(localRepository) && FileSystem.isDirectory(localRepository) && StringTools.startsWith(path, localRepository)) + if (FileSystem.exists(localRepository) + && FileSystem.isDirectory(localRepository) + && StringTools.startsWith(path, localRepository)) { args.push("-nolocalrepocheck"); } diff --git a/tools/RunScript.hx b/tools/RunScript.hx index 8b6060829e..4dcd97b71f 100644 --- a/tools/RunScript.hx +++ b/tools/RunScript.hx @@ -27,7 +27,16 @@ class RunScript if (!rebuildBinaries) return; - var platforms = ["Windows", "Mac", "Mac64", "MacArm64", "Linux", "Linux64", "LinuxArm", "LinuxArm64"]; + var platforms = [ + "Windows", + "Mac", + "Mac64", + "MacArm64", + "Linux", + "Linux64", + "LinuxArm", + "LinuxArm64" + ]; for (platform in platforms) { @@ -208,17 +217,17 @@ class RunScript if (args.indexOf("-eval") >= 0) { args.remove("-eval"); - Log.info("Experimental: executing `lime " + args.slice(0, args.length - 1).join(" ") - + "` using Eval (https://haxe.org/blog/eval/)"); + Log.info("Experimental: executing `lime " + args.slice(0, args.length - 1).join(" ") + "` using Eval (https://haxe.org/blog/eval/)"); var args = [ - "-D", "lime", - "-cp", toolsDirectory, - "-cp", Path.combine(toolsDirectory, "platforms"), - "-cp", Path.combine(limeDirectory, "src"), - "-lib", "format", - "-lib", "hxp", - "--run", "CommandLineTools"].concat(args); + "-D", "lime", + "-cp", toolsDirectory, + "-cp", Path.combine(toolsDirectory, "platforms"), + "-cp", Path.combine(limeDirectory, "src"), + "-lib", "format", + "-lib", "hxp", + "--run", "CommandLineTools" + ].concat(args); Sys.exit(runCommand("", "haxe", args)); } diff --git a/tools/SVGExport.hx b/tools/SVGExport.hx index 4bb62d0bdf..f83d2e23e9 100644 --- a/tools/SVGExport.hx +++ b/tools/SVGExport.hx @@ -79,7 +79,7 @@ class SVGExport case LINUX: var arguments = Sys.args(); - if ( System.hostArchitecture == ARMV7 ) + if (System.hostArchitecture == ARMV7) { untyped $loader.path = $array(path + "LinuxArm/", $loader.path); } diff --git a/tools/mpeg/audio/MpegAudioReader.hx b/tools/mpeg/audio/MpegAudioReader.hx index 91ba3f830b..81a0279828 100644 --- a/tools/mpeg/audio/MpegAudioReader.hx +++ b/tools/mpeg/audio/MpegAudioReader.hx @@ -102,14 +102,14 @@ class MpegAudioReader frames.push(frame); case Info(_): - // Discard info tag. + // Discard info tag. case GaplessInfo(giEncoderDelay, giEndPadding): encoderDelay = giEncoderDelay; endPadding = giEndPadding; case Unknown(_): - // Discard unknown bytes + // Discard unknown bytes case End: break; diff --git a/tools/platforms/AndroidPlatform.hx b/tools/platforms/AndroidPlatform.hx index ebdad5f110..2887c6a23c 100644 --- a/tools/platforms/AndroidPlatform.hx +++ b/tools/platforms/AndroidPlatform.hx @@ -162,8 +162,16 @@ class AndroidPlatform extends PlatformTarget for (architecture in architectures) { var minSDKVer = project.config.getInt("android.minimum-sdk-version", 21); - //PLATFORM define needed for older ndk and gcc toolchain - var haxeParams = [hxml, "-D", "android", "-D", 'PLATFORM_NUMBER=$minSDKVer', "-D", 'PLATFORM=android-$minSDKVer']; + // PLATFORM define needed for older ndk and gcc toolchain + var haxeParams = [ + hxml, + "-D", + "android", + "-D", + 'PLATFORM_NUMBER=$minSDKVer', + "-D", + 'PLATFORM=android-$minSDKVer' + ]; var cppParams = ["-Dandroid", '-DPLATFORM_NUMBER=$minSDKVer', '-DPLATFORM=android-$minSDKVer']; var path = sourceSet + "/jniLibs/armeabi"; var suffix = ".so"; @@ -301,7 +309,8 @@ class AndroidPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); @@ -357,8 +366,7 @@ class AndroidPlatform extends PlatformTarget public override function rebuild():Void { - var armv5 = (/*command == "rebuild" ||*/ - ArrayTools.containsValue(project.architectures, Architecture.ARMV5) + var armv5 = (/*command == "rebuild" ||*/ ArrayTools.containsValue(project.architectures, Architecture.ARMV5) || ArrayTools.containsValue(project.architectures, Architecture.ARMV6)); var armv7 = (command == "rebuild" || ArrayTools.containsValue(project.architectures, Architecture.ARMV7)); var arm64 = (command == "rebuild" || ArrayTools.containsValue(project.architectures, Architecture.ARM64)); @@ -403,6 +411,8 @@ class AndroidPlatform extends PlatformTarget // initialize (project); + prepareEmbeddedAssets(); + var destination = targetDirectory + "/bin"; var sourceSet = destination + "/app/src/main"; System.mkdir(sourceSet); @@ -441,31 +451,47 @@ class AndroidPlatform extends PlatformTarget context.ANDROID_ENABLE_JETIFIER = project.config.getString("android.enableJetifier", "false"); context.ANDROID_GRADLE_PROPERTIES = project.config.getKeyValueArray("android.gradle-properties"); context.ANDROID_DISPLAY_CUTOUT = project.config.getString("android.layoutInDisplayCutoutMode", "default"); + context.ANDROID_VULKAN = project.window.renderType != null && project.window.renderType.toLowerCase() == "vulkan"; + context.ANDROID_VULKAN_REQUIRED = project.config.getBool("android.vulkan-required", true); + context.ANDROID_VULKAN_VERSION = project.config.getString("android.vulkan-version", "0x400003"); - context.ANDROID_MANIFEST = project.config.getKeyValueArray("android.manifest", { - "android:versionCode": project.meta.buildNumber, - "android:versionName": project.meta.version, - "android:installLocation": project.config.getString("android.install-location", "auto") - }); + context.ANDROID_MANIFEST = project.config.getKeyValueArray("android.manifest", + { + "android:versionCode": project.meta.buildNumber, + "android:versionName": project.meta.version, + "android:installLocation": project.config.getString("android.install-location", "auto") + }); context.ANDROID_MANIFEST_CHILDREN = project.config.get("android.manifest").xmlChildren; - context.ANDROID_APPLICATION = project.config.getKeyValueArray("android.application", { - "android:label": project.meta.title, - "android:allowBackup": "true", - "android:theme": "@android:style/Theme.NoTitleBar" + (project.window.fullscreen ? ".Fullscreen" : ""), - "android:hardwareAccelerated": "true", - "android:allowNativeHeapPointerTagging": context.ANDROID_TARGET_SDK_VERSION >= 30 ? "false" : null - }); + context.ANDROID_APPLICATION = project.config.getKeyValueArray("android.application", + { + "android:label": project.meta.title, + "android:allowBackup": "true", + "android:theme": "@android:style/Theme.NoTitleBar" + (project.window.fullscreen ? ".Fullscreen" : ""), + "android:hardwareAccelerated": "true", + "android:allowNativeHeapPointerTagging": context.ANDROID_TARGET_SDK_VERSION >= 30 ? "false" : null + }); context.ANDROID_APPLICATION_CHILDREN = project.config.get("android.application").xmlChildren; - context.ANDROID_ACTIVITY = project.config.getKeyValueArray("android.activity", { - "android:name": "MainActivity", - "android:exported": "true", - "android:launchMode": "singleTask", - "android:label": project.meta.title, - "android:configChanges": project.config.getArrayString("android.configChanges", - ["layoutDirection", "locale", "orientation", "uiMode", "screenLayout", "screenSize", "smallestScreenSize", "keyboard", "keyboardHidden", "navigation"]) - .join("|"), - "android:screenOrientation": project.window.orientation == PORTRAIT ? "sensorPortrait" : (project.window.orientation == LANDSCAPE ? "sensorLandscape" : null) - }); + context.ANDROID_ACTIVITY = project.config.getKeyValueArray("android.activity", + { + "android:name": "MainActivity", + "android:exported": "true", + "android:launchMode": "singleTask", + "android:label": project.meta.title, + "android:configChanges": project.config.getArrayString("android.configChanges", + [ + "layoutDirection", + "locale", + "orientation", + "uiMode", + "screenLayout", + "screenSize", + "smallestScreenSize", + "keyboard", + "keyboardHidden", + "navigation" + ]).join("|"), + "android:screenOrientation": project.window.orientation == PORTRAIT ? "sensorPortrait" : (project.window.orientation == LANDSCAPE ? "sensorLandscape" : null) + }); context.ANDROID_ACTIVITY_CHILDREN = project.config.get("android.activity").xmlChildren; context.ANDROID_ACCEPT_FILE_INTENT = project.config.getArrayString("android.accept-file-intent", []); @@ -539,9 +565,7 @@ class AndroidPlatform extends PlatformTarget } } } - catch (e:Dynamic) - { - } + catch (e:Dynamic) {} } if (Reflect.hasField(context, "KEY_STORE")) context.KEY_STORE = StringTools.replace(context.KEY_STORE, "\\", "\\\\"); @@ -601,7 +625,7 @@ class AndroidPlatform extends PlatformTarget && !context.HAS_ICON) { context.HAS_ICON = true; - context.ANDROID_APPLICATION.push({ key: "android:icon", value: "@drawable/icon" }); + context.ANDROID_APPLICATION.push({key: "android:icon", value: "@drawable/icon"}); } } diff --git a/tools/platforms/FlashPlatform.hx b/tools/platforms/FlashPlatform.hx index 7fd57cd39e..e2fa792214 100644 --- a/tools/platforms/FlashPlatform.hx +++ b/tools/platforms/FlashPlatform.hx @@ -173,7 +173,8 @@ class FlashPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); @@ -312,21 +313,20 @@ class FlashPlatform extends PlatformTarget } /*private function getIcon (size:Int, targetPath:String):Void { - - var icon = icons.findIcon (size, size); - - if (icon != "") { - - System.copyIfNewer (icon, targetPath); - - } else { - - icons.updateIcon (size, size, targetPath); - - } - - }*/ - + + var icon = icons.findIcon (size, size); + + if (icon != "") { + + System.copyIfNewer (icon, targetPath); + + } else { + + icons.updateIcon (size, size, targetPath); + + } + + }*/ @ignore public override function install():Void {} @ignore public override function rebuild():Void {} diff --git a/tools/platforms/HTML5Platform.hx b/tools/platforms/HTML5Platform.hx index e998836661..498b7cb8b8 100644 --- a/tools/platforms/HTML5Platform.hx +++ b/tools/platforms/HTML5Platform.hx @@ -209,7 +209,8 @@ class HTML5Platform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); diff --git a/tools/platforms/IOSPlatform.hx b/tools/platforms/IOSPlatform.hx index dc9170417c..b5e5931a44 100644 --- a/tools/platforms/IOSPlatform.hx +++ b/tools/platforms/IOSPlatform.hx @@ -409,7 +409,7 @@ class IOSPlatform extends PlatformTarget if (allowInsecureHTTP != "*" && allowInsecureHTTP != "true") { - var sites:Array<{domain: String}> = []; + var sites:Array<{domain:String}> = []; if (allowInsecureHTTP != "false") { @@ -446,7 +446,8 @@ class IOSPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); @@ -523,6 +524,8 @@ class IOSPlatform extends PlatformTarget // manifest.type = AssetType.TEXT; // project.assets.push (manifest); + prepareEmbeddedAssets(); + var context = generateContext(); context.OUTPUT_DIR = targetDirectory; @@ -865,7 +868,6 @@ class IOSPlatform extends PlatformTarget context.HAS_LAUNCH_IMAGE = has_launch_image; }*/ - @ignore public override function install():Void {} @ignore public override function trace():Void {} diff --git a/tools/platforms/LinuxPlatform.hx b/tools/platforms/LinuxPlatform.hx index b23644f544..0bccbbc624 100644 --- a/tools/platforms/LinuxPlatform.hx +++ b/tools/platforms/LinuxPlatform.hx @@ -122,7 +122,9 @@ class LinuxPlatform extends PlatformTarget for (architecture in project.architectures) { - if (!targetFlags.exists("32") && !targetFlags.exists("x86_32") && (architecture == Architecture.X64 || architecture == Architecture.ARM64)) + if (!targetFlags.exists("32") + && !targetFlags.exists("x86_32") + && (architecture == Architecture.X64 || architecture == Architecture.ARM64)) { is64 = true; } @@ -198,7 +200,8 @@ class LinuxPlatform extends PlatformTarget } else { - ProjectHelper.copyLibrary(project, ndll, "Linux" + (( System.hostArchitecture == ARMV7 || System.hostArchitecture == ARM64)?"Arm":"") + (is64 ? "64" : ""), "", + ProjectHelper.copyLibrary(project, ndll, + "Linux" + ((System.hostArchitecture == ARMV7 || System.hostArchitecture == ARM64) ? "Arm" : "") + (is64 ? "64" : ""), "", (ndll.haxelib != null && (ndll.haxelib.name == "hxcpp" || ndll.haxelib.name == "hxlibc")) ? ".dll" : ".ndll", applicationDirectory, project.debug, targetSuffix); @@ -212,9 +215,13 @@ class LinuxPlatform extends PlatformTarget if (noOutput) return; - NekoHelper.createExecutable(project.templatePaths, "linux" + (( System.hostArchitecture == ARMV7 || System.hostArchitecture == ARM64)?"Arm":"") + (is64 ? "64" : ""), targetDirectory + "/obj/ApplicationMain.n", executablePath); + NekoHelper.createExecutable(project.templatePaths, + "linux" + + ((System.hostArchitecture == ARMV7 || System.hostArchitecture == ARM64) ? "Arm" : "") + + (is64 ? "64" : ""), + targetDirectory + + "/obj/ApplicationMain.n", executablePath); NekoHelper.copyLibraries(project.templatePaths, "linux" + (is64 ? "64" : ""), applicationDirectory); - } else if (targetType == "hl") { @@ -230,12 +237,15 @@ class LinuxPlatform extends PlatformTarget var command = [ compiler, "-O3", - "-o", executablePath, + "-o", + executablePath, "-std=c11", "-Wl,-rpath,$ORIGIN", - "-I", Path.combine(targetDirectory, "obj"), + "-I", + Path.combine(targetDirectory, "obj"), Path.combine(targetDirectory, "obj/ApplicationMain.c"), - "-L", applicationDirectory, + "-L", + applicationDirectory, // gcc 14 and clang 22 made incompatible-pointer-types an // error instead of a warning, but it's required for // assignment to Dynamic in Haxe @@ -416,7 +426,7 @@ class LinuxPlatform extends PlatformTarget { // var project = project.clone (); - if(targetFlags.exists('rpi')) + if (targetFlags.exists('rpi')) { project.haxedefs.set("rpi", 1); } @@ -441,7 +451,8 @@ class LinuxPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); @@ -473,7 +484,7 @@ class LinuxPlatform extends PlatformTarget { var commands:Array> = []; - if (targetFlags.exists('rpi') && System.hostArchitecture == ARM64 ) + if (targetFlags.exists('rpi') && System.hostArchitecture == ARM64) { commands.push([ "-Dlinux", @@ -506,14 +517,9 @@ class LinuxPlatform extends PlatformTarget // TODO: Support single binary commands.push(["-Dlinux", "-DHXCPP_M64", "-Dhashlink"]); } - else if (System.hostArchitecture == ARM64 ) + else if (System.hostArchitecture == ARM64) { - commands.push([ - "-Dlinux", - "-Dtoolchain=linux", - "-DBINDIR=LinuxArm64", - "-DHXCPP_ARM64", - ]); + commands.push(["-Dlinux", "-Dtoolchain=linux", "-DBINDIR=LinuxArm64", "-DHXCPP_ARM64",]); } else { @@ -567,6 +573,8 @@ class LinuxPlatform extends PlatformTarget // project = project.clone (); // initialize (project); + prepareEmbeddedAssets(); + if (project.targetFlags.exists("xml")) { project.haxeflags.push("-xml " + targetDirectory + "/types.xml"); @@ -588,7 +596,9 @@ class LinuxPlatform extends PlatformTarget if (ndll.path == null || ndll.path == "") { - context.ndlls[i].path = NDLL.getLibraryPath(ndll, "Linux" + (( System.hostArchitecture == ARMV7 || System.hostArchitecture == ARM64) ? "Arm" : "") + (is64 ? "64" : ""), "lib", ".a", project.debug); + context.ndlls[i].path = NDLL.getLibraryPath(ndll, + "Linux" + ((System.hostArchitecture == ARMV7 || System.hostArchitecture == ARM64) ? "Arm" : "") + (is64 ? "64" : ""), "lib", ".a", + project.debug); } } } diff --git a/tools/platforms/MacPlatform.hx b/tools/platforms/MacPlatform.hx index a90383a147..c883bbf68b 100644 --- a/tools/platforms/MacPlatform.hx +++ b/tools/platforms/MacPlatform.hx @@ -231,13 +231,16 @@ class MacPlatform extends PlatformTarget // if we ever support ARM or Universal binaries, this will // need to be handled differently. var command = [ - "arch", "-x86_64", + "arch", + "-x86_64", compiler, "-O3", - "-o", executablePath, + "-o", + executablePath, "-std=c11", "-Wl,-rpath,@executable_path", - "-I", Path.combine(targetDirectory, "obj"), + "-I", + Path.combine(targetDirectory, "obj"), Path.combine(targetDirectory, "obj/ApplicationMain.c"), // gcc 14 and clang 22 made incompatible-pointer-types an // error instead of a warning, but it's required for @@ -264,7 +267,12 @@ class MacPlatform extends PlatformTarget // when launched inside an .app file, the executable // can't find the library files unless we tell // it to search specifically from @executable_path - System.runCommand("", "install_name_tool", ["-change", Path.withoutDirectory(file), "@executable_path/" + Path.withoutDirectory(file), executablePath]); + System.runCommand("", "install_name_tool", [ + "-change", + Path.withoutDirectory(file), + "@executable_path/" + Path.withoutDirectory(file), + executablePath + ]); default: } } @@ -367,7 +375,10 @@ class MacPlatform extends PlatformTarget } } - if (System.hostPlatform != WINDOWS && targetType != "nodejs" && targetType != "java" && sys.FileSystem.exists(executablePath)) + if (System.hostPlatform != WINDOWS + && targetType != "nodejs" + && targetType != "java" + && sys.FileSystem.exists(executablePath)) { System.runCommand("", "chmod", ["755", executablePath]); } @@ -410,7 +421,8 @@ class MacPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); @@ -520,6 +532,8 @@ class MacPlatform extends PlatformTarget // project = project.clone (); + prepareEmbeddedAssets(); + if (project.targetFlags.exists("xml")) { project.haxeflags.push("-xml " + targetDirectory + "/types.xml"); @@ -630,10 +644,7 @@ class MacPlatform extends PlatformTarget // these are the known directories where Homebrew installs its dependencies // we may need to add more in the future, but this seems to be enough for now - var homebrewDirs = [ - "/usr/local/opt/", - "/usr/local/Cellar/" - ]; + var homebrewDirs = ["/usr/local/opt/", "/usr/local/Cellar/"]; // first, collect all executables, hdlls, and dylibs that were built // by BuildHashlink.xml @@ -698,7 +709,10 @@ class MacPlatform extends PlatformTarget continue; } } - if (Lambda.exists(homebrewDirs, function(dirPath:String):Bool { return StringTools.startsWith(resolvedLibPath, dirPath); })) + if (Lambda.exists(homebrewDirs, function(dirPath:String):Bool + { + return StringTools.startsWith(resolvedLibPath, dirPath); + })) { homebrewDependencyPaths.push(libPath); pathsToSearchForHomebrewDependencies.push(resolvedLibPath); diff --git a/tools/platforms/TVOSPlatform.hx b/tools/platforms/TVOSPlatform.hx index 159c531ebe..39e0b629d0 100644 --- a/tools/platforms/TVOSPlatform.hx +++ b/tools/platforms/TVOSPlatform.hx @@ -357,7 +357,8 @@ class TVOSPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); @@ -433,6 +434,8 @@ class TVOSPlatform extends PlatformTarget // manifest.type = AssetType.TEXT; // project.assets.push (manifest); + prepareEmbeddedAssets(); + var context = generateContext(); context.OUTPUT_DIR = targetDirectory; @@ -636,7 +639,6 @@ class TVOSPlatform extends PlatformTarget context.HAS_LAUNCH_IMAGE = has_launch_image; }*/ - @ignore public override function install():Void {} @ignore public override function trace():Void {} diff --git a/tools/platforms/TizenPlatform.hx b/tools/platforms/TizenPlatform.hx index 8ecb2d082f..5aff46f681 100644 --- a/tools/platforms/TizenPlatform.hx +++ b/tools/platforms/TizenPlatform.hx @@ -203,6 +203,8 @@ class TizenPlatform extends PlatformTarget asset.resourceName = "../res/" + asset.resourceName; } + prepareEmbeddedAssets(); + if (project.targetFlags.exists("xml")) { project.haxeflags.push("-xml " + targetDirectory + "/types.xml"); diff --git a/tools/platforms/WebAssemblyPlatform.hx b/tools/platforms/WebAssemblyPlatform.hx index dbf8ad19f4..47e30643bc 100644 --- a/tools/platforms/WebAssemblyPlatform.hx +++ b/tools/platforms/WebAssemblyPlatform.hx @@ -118,7 +118,19 @@ class WebAssemblyPlatform extends PlatformTarget } var hxml = targetDirectory + "/haxe/" + buildType + ".hxml"; - var args = [hxml, "-D", "webassembly", "-D", "wasm", "-D", "emscripten", "-D", "webgl", "-D", "static_link"]; + var args = [ + hxml, + "-D", + "webassembly", + "-D", + "wasm", + "-D", + "emscripten", + "-D", + "webgl", + "-D", + "static_link" + ]; if (Log.verbose) { @@ -135,7 +147,13 @@ class WebAssemblyPlatform extends PlatformTarget project.path(sdkPath); - System.runCommand("", "emcc", ["-c", "-fwasm-exceptions", targetDirectory + "/obj/Main.cpp", "-o", targetDirectory + "/obj/Main.o"], true, false, true); + System.runCommand("", "emcc", [ + "-c", + "-fwasm-exceptions", + targetDirectory + "/obj/Main.cpp", + "-o", + targetDirectory + "/obj/Main.o" + ], true, false, true); args = ["Main.o"]; @@ -159,9 +177,7 @@ class WebAssemblyPlatform extends PlatformTarget prefix = "lib"; } - args = args.concat([ - prefix + "ApplicationMain" + (project.debug ? "-debug" : "") + ".a" - ]); + args = args.concat([prefix + "ApplicationMain" + (project.debug ? "-debug" : "") + ".a"]); if (!project.targetFlags.exists("asmjs")) { @@ -188,19 +204,19 @@ class WebAssemblyPlatform extends PlatformTarget } } - // Fix Rendering - args.push("-s"); - args.push("MIN_WEBGL_VERSION=2"); - args.push("-s"); - args.push("MAX_WEBGL_VERSION=2"); + // Fix Rendering + args.push("-s"); + args.push("MIN_WEBGL_VERSION=2"); + args.push("-s"); + args.push("MAX_WEBGL_VERSION=2"); - // Fix GC - args.push("--Wno-limited-postlink-optimizations"); - // https://github.com/HaxeFoundation/hxcpp/blob/767fe94d19a041147c4f65dea02c89cb206a0758/toolchain/emscripten-toolchain.xml#L29-L33 - args.push("-s"); - args.push("BINARYEN_EXTRA_PASSES='--spill-pointers'"); + // Fix GC + args.push("--Wno-limited-postlink-optimizations"); + // https://github.com/HaxeFoundation/hxcpp/blob/767fe94d19a041147c4f65dea02c89cb206a0758/toolchain/emscripten-toolchain.xml#L29-L33 + args.push("-s"); + args.push("BINARYEN_EXTRA_PASSES='--spill-pointers'"); - args.push("-fwasm-exceptions"); + args.push("-fwasm-exceptions"); // set initial size // args.push("-s"); @@ -209,31 +225,32 @@ class WebAssemblyPlatform extends PlatformTarget args.push("-s"); args.push("STACK_SIZE=1MB"); - args.push("-s"); - args.push("FETCH=1"); + args.push("-s"); + args.push("FETCH=1"); // args.push("-s"); // args.push("SAFE_HEAP=1"); if (project.targetFlags.exists("final")) { - args.push("-O3"); + args.push("-O3"); } else if (!project.debug) { - args.push("-O2"); + args.push("-O2"); } else { - args.push("-O1"); + args.push("-O1"); } args.push("-s"); args.push("ALLOW_MEMORY_GROWTH=1"); - if(project.targetFlags.exists("websocket")) { - args.push("-lwebsocket.js"); - } + if (project.targetFlags.exists("websocket")) + { + args.push("-lwebsocket.js"); + } if (project.targetFlags.exists("minify")) { @@ -334,7 +351,8 @@ class WebAssemblyPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); @@ -375,6 +393,8 @@ class WebAssemblyPlatform extends PlatformTarget var destination = targetDirectory + "/bin/"; System.mkdir(destination); + prepareEmbeddedAssets(); + // for (asset in project.assets) { // // if (asset.type == AssetType.FONT) { @@ -447,21 +467,7 @@ class WebAssemblyPlatform extends PlatformTarget // ProjectHelper.recursiveSmartCopyTemplate(project, "webassembly/cpp", targetDirectory + "/obj", context); ProjectHelper.recursiveSmartCopyTemplate(project, "cpp/static", targetDirectory + "/obj", context); - for (asset in project.assets) - { - var path = Path.combine(destination, asset.targetPath); - - if (asset.type == AssetType.TEMPLATE) - { - System.mkdir(Path.directory(path)); - AssetHelper.copyAsset(asset, path, context); - } - else - { - System.mkdir(Path.directory(path)); - AssetHelper.copyAsset(asset, path, context); - } - } + copyProjectAssets(destination); } @ignore public override function install():Void {} diff --git a/tools/platforms/WindowsPlatform.hx b/tools/platforms/WindowsPlatform.hx index f9f9aa58fd..fd59564832 100644 --- a/tools/platforms/WindowsPlatform.hx +++ b/tools/platforms/WindowsPlatform.hx @@ -260,7 +260,15 @@ class WindowsPlatform extends PlatformTarget // start by finding visual studio var programFilesX86 = Sys.getEnv("ProgramFiles(x86)"); var vswhereCommand = programFilesX86 + "\\Microsoft Visual Studio\\Installer\\vswhere.exe"; - var vswhereOutput = System.runProcess("", vswhereCommand, ["-latest", "-products", "*", "-requires", "Microsoft.Component.MSBuild", "-property", "installationPath"]); + var vswhereOutput = System.runProcess("", vswhereCommand, [ + "-latest", + "-products", + "*", + "-requires", + "Microsoft.Component.MSBuild", + "-property", + "installationPath" + ]); var visualStudioPath = StringTools.trim(vswhereOutput); // then, find MSBuild inside visual studio var msBuildPath = visualStudioPath + "\\MSBuild\\Current\\Bin\\MSBuild.exe"; @@ -332,8 +340,7 @@ class WindowsPlatform extends PlatformTarget { ProjectHelper.copyLibrary(project, ndll, "Windows" + (is64 ? "64" : ""), "", ".hdll", applicationDirectory, project.debug, targetSuffix); - ProjectHelper.copyLibrary(project, ndll, "Windows" + (is64 ? "64" : ""), "", ".lib", applicationDirectory, project.debug, - ".lib"); + ProjectHelper.copyLibrary(project, ndll, "Windows" + (is64 ? "64" : ""), "", ".lib", applicationDirectory, project.debug, ".lib"); } else { @@ -378,10 +385,12 @@ class WindowsPlatform extends PlatformTarget command = [ "gcc", "-O3", - "-o", executablePath, + "-o", + executablePath, "-std=c11", "-Wl,-subsystem,windows", - "-I", Path.combine(targetDirectory, "obj"), + "-I", + Path.combine(targetDirectory, "obj"), Path.combine(targetDirectory, "obj/ApplicationMain.c"), "C:/Windows/System32/dbghelp.dll", // gcc 14 and clang 22 made incompatible-pointer-types an @@ -405,13 +414,31 @@ class WindowsPlatform extends PlatformTarget // start by finding visual studio var programFilesX86 = Sys.getEnv("ProgramFiles(x86)"); var vswhereCommand = programFilesX86 + "\\Microsoft Visual Studio\\Installer\\vswhere.exe"; - var vswhereOutput = System.runProcess("", vswhereCommand, ["-latest", "-products", "*", "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "-property", "installationPath"]); + var vswhereOutput = System.runProcess("", vswhereCommand, [ + "-latest", + "-products", + "*", + "-requires", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "-property", + "installationPath" + ]); var visualStudioPath = StringTools.trim(vswhereOutput); var vcvarsallPath = visualStudioPath + "\\VC\\Auxiliary\\Build\\vcvarsall.bat"; // this command sets up the environment variables and things that visual studio requires - var vcvarsallCommand = [vcvarsallPath, "x64"].map(function(arg:String):String { return ~/([&|\(\)<>\^ ])/g.replace(arg, "^$1"); }); + var vcvarsallCommand = [vcvarsallPath, "x64"].map(function(arg:String):String + { + return ~/([&|\(\)<>\^ ])/g.replace(arg, "^$1"); + }); // this command runs the cl.exe c compiler from visual studio - var clCommand = ["cl.exe", "/Ox", "/Fe:" + executablePath, "-I", Path.combine(targetDirectory, "obj"), Path.combine(targetDirectory, "obj/ApplicationMain.c")]; + var clCommand = [ + "cl.exe", + "/Ox", + "/Fe:" + executablePath, + "-I", + Path.combine(targetDirectory, "obj"), + Path.combine(targetDirectory, "obj/ApplicationMain.c") + ]; for (file in System.readDirectory(applicationDirectory)) { switch Path.extension(file) @@ -424,7 +451,10 @@ class WindowsPlatform extends PlatformTarget } clCommand.push("/link"); clCommand.push("/subsystem:windows"); - clCommand = clCommand.map(function(arg:String):String { return ~/([&|\(\)<>\^ ])/g.replace(arg, "^$1"); }); + clCommand = clCommand.map(function(arg:String):String + { + return ~/([&|\(\)<>\^ ])/g.replace(arg, "^$1"); + }); // combine both commands into one command = ["cmd.exe", "/s", "/c", vcvarsallCommand.join(" ") + " && " + clCommand.join(" ")]; } @@ -602,6 +632,8 @@ class WindowsPlatform extends PlatformTarget if (noOutput) return; + IconHelper.createWindowsIcon(icons, Path.combine(targetDirectory + "/obj", "ApplicationMain.ico")); + CPPHelper.compile(project, targetDirectory + "/obj", flags); System.copyFile(targetDirectory + "/obj/ApplicationMain" + (project.debug ? "-debug" : "") + ".exe", executablePath); @@ -630,19 +662,14 @@ class WindowsPlatform extends PlatformTarget if (noOutput) return; + IconHelper.createWindowsIcon(icons, Path.combine(targetDirectory + "/obj", "ApplicationMain.ico")); + CPPHelper.compile(project, targetDirectory + "/obj", flags.concat(["-Dstatic_link"])); + CPPHelper.compile(project, targetDirectory + "/obj", flags, "BuildMain.xml"); System.copyFile(targetDirectory + "/obj/Main" + (project.debug ? "-debug" : "") + ".exe", executablePath); } - - var iconPath = Path.combine(applicationDirectory, "icon.ico"); - - if (IconHelper.createWindowsIcon(icons, iconPath) && System.hostPlatform == WINDOWS) - { - var templates = [Haxelib.getPath(new Haxelib(#if lime "lime" #else "hxp" #end)) + "/templates"].concat(project.templatePaths); - System.runCommand("", System.findTemplate(templates, "bin/ReplaceVistaIcon.exe"), [executablePath, iconPath, "1"], true, true); - } } } } @@ -739,7 +766,8 @@ class WindowsPlatform extends PlatformTarget // modified more recently than the .hxml, then the .hxml cannot be // considered valid anymore. it may cause errors in editors like vscode. if (FileSystem.exists(path) - && (project.projectFilePath == null || !FileSystem.exists(project.projectFilePath) + && (project.projectFilePath == null + || !FileSystem.exists(project.projectFilePath) || (FileSystem.stat(path).mtime.getTime() > FileSystem.stat(project.projectFilePath).mtime.getTime()))) { return File.getContent(path); @@ -784,7 +812,8 @@ class WindowsPlatform extends PlatformTarget if (targetType == "hl") { // default to 64 bit, just like upstream Hashlink releases - if (!targetFlags.exists("32") && !targetFlags.exists("x86_32") + if (!targetFlags.exists("32") + && !targetFlags.exists("x86_32") && (System.hostArchitecture == X64 || targetFlags.exists("64") || targetFlags.exists("x86_64"))) { commands.push(["-Dwindows", "-DHXCPP_M64", "-Dhashlink"]); @@ -796,7 +825,8 @@ class WindowsPlatform extends PlatformTarget } else { - if (!targetFlags.exists("64") && !targetFlags.exists("x86_64") + if (!targetFlags.exists("64") + && !targetFlags.exists("x86_64") && (command == "rebuild" || System.hostArchitecture == X86 || (targetType != "cpp" && targetType != "winrt"))) { if (targetType == "winrt") @@ -813,7 +843,8 @@ class WindowsPlatform extends PlatformTarget // as previous Windows builds. For now, force -64 to be done last // so that it can be debugged in a default "rebuild" - if (!targetFlags.exists("32") && !targetFlags.exists("x86_32") + if (!targetFlags.exists("32") + && !targetFlags.exists("x86_32") && System.hostArchitecture == X64 && (command != "rebuild" || targetType == "cpp" || targetType == "neko" || targetType == "winrt")) { @@ -957,6 +988,8 @@ class WindowsPlatform extends PlatformTarget // project = project.clone (); + prepareEmbeddedAssets(); + if (project.targetFlags.exists("xml")) { project.haxeflags.push("-xml " + targetDirectory + "/types.xml"); @@ -1019,6 +1052,12 @@ class WindowsPlatform extends PlatformTarget } else if (targetType == "cpp") { + var windowsIcons = project.icons; + if (windowsIcons.length == 0) + { + windowsIcons = [new Icon(System.findTemplate(project.templatePaths, "default/icon.svg"))]; + } + context.HAS_ICON = IconHelper.createWindowsIcon(windowsIcons, Path.combine(targetDirectory + "/obj", "ApplicationMain.ico")); ProjectHelper.recursiveSmartCopyTemplate(project, "windows/resource", targetDirectory + "/obj", context); if (project.targetFlags.exists("static")) diff --git a/tools/utils/PlatformSetup.hx b/tools/utils/PlatformSetup.hx index 2ba158cb00..5d64d37e70 100644 --- a/tools/utils/PlatformSetup.hx +++ b/tools/utils/PlatformSetup.hx @@ -366,8 +366,7 @@ class PlatformSetup setupAndroid(); case "blackberry": - - // setupBlackBerry (); + // setupBlackBerry (); case "html5": Log.println("\x1b[0;3mNo additional configuration is required.\x1b[0m"); @@ -392,15 +391,13 @@ class PlatformSetup } case "tizen": - - // setupTizen (); + // setupTizen (); case "webassembly", "wasm", "emscripten": setupWebAssembly(); case "webos": - - // setupWebOS (); + // setupWebOS (); case "electron": setupElectron(); @@ -1236,9 +1233,12 @@ class PlatformSetup public static function setupHL():Void { var message = "Absolute path to a custom version of HashLink."; - if (ConfigHelper.getConfigValue("HL_PATH") == null) { + if (ConfigHelper.getConfigValue("HL_PATH") == null) + { message += " Leave empty to use Lime's default bundled version."; - } else { + } + else + { message += " Leave empty to keep the currently configured version. To restore Lime's default bundled version, run the command: lime config remove HL_PATH"; } getDefineValue("HL_PATH", message); @@ -1274,8 +1274,25 @@ class PlatformSetup "extendedKeyUsage=critical,codeSigning", ].join("\n")); System.runCommand("", "openssl", [ - "req", "-x509", "-newkey", "rsa:4096", "-keyout", key, "-nodes", "-days", "365", "-subj", "/CN=hl-cert", "-outform", "der", "-out", - cert, "-extensions", "v3_req", "-config", openSSLConf + "req", + "-x509", + "-newkey", + "rsa:4096", + "-keyout", + key, + "-nodes", + "-days", + "365", + "-subj", + "/CN=hl-cert", + "-outform", + "der", + "-out", + cert, + "-extensions", + "v3_req", + "-config", + openSSLConf ], true, false, true); System.runCommand("", "sudo", [ "security",