diff --git a/.github/actions/setup-harmony-toolchain/action.yml b/.github/actions/setup-harmony-toolchain/action.yml new file mode 100644 index 0000000000000..b13a29888c03a --- /dev/null +++ b/.github/actions/setup-harmony-toolchain/action.yml @@ -0,0 +1,33 @@ +name: 'Setup Harmony toolchain' +inputs: + version: + description: 'Harmony version' + default: '5.0.0-Release' +runs: + using: 'composite' + steps: + - uses: actions/cache/restore@v4 + id: restore-cache + with: + path: /opt/native + key: harmony-${{ inputs.version }} + + - name: Download Harmony toolchain + if: ${{ !steps.restore-cache.outputs.cache-hit }} + shell: bash + run: | + wget https://repo.huaweicloud.com/openharmony/os/${{ inputs.version }}/ohos-sdk-windows_linux-public.tar.gz + tar -zxvf ohos-sdk-windows_linux-public.tar.gz + mkdir -p /opt + + unzip linux/native*.zip -d /opt + - uses: actions/cache/save@v4 + if: ${{ !steps.restore-cache.outputs.cache-hit }} + with: + path: /opt/native + key: harmony-${{ inputs.version }} + - name: 'Set output vars' + id: final + shell: bash + run: | + echo "HARMONY_NATIVE_SDK=/opt/native" >> $GITHUB_OUTPUT diff --git a/.github/workflows/create-test-plan.py b/.github/workflows/create-test-plan.py index 219a4de10ede1..53ca8fa2b2bf1 100755 --- a/.github/workflows/create-test-plan.py +++ b/.github/workflows/create-test-plan.py @@ -55,6 +55,7 @@ class SdlPlatform(Enum): FreeBSD = "freebsd" NetBSD = "netbsd" NGage = "ngage" + Harmony = "harmony" class Msys2Platform(Enum): @@ -98,6 +99,7 @@ class JobSpec: clang_cl: bool = False gdk: bool = False vita_gles: Optional[VitaGLES] = None + harmony_arch: Optional[str] = None JOB_SPECS = { @@ -141,6 +143,9 @@ class JobSpec: "netbsd": JobSpec(name="NetBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.NetBSD, artifact="SDL-netbsd-x64", ), "freebsd": JobSpec(name="FreeBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.FreeBSD, artifact="SDL-freebsd-x64", ), "ngage": JobSpec(name="N-Gage", os=JobOs.WindowsLatest, platform=SdlPlatform.NGage, artifact="SDL-ngage", ), + "harmony-arm64": JobSpec(name="Harmony (Arm64)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Harmony, artifact="SDL-harmony-arm64", harmony_arch="arm64-v8a"), + "harmony-arm32": JobSpec(name="Harmony (Arm32)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Harmony, artifact="SDL-harmony-arm32", harmony_arch="armeabi-v7a"), + "harmony-x86_64": JobSpec(name="Harmony (x86-64)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Harmony, artifact="SDL-harmony-x86_64", harmony_arch="x86_64"), } @@ -757,6 +762,17 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta job.setup_gage_sdk_path = "C:/ngagesdk" job.cmake_toolchain_file = "C:/ngagesdk/cmake/ngage-toolchain.cmake" job.test_pkg_config = False + case SdlPlatform.Harmony: + job.cmake_arguments.extend(( + f"-DOHOS_ARCH={spec.harmony_arch}", + "-DCMAKE_TOOLCHAIN_FILE=/opt/native/build/cmake/ohos.toolchain.cmake", + "-DCMAKE_PLATFORM_NO_VERSIONED_SONAME=1" + )) + job.shared_lib = SharedLibType.SO + job.static_lib = StaticLibType.A + job.run_tests = False + job.test_pkg_config = False + job.werror = False case _: raise ValueError(f"Unsupported platform={spec.platform}") diff --git a/.github/workflows/generic.yml b/.github/workflows/generic.yml index 083859b341625..1cd6b62411fcf 100644 --- a/.github/workflows/generic.yml +++ b/.github/workflows/generic.yml @@ -51,6 +51,9 @@ jobs: uses: ./.github/actions/setup-msvc-libusb with: arch: ${{ matrix.platform.setup-libusb-arch }} + - name: 'Set up Harmony toolchain' + if: ${{ matrix.platform.platform == 'harmony' }} + uses: ./.github/actions/setup-harmony-toolchain - uses: mymindstorm/setup-emsdk@v14 if: ${{ matrix.platform.platform == 'emscripten' }} with: diff --git a/CMakeLists.txt b/CMakeLists.txt index f66b7726054d4..db9b6f66e21f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1500,7 +1500,47 @@ if(ANDROID) endif() endif() endif() +elseif(OHOS) + # disable warnings from the toolchain + sdl_compile_options(PRIVATE "-Wno-unused-command-line-argument") + sdl_link_dependency(ohos LIBS ace_napi.z hilog_ndk.z ace_ndk.z rawfile.z pixelmap_ndk.z) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/ohos/*.c") + + if(SDL_VIDEO) + set(SDL_VIDEO_DRIVER_OHOS 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/ohos/*.c") + set(HAVE_SDL_VIDEO TRUE) + set(HAVE_VULKAN ON) + set(SDL_VIDEO_VULKAN ON) + set(SDL_VIDEO_RENDER_VULKAN 1) + set(HAVE_RENDER_VULKAN TRUE) + + if(SDL_OPENGLES) + set(SDL_VIDEO_OPENGL_EGL 1) + set(HAVE_OPENGLES TRUE) + set(SDL_VIDEO_OPENGL_ES2 1) + set(SDL_VIDEO_RENDER_OGL_ES2 1) + + sdl_link_dependency(opengles LIBS GLESv2) + endif() + endif() + + set(SDL_LOADSO_DLOPEN 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/loadso/dlopen/*.c") + set(HAVE_SDL_LOADSO TRUE) + + set(SDL_TIME_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c") + set(HAVE_SDL_TIME TRUE) + + set(SDL_TIMER_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c") + set(HAVE_SDL_TIMERS TRUE) + + set(SDL_PTHREADS 1) + + CheckPTHREAD() elseif(EMSCRIPTEN) # Hide noisy warnings that intend to aid mostly during initial stages of porting a new # project. Uncomment at will for verbose cross-compiling -I/../ path info. diff --git a/cmake/macros.cmake b/cmake/macros.cmake index 3ee413c52ff0e..f5adebc3e844f 100644 --- a/cmake/macros.cmake +++ b/cmake/macros.cmake @@ -373,7 +373,7 @@ function(SDL_PrintSummary) message(STATUS "") endif() - if(UNIX AND NOT (ANDROID OR APPLE OR EMSCRIPTEN OR HAIKU OR RISCOS)) + if(UNIX AND NOT (ANDROID OR APPLE OR EMSCRIPTEN OR HAIKU OR RISCOS OR OHOS)) if(NOT (HAVE_X11 OR HAVE_WAYLAND)) if(NOT SDL_UNIX_CONSOLE_BUILD) message(FATAL_ERROR diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake index ea9d73b266135..a73150c95cae3 100644 --- a/cmake/sdlchecks.cmake +++ b/cmake/sdlchecks.cmake @@ -829,7 +829,7 @@ macro(CheckPTHREAD) if(ANDROID OR SDL_PTHREADS_PRIVATE) # the android libc provides built-in support for pthreads, so no # additional linking or compile flags are necessary - elseif(LINUX) + elseif(LINUX OR OHOS) set(PTHREAD_CFLAGS "-D_REENTRANT") set(PTHREAD_LDFLAGS "-pthread") elseif(BSDI) diff --git a/docs/README-ohos.md b/docs/README-ohos.md new file mode 100644 index 0000000000000..5b184300a9c9a --- /dev/null +++ b/docs/README-ohos.md @@ -0,0 +1,28 @@ +OpenHarmony / HarmonyOS +================================================================================ + +Requirements +================================================================================ + +DevEco Studio 5.0.0 or later +https://developer.huawei.com/consumer/en/download + +Harmony OS Development Toolchain 5.0.0 (API 12) or later (Bundled in the DevEco Studio) + + +How the port works +================================================================================ + +- OpenHarmony / Harmony OS apps are based on ArkTS/JS running on the Ark JS runtime, optionally with parts written in C +- We can use the napi and ndk provided by the Harmony SDK to fetch the app window, context and so on. We wrote a simple Harmony shell for SDL, simpily initialize the basic application and the context for SDL library, then runs your app in another thread. (Harmony JS apps only contains one thread, if we runs your app main loop directly in JS, the whole app just freezes) +- This produces a .hap or .app package which can be installed in OpenHarmony and HarmonyOS Emulators (you will need to apply for a certificate to sign the app before testing it on a real HarmonyOS machine) + + +Building the example app and test it (HarmonyOS Emulator) +================================================================================ + +Download the DevEco Studio, and open the ohos-project folder in this repo + +Then, download a emulator in the Device Manager tab, and runs it. + +Click the run button, the IDE will automatically build the app and run it for you, you can act with your app in the emulator window. diff --git a/include/SDL3/SDL_platform_defines.h b/include/SDL3/SDL_platform_defines.h index f7f14be00572e..a8ebbfd7d0fa1 100644 --- a/include/SDL3/SDL_platform_defines.h +++ b/include/SDL3/SDL_platform_defines.h @@ -112,6 +112,11 @@ #undef SDL_PLATFORM_LINUX #endif +#if defined(OHOS) || defined(__OHOS__) +#define SDL_PLATFORM_OHOS 1 +#undef SDL_PLATFORM_LINUX +#endif + #if defined(__unix__) || defined(__unix) || defined(unix) /** diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index 76916aff72b19..ab5ce710a257f 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -269,6 +269,7 @@ #cmakedefine SDL_AUDIO_DRIVER_JACK 1 #cmakedefine SDL_AUDIO_DRIVER_JACK_DYNAMIC @SDL_AUDIO_DRIVER_JACK_DYNAMIC@ #cmakedefine SDL_AUDIO_DRIVER_NETBSD 1 +#cmakedefine SDL_VIDEO_DRIVER_OHOS 1 #cmakedefine SDL_AUDIO_DRIVER_OSS 1 #cmakedefine SDL_AUDIO_DRIVER_PIPEWIRE 1 #cmakedefine SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC @SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC@ @@ -397,6 +398,7 @@ #cmakedefine SDL_VIDEO_DRIVER_N3DS 1 #cmakedefine SDL_VIDEO_DRIVER_NGAGE 1 #cmakedefine SDL_VIDEO_DRIVER_OFFSCREEN 1 +#cmakedefine SDL_VIDEO_DRIVER_OHOS 1 #cmakedefine SDL_VIDEO_DRIVER_PS2 1 #cmakedefine SDL_VIDEO_DRIVER_PSP 1 #cmakedefine SDL_VIDEO_DRIVER_RISCOS 1 diff --git a/ohos-project/.gitignore b/ohos-project/.gitignore new file mode 100644 index 0000000000000..d2ff20141ceed --- /dev/null +++ b/ohos-project/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/ohos-project/AppScope/app.json5 b/ohos-project/AppScope/app.json5 new file mode 100644 index 0000000000000..2a0816969263b --- /dev/null +++ b/ohos-project/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "com.cpp.app", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/ohos-project/AppScope/resources/base/element/string.json b/ohos-project/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000..1080233f01384 --- /dev/null +++ b/ohos-project/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "MyApplication" + } + ] +} diff --git a/ohos-project/AppScope/resources/base/media/background.png b/ohos-project/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000..923f2b3f27e91 Binary files /dev/null and b/ohos-project/AppScope/resources/base/media/background.png differ diff --git a/ohos-project/AppScope/resources/base/media/foreground.png b/ohos-project/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000..959c384b08eb4 Binary files /dev/null and b/ohos-project/AppScope/resources/base/media/foreground.png differ diff --git a/ohos-project/AppScope/resources/base/media/layered_image.json b/ohos-project/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000..fb49920440fb4 --- /dev/null +++ b/ohos-project/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/ohos-project/AppScope/resources/base/media/oforeground.png b/ohos-project/AppScope/resources/base/media/oforeground.png new file mode 100644 index 0000000000000..97014d3e10e5f Binary files /dev/null and b/ohos-project/AppScope/resources/base/media/oforeground.png differ diff --git a/ohos-project/build-profile.json5 b/ohos-project/build-profile.json5 new file mode 100644 index 0000000000000..0d9f5b24aae76 --- /dev/null +++ b/ohos-project/build-profile.json5 @@ -0,0 +1,42 @@ +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "targetSdkVersion": "5.0.1(13)", + "compatibleSdkVersion": "5.0.1(13)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ohos-project/code-linter.json5 b/ohos-project/code-linter.json5 new file mode 100644 index 0000000000000..073990fa45394 --- /dev/null +++ b/ohos-project/code-linter.json5 @@ -0,0 +1,32 @@ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/ohos-project/entry/.gitignore b/ohos-project/entry/.gitignore new file mode 100644 index 0000000000000..e2713a2779c5a --- /dev/null +++ b/ohos-project/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/ohos-project/entry/build-profile.json5 b/ohos-project/entry/build-profile.json5 new file mode 100644 index 0000000000000..5227011597e93 --- /dev/null +++ b/ohos-project/entry/build-profile.json5 @@ -0,0 +1,44 @@ +{ + "apiType": "stageMode", + "buildOption": { + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "-DCMAKE_PLATFORM_NO_VERSIONED_SONAME=1", + "cppFlags": "", + "abiFilters": [ + "arm64-v8a", + "x86_64" + ] + }, + + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + }, + "nativeLib": { + "debugSymbol": { + "strip": true, + "exclude": [] + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ohos-project/entry/hvigorfile.ts b/ohos-project/entry/hvigorfile.ts new file mode 100644 index 0000000000000..c6edcd90486dd --- /dev/null +++ b/ohos-project/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ohos-project/entry/obfuscation-rules.txt b/ohos-project/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000..272efb6ca3f24 --- /dev/null +++ b/ohos-project/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/ohos-project/entry/oh-package-lock.json5 b/ohos-project/entry/oh-package-lock.json5 new file mode 100644 index 0000000000000..ca4ac9f40857d --- /dev/null +++ b/ohos-project/entry/oh-package-lock.json5 @@ -0,0 +1,25 @@ +{ + "meta": { + "stableOrder": true + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "libSDL3.so@src/main/cpp/sdl": "libSDL3.so@src/main/cpp/sdl", + "libentry.so@src/main/cpp/types/libentry": "libentry.so@src/main/cpp/types/libentry" + }, + "packages": { + "libSDL3.so@src/main/cpp/sdl": { + "name": "libSDL3.so", + "version": "1.0.0", + "resolved": "src/main/cpp/sdl", + "registryType": "local" + }, + "libentry.so@src/main/cpp/types/libentry": { + "name": "libentry.so", + "version": "1.0.0", + "resolved": "src/main/cpp/types/libentry", + "registryType": "local" + } + } +} \ No newline at end of file diff --git a/ohos-project/entry/oh-package.json5 b/ohos-project/entry/oh-package.json5 new file mode 100644 index 0000000000000..fb6c90c6ef928 --- /dev/null +++ b/ohos-project/entry/oh-package.json5 @@ -0,0 +1,12 @@ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "libentry.so": "file:./src/main/cpp/types/libentry", + "libSDL3.so": "file:./src/main/cpp/sdl" + } +} diff --git a/ohos-project/entry/src/main/cpp/CMakeLists.txt b/ohos-project/entry/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000000000..bc39e8748e768 --- /dev/null +++ b/ohos-project/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,21 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.5.0) +project(MyApplication10) + +set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +if(DEFINED PACKAGE_FIND_FILE) + include(${PACKAGE_FIND_FILE}) +endif() + +add_subdirectory(../../../../.. external/sdlbin) + +link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) +add_definitions(-DVK_USE_PLATFORM_OHOS=1) +include_directories(${NATIVERENDER_ROOT_PATH} + ${NATIVERENDER_ROOT_PATH}/include + ${SDL3_SOURCE_DIR}/include) + +add_library(entry SHARED napi_init.cpp) +add_dependencies(entry SDL3::SDL3-shared) +target_link_libraries(entry PUBLIC libace_napi.z.so libSDL3.so libvulkan.so libGLESv2.so) diff --git a/ohos-project/entry/src/main/cpp/napi_init.cpp b/ohos-project/entry/src/main/cpp/napi_init.cpp new file mode 100644 index 0000000000000..8730b430e4ed3 --- /dev/null +++ b/ohos-project/entry/src/main/cpp/napi_init.cpp @@ -0,0 +1,167 @@ +#include "SDL3/SDL_assert.h" +#include "SDL3/SDL_init.h" +#include "SDL3/SDL_messagebox.h" +#include "SDL3/SDL_render.h" +#include "SDL3/SDL_timer.h" +#include "SDL3/SDL_video.h" +#include "SDL3/SDL_vulkan.h" +#include "napi/native_api.h" +#include "SDL3/SDL_log.h" +#include "SDL3/SDL_hints.h" +#include +#include +#include +#include +#include + +static napi_value Add(napi_env env, napi_callback_info info) +{ + size_t argc = 2; + napi_value args[2] = {nullptr}; + + napi_get_cb_info(env, info, &argc, args , nullptr, nullptr); + + napi_valuetype valuetype0; + napi_typeof(env, args[0], &valuetype0); + + napi_valuetype valuetype1; + napi_typeof(env, args[1], &valuetype1); + + double value0; + napi_get_value_double(env, args[0], &value0); + + double value1; + napi_get_value_double(env, args[1], &value1); + + napi_value sum; + napi_create_double(env, value0 + value1, &sum); + + SDL_Log("Add invoke!"); + + return sum; + +} + +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr } + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return exports; +} + +float vtxdata[] = { + -0.5f, -0.5f, 0.f, + 0.5f, -0.5f, 0.0f, + 0.0f, 0.5f, 0.0f +}; + +float vtxdata2[] = { + 0.f, 0.f, 1.f, + 0.f, 1.f, 0.f, + 1.f, 0.f, 0.f +}; + +int main() +{ + SDL_SetHint(SDL_HINT_EGL_LIBRARY, "libEGL.so"); + SDL_SetHint(SDL_HINT_OPENGL_LIBRARY, "libGLESv2.so"); + SDL_SetHint(SDL_HINT_OPENGL_ES_DRIVER, "libGLESv2.so"); + 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_Init(SDL_INIT_VIDEO); + SDL_Log("Main func invoke !!!"); + // SDL_GL_LoadLibrary("libGLESv2.so"); + SDL_Log("sdl error: %s", SDL_GetError()); + SDL_Window* win = SDL_CreateWindow("test", 1024, 1024, SDL_WINDOW_OPENGL); + + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "SDL Application", "test!", win); + + auto context = SDL_GL_CreateContext(win); + SDL_GL_MakeCurrent(win, context); + + int frgshader = ((PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader"))(GL_FRAGMENT_SHADER); + int vexshader = ((PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader"))(GL_VERTEX_SHADER); + + auto frag = "varying vec4 v_color;void main() {gl_FragColor = v_color;}"; + ((PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource"))(frgshader, 1, &frag, nullptr); + ((PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader"))(frgshader); + int status = 1; + ((PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv"))(frgshader, GL_COMPILE_STATUS, &status); + int status2 = 1; + ((PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv"))(frgshader, GL_INFO_LOG_LENGTH, &status2); + std::string log(status2, '\0'); + ((PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog"))(frgshader, status2, nullptr, (char*)log.c_str()); + + SDL_Log("test: %d %d %s", status, status2, log.c_str()); + + auto vert = "attribute vec3 pos;attribute vec3 color;varying vec4 v_color;void main() {gl_Position=vec4(pos,1.0);v_color=vec4(color, 1.0);}"; + ((PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource"))(vexshader, 1, &vert, nullptr); + ((PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader"))(vexshader); + ((PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv"))(vexshader, GL_COMPILE_STATUS, &status); + ((PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv"))(vexshader, GL_INFO_LOG_LENGTH, &status2); + std::string log2(status2, '\0'); + ((PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog"))(vexshader, status2, nullptr, (char*)log2.c_str()); + + SDL_Log("test: %d %d %s", status, status2, log2.c_str()); + + auto prog = ((PFNGLCREATEPROGRAMPROC)SDL_GL_GetProcAddress("glCreateProgram"))(); + ((PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader"))(prog, vexshader); + ((PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader"))(prog, frgshader); + ((PFNGLLINKPROGRAMPROC)SDL_GL_GetProcAddress("glLinkProgram"))(prog); + ((PFNGLGETPROGRAMIVPROC)SDL_GL_GetProcAddress("glGetProgramiv"))(prog, GL_LINK_STATUS, &status); + SDL_Log("link: %d", status); + + ((PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader"))(vexshader); + ((PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader"))(frgshader); + + while (true) { + int w, h; + SDL_GetWindowSize(win, &w, &h); + + ((PFNGLVIEWPORTPROC)SDL_GL_GetProcAddress("glViewport"))(0, 0, w, h); + ((PFNGLCLEARPROC)SDL_GL_GetProcAddress("glClear"))(GL_COLOR_BUFFER_BIT); + ((PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram"))(prog); + for (int i = 0; i < 9; i++) { + vtxdata2[i] += 0.01f; + if (vtxdata2[i] >= 1.f) { + vtxdata2[i] = 0.f; + } + } + ((PFNGLVERTEXATTRIBPOINTERPROC)SDL_GL_GetProcAddress("glVertexAttribPointer"))(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)vtxdata); + ((PFNGLENABLEVERTEXATTRIBARRAYPROC)SDL_GL_GetProcAddress("glEnableVertexAttribArray"))(0); + ((PFNGLVERTEXATTRIBPOINTERPROC)SDL_GL_GetProcAddress("glVertexAttribPointer"))(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)vtxdata2); + ((PFNGLENABLEVERTEXATTRIBARRAYPROC)SDL_GL_GetProcAddress("glEnableVertexAttribArray"))(1); + + ((PFNGLDRAWARRAYSPROC)SDL_GL_GetProcAddress("glDrawArrays"))(GL_TRIANGLES, 0, 3); + + SDL_GL_SwapWindow(win); + } + + SDL_Log("glversion: %s", ((PFNGLGETSTRINGPROC)SDL_GL_GetProcAddress("glGetString"))(GL_VERSION)); + + SDL_GL_DestroyContext(context); + + SDL_DestroyWindow(win); + + return 0; +} +EXTERN_C_END + +static napi_module demoModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "entry", + .nm_priv = ((void*)0), + .reserved = { 0 }, +}; + +extern "C" __attribute__((constructor)) void RegisterEntryModule(void) +{ + napi_module_register(&demoModule); +} diff --git a/ohos-project/entry/src/main/cpp/sdl/Index.d.ts b/ohos-project/entry/src/main/cpp/sdl/Index.d.ts new file mode 100644 index 0000000000000..a98f439804ff3 --- /dev/null +++ b/ohos-project/entry/src/main/cpp/sdl/Index.d.ts @@ -0,0 +1,2 @@ +export const sdlCallbackInit: (d) => void; +export const sdlLaunchMain: (lib: string, func: string) => number; diff --git a/ohos-project/entry/src/main/cpp/sdl/oh-package.json5 b/ohos-project/entry/src/main/cpp/sdl/oh-package.json5 new file mode 100644 index 0000000000000..3a8ac3e1b552f --- /dev/null +++ b/ohos-project/entry/src/main/cpp/sdl/oh-package.json5 @@ -0,0 +1,6 @@ +{ + "name": "libSDL3.so", + "types": "./Index.d.ts", + "version": "1.0.0", + "description": "Please describe the basic information." +} diff --git a/ohos-project/entry/src/main/cpp/types/libentry/Index.d.ts b/ohos-project/entry/src/main/cpp/types/libentry/Index.d.ts new file mode 100644 index 0000000000000..e44f3615a4767 --- /dev/null +++ b/ohos-project/entry/src/main/cpp/types/libentry/Index.d.ts @@ -0,0 +1 @@ +export const add: (a: number, b: number) => number; \ No newline at end of file diff --git a/ohos-project/entry/src/main/cpp/types/libentry/oh-package.json5 b/ohos-project/entry/src/main/cpp/types/libentry/oh-package.json5 new file mode 100644 index 0000000000000..ea410725a8826 --- /dev/null +++ b/ohos-project/entry/src/main/cpp/types/libentry/oh-package.json5 @@ -0,0 +1,6 @@ +{ + "name": "libentry.so", + "types": "./Index.d.ts", + "version": "1.0.0", + "description": "Please describe the basic information." +} \ No newline at end of file diff --git a/ohos-project/entry/src/main/ets/entryability/EntryAbility.ets b/ohos-project/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000..f562838e87d9e --- /dev/null +++ b/ohos-project/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,47 @@ +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; +import { KeyboardAvoidMode } from '@ohos.arkui.UIContext'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + windowStage.getMainWindowSync().getUIContext().setKeyboardAvoidMode(KeyboardAvoidMode.OFFSET); + windowStage.getMainWindowSync().setWindowLayoutFullScreen(true) + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/ohos-project/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ohos-project/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000..8e4de99282050 --- /dev/null +++ b/ohos-project/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,16 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/ohos-project/entry/src/main/ets/pages/Index.ets b/ohos-project/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000..6942023db0260 --- /dev/null +++ b/ohos-project/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,51 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import sdltest from 'libSDL3.so'; +import { intl } from '@kit.LocalizationKit'; +import { promptAction } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export class ArkNapiCallback { + onMainLaunch() { + sdltest.sdlLaunchMain("libentry.so", "main") + } + showDialog(title: string, message: string) { + promptAction.showDialog({title: title, message: message, buttons: [{text: 'Ok', color: '#999999'}]}); + } + fetchLocale(): string { + let locale = new intl.Locale(); + return locale.toString(); + } + test(): number { + hilog.info(DOMAIN, 'testTag', 'Call from native !!!'); + focusControl.requestFocus("inputHandler") + let locale = new intl.Locale(); + hilog.info(DOMAIN, 'testTag', locale.toString()); + return 1; + } +} + +let callbackRef: ArkNapiCallback = new ArkNapiCallback() + +@Entry +@Component +struct Index { + aboutToAppear(): void { + sdltest.sdlCallbackInit(callbackRef) + } + + build() { + Column() { + XComponent({ id: 'mainView', type: 'surface', libraryname: 'SDL3' }) + .id('mainView') + TextInput().id('inputHandler').onChange((value: string) => { + hilog.info(DOMAIN, 'testTag', value) + }).onSubmit(() => { + hilog.info(DOMAIN, 'testTag', "submit") + }) + + } + .alignItems(HorizontalAlign.End) + .justifyContent(FlexAlign.End) + } +} diff --git a/ohos-project/entry/src/main/module.json5 b/ohos-project/entry/src/main/module.json5 new file mode 100644 index 0000000000000..b4b367580a64f --- /dev/null +++ b/ohos-project/entry/src/main/module.json5 @@ -0,0 +1,55 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "requestPermissions": [ + ], + + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/ohos-project/entry/src/main/resources/base/element/color.json b/ohos-project/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000..3c712962da3c2 --- /dev/null +++ b/ohos-project/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/ohos-project/entry/src/main/resources/base/element/float.json b/ohos-project/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000..33ea22304f9b1 --- /dev/null +++ b/ohos-project/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} diff --git a/ohos-project/entry/src/main/resources/base/element/string.json b/ohos-project/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000..3f04948b1209a --- /dev/null +++ b/ohos-project/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "SDL Demo" + } + ] +} \ No newline at end of file diff --git a/ohos-project/entry/src/main/resources/base/media/background.png b/ohos-project/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000..923f2b3f27e91 Binary files /dev/null and b/ohos-project/entry/src/main/resources/base/media/background.png differ diff --git a/ohos-project/entry/src/main/resources/base/media/foreground.png b/ohos-project/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000..97014d3e10e5f Binary files /dev/null and b/ohos-project/entry/src/main/resources/base/media/foreground.png differ diff --git a/ohos-project/entry/src/main/resources/base/media/layered_image.json b/ohos-project/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000..fb49920440fb4 --- /dev/null +++ b/ohos-project/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/ohos-project/entry/src/main/resources/base/media/startIcon.png b/ohos-project/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000..205ad8b5a8a42 Binary files /dev/null and b/ohos-project/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ohos-project/entry/src/main/resources/base/profile/backup_config.json b/ohos-project/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000..78f40ae7c494d --- /dev/null +++ b/ohos-project/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ohos-project/entry/src/main/resources/base/profile/main_pages.json b/ohos-project/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000..1898d94f58d61 --- /dev/null +++ b/ohos-project/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/ohos-project/entry/src/main/resources/dark/element/color.json b/ohos-project/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000..79b11c2747aec --- /dev/null +++ b/ohos-project/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/ohos-project/entry/src/mock/Libentry.mock.ets b/ohos-project/entry/src/mock/Libentry.mock.ets new file mode 100644 index 0000000000000..c2171716d040a --- /dev/null +++ b/ohos-project/entry/src/mock/Libentry.mock.ets @@ -0,0 +1,7 @@ +const NativeMock: Record = { + 'add': (a: number, b: number) => { + return a + b; + }, +}; + +export default NativeMock; \ No newline at end of file diff --git a/ohos-project/entry/src/mock/mock-config.json5 b/ohos-project/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000..6540976c9acc8 --- /dev/null +++ b/ohos-project/entry/src/mock/mock-config.json5 @@ -0,0 +1,5 @@ +{ + "libentry.so": { + "source": "src/mock/Libentry.mock.ets" + } +} \ No newline at end of file diff --git a/ohos-project/entry/src/ohosTest/ets/test/Ability.test.ets b/ohos-project/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000..85c78f67579d6 --- /dev/null +++ b/ohos-project/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,35 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ohos-project/entry/src/ohosTest/ets/test/List.test.ets b/ohos-project/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000..794c7dc4ed66b --- /dev/null +++ b/ohos-project/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,5 @@ +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/ohos-project/entry/src/ohosTest/module.json5 b/ohos-project/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000..55725a929993a --- /dev/null +++ b/ohos-project/entry/src/ohosTest/module.json5 @@ -0,0 +1,13 @@ +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ohos-project/entry/src/test/List.test.ets b/ohos-project/entry/src/test/List.test.ets new file mode 100644 index 0000000000000..bb5b5c3731e28 --- /dev/null +++ b/ohos-project/entry/src/test/List.test.ets @@ -0,0 +1,5 @@ +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/ohos-project/entry/src/test/LocalUnit.test.ets b/ohos-project/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000..165fc1615ee86 --- /dev/null +++ b/ohos-project/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,33 @@ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/ohos-project/hvigor/hvigor-config.json5 b/ohos-project/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000..5bebc97554473 --- /dev/null +++ b/ohos-project/hvigor/hvigor-config.json5 @@ -0,0 +1,22 @@ +{ + "modelVersion": "5.0.5", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/ohos-project/hvigorfile.ts b/ohos-project/hvigorfile.ts new file mode 100644 index 0000000000000..f3cb9f1a87a81 --- /dev/null +++ b/ohos-project/hvigorfile.ts @@ -0,0 +1,6 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ohos-project/oh-package-lock.json5 b/ohos-project/oh-package-lock.json5 new file mode 100644 index 0000000000000..c6f99f5c73b06 --- /dev/null +++ b/ohos-project/oh-package-lock.json5 @@ -0,0 +1,27 @@ +{ + "meta": { + "stableOrder": true + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0", + "@ohos/hypium@1.0.21": "@ohos/hypium@1.0.21" + }, + "packages": { + "@ohos/hamock@1.0.0": { + "name": "@ohos/hamock", + "version": "1.0.0", + "integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==", + "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hamock/-/hamock-1.0.0.har", + "registryType": "ohpm" + }, + "@ohos/hypium@1.0.21": { + "name": "@ohos/hypium", + "version": "1.0.21", + "integrity": "sha512-iyKGMXxE+9PpCkqEwu0VykN/7hNpb+QOeIuHwkmZnxOpI+dFZt6yhPB7k89EgV1MiSK/ieV/hMjr5Z2mWwRfMQ==", + "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/hypium-1.0.21.har", + "registryType": "ohpm" + } + } +} \ No newline at end of file diff --git a/ohos-project/oh-package.json5 b/ohos-project/oh-package.json5 new file mode 100644 index 0000000000000..a8aff0c5aff22 --- /dev/null +++ b/ohos-project/oh-package.json5 @@ -0,0 +1,10 @@ +{ + "modelVersion": "5.0.5", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.21", + "@ohos/hamock": "1.0.0" + } +} diff --git a/src/SDL_log.c b/src/SDL_log.c index da55dcf1c19ca..2e159fba7bfc9 100644 --- a/src/SDL_log.c +++ b/src/SDL_log.c @@ -36,6 +36,10 @@ #include #endif +#ifdef SDL_PLATFORM_OHOS +#include +#endif + #include "stdlib/SDL_vacopy.h" // The size of the stack buffer to use for rendering log messages. @@ -120,6 +124,19 @@ static int SDL_android_priority[] = { SDL_COMPILE_TIME_ASSERT(android_priority, SDL_arraysize(SDL_android_priority) == SDL_LOG_PRIORITY_COUNT); #endif // SDL_PLATFORM_ANDROID +#ifdef SDL_PLATFORM_OHOS +static int SDL_ohos_priority[] = { + LOG_DEBUG, + LOG_DEBUG, + LOG_DEBUG, + LOG_DEBUG, + LOG_INFO, + LOG_WARN, + LOG_ERROR, + LOG_FATAL +}; +#endif + static void SDLCALL SDL_LoggingChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { SDL_ResetLogPriorities(); @@ -556,7 +573,7 @@ void SDL_LogMessage(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_ST va_end(ap); } -#ifdef SDL_PLATFORM_ANDROID +#if defined(SDL_PLATFORM_ANDROID) || defined(SDL_PLATFORM_OHOS) static const char *GetCategoryPrefix(int category) { if (category < SDL_LOG_CATEGORY_RESERVED2) { @@ -567,7 +584,7 @@ static const char *GetCategoryPrefix(int category) } return "CUSTOM"; } -#endif // SDL_PLATFORM_ANDROID +#endif void SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) { @@ -751,6 +768,13 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category)); __android_log_write(SDL_android_priority[priority], tag, message); } + #elif defined(SDL_PLATFORM_OHOS) + { + char tag[32]; + + SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category)); + OH_LOG_Print(LOG_APP, SDL_ohos_priority[priority], 0, tag, "%{public}s", message); + } #elif defined(SDL_PLATFORM_APPLE) && (defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT)) /* Technically we don't need Cocoa/UIKit, but that's where this function is defined for now. */ diff --git a/src/audio/SDL_audiotypecvt.c b/src/audio/SDL_audiotypecvt.c index 78c325e577572..75174a9100bcb 100644 --- a/src/audio/SDL_audiotypecvt.c +++ b/src/audio/SDL_audiotypecvt.c @@ -536,9 +536,11 @@ static void SDL_TARGETING("ssse3") SDL_Convert_Swap32_SSSE3(Uint32 *dst, const U // be guarded by the STDC FENV_ACCESS pragma; otherwise, it's undefined // behavior. However, the compiler support for this pragma is bad. #if defined(__clang__) +#ifndef SDL_PLATFORM_OHOS #if __clang_major__ >= 12 #pragma STDC FENV_ACCESS ON #endif +#endif #elif defined(_MSC_VER) #pragma fenv_access (on) #elif defined(__GNUC__) @@ -813,9 +815,11 @@ static void SDL_Convert_Swap32_NEON(Uint32 *dst, const Uint32 *src, int num_samp } #if defined(__clang__) +#ifndef SDL_PLATFORM_OHOS #if __clang_major__ >= 12 #pragma STDC FENV_ACCESS DEFAULT #endif +#endif #elif defined(_MSC_VER) #pragma fenv_access (off) #elif defined(__GNUC__) diff --git a/src/core/ohos/SDL_ohos.c b/src/core/ohos/SDL_ohos.c new file mode 100644 index 0000000000000..ceee68254f788 --- /dev/null +++ b/src/core/ohos/SDL_ohos.c @@ -0,0 +1,513 @@ +#include "SDL_internal.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SDL_PLATFORM_OHOS + +#include "../../video/ohos/SDL_ohoskeyboard.h" +#include "../../video/ohos/SDL_ohostouch.h" +#include "../../video/ohos/SDL_ohosvideo.h" +#include "SDL3/SDL_mutex.h" +#include "SDL_ohos.h" +#include "napi/native_api.h" +#include + +static OHNativeWindow *g_ohosNativeWindow; +static SDL_Mutex *g_ohosPageMutex = NULL; +static OH_NativeXComponent_Callback callback; +static OH_NativeXComponent_MouseEvent_Callback mouseCallback; +static int x, y, wid, hei; +static struct +{ + napi_env env; + napi_threadsafe_function func; + napi_ref interface; +} napiEnv; + +typedef enum +{ + Int, + Long, + Double, + String +} napiArgType; + +typedef struct +{ + napiArgType type; + bool enabled; + union + { + int i; + long long l; + double d; + const char *str; + } data; +} napiCallbackArg; +typedef struct +{ + const char *func; + int argCount; + napiCallbackArg arg[16]; + napiArgType type; + napiCallbackArg ret; + bool returned; +} napiCallbackData; + +void OHOS_windowUpdateAttributes(SDL_Window *w) +{ + w->x = x; + w->y = y; + w->w = wid; + w->h = hei; + + SDL_SetWindowSize(w, wid, hei); +} + +void OHOS_windowDataFill(SDL_Window *w) +{ + w->internal = SDL_calloc(1, sizeof(SDL_WindowData)); + OHOS_windowUpdateAttributes(w); + w->internal->native_window = g_ohosNativeWindow; + + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + + if (_this->windows == NULL) { + _this->windows = w; + } else { + _this->windows->next = w; + w->prev = _this->windows; + } + +#ifdef SDL_VIDEO_OPENGL_EGL + if (w->flags & SDL_WINDOW_OPENGL) { + SDL_LockMutex(g_ohosPageMutex); + if (w->internal->egl_surface == EGL_NO_SURFACE) { + w->internal->egl_surface = SDL_EGL_CreateSurface(_this, w, (NativeWindowType)g_ohosNativeWindow); + } + SDL_UnlockMutex(g_ohosPageMutex); + } +#endif +} +void OHOS_removeWindow(SDL_Window *w) +{ + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + if (_this->windows == w) { + _this->windows = _this->windows->next; + } else { + SDL_Window *curWin = _this->windows; + while (curWin != NULL) { + if (curWin == w) { + if (curWin->next == NULL) { + curWin->prev->next = NULL; + } else { + curWin->prev->next = curWin->next; + curWin->next->prev = curWin->prev; + } + break; + } + curWin = curWin->next; + } + } + +#ifdef SDL_VIDEO_OPENGL_EGL + if (w->flags & SDL_WINDOW_OPENGL) { + SDL_LockMutex(g_ohosPageMutex); + if (w->internal->egl_context) { + SDL_EGL_DestroyContext(_this, w->internal->egl_context); + } + if (w->internal->egl_surface != EGL_NO_SURFACE) { + SDL_EGL_DestroySurface(_this, w->internal->egl_surface); + } + SDL_UnlockMutex(g_ohosPageMutex); + } + SDL_free(w->internal); +#endif +} + +void OHOS_LockPage() +{ + SDL_LockMutex(g_ohosPageMutex); +} +void OHOS_UnlockPage() +{ + SDL_UnlockMutex(g_ohosPageMutex); +} + +int OHOS_FetchWidth() +{ + return wid; +} +int OHOS_FetchHeight() +{ + return hei; +} + +static void sdlJSCallback(napi_env env, napi_value jsCb, void *content, void *data) +{ + napiCallbackData *ar = (napiCallbackData *)data; + + napi_value callb = NULL; + napi_get_reference_value(env, napiEnv.interface, &callb); + napi_value jsMethod = NULL; + napi_get_named_property(env, callb, ar->func, &jsMethod); + + napi_value args[16]; + SDL_Log("[SDL] calling js function %s with %d args", ar->func, ar->argCount); + for (int i = 0; i < ar->argCount; i++) { + if (!ar->arg[i].enabled) { + continue; + } + switch (ar->arg[i].type) { + case Int: + { + napi_create_int32(env, ar->arg[i].data.i, args + i); + break; + } + case Long: + { + napi_create_int64(env, ar->arg[i].data.l, args + i); + break; + } + case Double: + { + napi_create_double(env, ar->arg[i].data.d, args + i); + break; + } + case String: + { + const char* p = ar->arg[i].data.str; int l = 0; + while (*p) { + l++; + p++; + } + napi_create_string_utf8(env, ar->arg[i].data.str, l, args + i); + break; + } + } + } + + napi_value v; + napi_call_function(env, NULL, jsMethod, ar->argCount, args, &v); + switch (ar->type) { + case Int: + { + napi_get_value_int32(env, v, &ar->ret.data.i); + break; + } + case Long: + { + napi_get_value_int64(env, v, (int64_t *)&ar->ret.data.l); + break; + } + case String: + { + size_t stringSize = 0; + napi_get_value_string_utf8(env, v, NULL, 0, &stringSize); + char *value = SDL_malloc(stringSize + 1); + napi_get_value_string_utf8(env, v, value, stringSize + 1, &stringSize); + ar->ret.data.str = value; + break; + } + case Double: + { + napi_get_value_double(env, v, &ar->ret.data.d); + break; + } + } + ar->returned = true; +} + +void OHOS_MessageBox(const char* title, const char* message) +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "showDialog"; + data->argCount = 2; + data->arg[0].type = String; + data->arg[0].enabled = true; + data->arg[0].data.str = title; + data->arg[1].type = String; + data->arg[1].enabled = true; + data->arg[1].data.str = message; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_nonblocking); +} + +const char* OHOS_Locale() +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "fetchLocale"; + data->argCount = 0; + data->type = String; + data->returned = false; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_nonblocking); + + while (!data->returned) {} + + const char* d = data->ret.data.str; + SDL_free(data); + return d; +} + +static napi_value sdlCallbackInit(napi_env env, napi_callback_info info) +{ + napiEnv.env = env; + size_t argc = 1; + napi_value args[1] = { NULL }; + + napi_get_cb_info(env, info, &argc, args, NULL, NULL); + + napi_create_reference(env, args[0], 1, &napiEnv.interface); + + napi_value resName = NULL; + napi_create_string_utf8(env, "SDLThreadSafe", NAPI_AUTO_LENGTH, &resName); + napi_create_threadsafe_function(env, args[0], NULL, resName, 0, 1, NULL, NULL, NULL, sdlJSCallback, &napiEnv.func); + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +typedef struct entrypoint_info_ { + char* libname; + char* func; +} entrypoint_info; +static int sdlLaunchMainInternal(void* reserved) +{ + if (!reserved) { + return -1; + } + entrypoint_info *data = (entrypoint_info*)reserved; + void *lib = dlopen(data->libname, RTLD_LAZY); + void *func = dlsym(lib, data->func); + typedef int (*test)(); + int d = ((test)func)(); + dlclose(lib); + SDL_free(reserved); + + return d; +} + +static SDL_Thread *mainThread; + +static napi_value sdlLaunchMain(napi_env env, napi_callback_info info) +{ + size_t argc = 2; + napi_value args[2] = { NULL, NULL }; + napi_get_cb_info(env, info, &argc, args, NULL, NULL); + + size_t libstringSize = 0; + napi_get_value_string_utf8(env, args[0], NULL, 0, &libstringSize); + char *libname = SDL_malloc(libstringSize + 1); + napi_get_value_string_utf8(env, args[0], libname, libstringSize + 1, &libstringSize); + + size_t fstringSize = 0; + napi_get_value_string_utf8(env, args[1], NULL, 0, &fstringSize); + char *fname = SDL_malloc(fstringSize + 1); + napi_get_value_string_utf8(env, args[1], fname, fstringSize + 1, &fstringSize); + + entrypoint_info *entry = (entrypoint_info*)SDL_malloc(sizeof(entrypoint_info)); + entry->func = fname; + entry->libname = libname; + mainThread = SDL_CreateThread(sdlLaunchMainInternal, "SDL App Thread", entry); + SDL_SetMainReady(); + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +static void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) +{ + SDL_Log("Native window: %p", window); + g_ohosNativeWindow = (OHNativeWindow *)window; + + uint64_t width; + uint64_t height; + double offsetX; + double offsetY; + OH_NativeXComponent_GetXComponentSize(component, window, &width, &height); + OH_NativeXComponent_GetXComponentOffset(component, window, &offsetX, &offsetY); + + SDL_LockMutex(g_ohosPageMutex); + wid = width; + hei = height; + x = (int)offsetX; + y = (int)offsetY; + SDL_UnlockMutex(g_ohosPageMutex); + + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + data->func = "onMainLaunch"; + data->argCount = 0; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_nonblocking); +} +static void OnSurfaceChangedCB(OH_NativeXComponent *component, void *window) +{ + g_ohosNativeWindow = (OHNativeWindow *)window; + + uint64_t width; + uint64_t height; + double offsetX; + double offsetY; + OH_NativeXComponent_GetXComponentSize(component, window, &width, &height); + OH_NativeXComponent_GetXComponentOffset(component, window, &offsetX, &offsetY); + + SDL_LockMutex(g_ohosPageMutex); + wid = width; + hei = height; + x = (int)offsetX; + y = (int)offsetY; + SDL_UnlockMutex(g_ohosPageMutex); + + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + if (_this && _this->windows) { + SDL_Window *win = _this->windows; + OHOS_windowUpdateAttributes(win); + } +} +static void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window) +{ + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + SDL_Window *win = _this->windows; + while (win != NULL) { +#ifdef SDL_VIDEO_OPENGL_EGL + if (win->flags & SDL_WINDOW_OPENGL) { + if (win->internal->egl_context) { + SDL_EGL_DestroyContext(_this, win->internal->egl_context); + } + if (win->internal->egl_surface) { + SDL_EGL_DestroySurface(_this, win->internal->egl_surface); + } + } +#endif + win = win->next; + } +} +static void onKeyEvent(OH_NativeXComponent *component, void *window) +{ + OH_NativeXComponent_KeyEvent *keyEvent = NULL; + SDL_Log("key!"); + if (OH_NativeXComponent_GetKeyEvent(component, &keyEvent) >= 0) { + OH_NativeXComponent_KeyAction action; + OH_NativeXComponent_KeyCode code; + OH_NativeXComponent_EventSourceType sourceType; + + OH_NativeXComponent_GetKeyEventAction(keyEvent, &action); + OH_NativeXComponent_GetKeyEventCode(keyEvent, &code); + OH_NativeXComponent_GetKeyEventSourceType(keyEvent, &sourceType); + + if (sourceType == OH_NATIVEXCOMPONENT_SOURCE_TYPE_KEYBOARD) { + if (OH_NATIVEXCOMPONENT_KEY_ACTION_DOWN == action) { + OHOS_OnKeyDown(code); + } else if (OH_NATIVEXCOMPONENT_KEY_ACTION_UP == action) { + OHOS_OnKeyUp(code); + } + } + } +} + +static void onNativeTouch(OH_NativeXComponent *component, void *window) +{ + OH_NativeXComponent_TouchEvent touchEvent; + OH_NativeXComponent_TouchPointToolType toolType = OH_NATIVEXCOMPONENT_TOOL_TYPE_UNKNOWN; + + OHOS_LockPage(); + OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent); + OH_NativeXComponent_GetTouchPointToolType(component, 0, &toolType); + + for (int i = 0; i < touchEvent.numPoints; i++) { + SDL_OHOSTouchEvent e; + e.timestamp = touchEvent.timeStamp; + // skip assertions + e.deviceId = touchEvent.deviceId + 1; + e.fingerId = touchEvent.touchPoints[i].id; + e.area = touchEvent.touchPoints[i].size; + e.x = touchEvent.touchPoints[i].x / (float)wid; + e.y = touchEvent.touchPoints[i].y / (float)hei; + e.p = touchEvent.touchPoints[i].force; + + switch (touchEvent.touchPoints[i].type) { + case OH_NATIVEXCOMPONENT_DOWN: + e.type = SDL_EVENT_FINGER_DOWN; + break; + case OH_NATIVEXCOMPONENT_MOVE: + e.type = SDL_EVENT_FINGER_MOTION; + break; + case OH_NATIVEXCOMPONENT_UP: + e.type = SDL_EVENT_FINGER_UP; + break; + case OH_NATIVEXCOMPONENT_CANCEL: + case OH_NATIVEXCOMPONENT_UNKNOWN: + e.type = SDL_EVENT_FINGER_CANCELED; + break; + } + + OHOS_OnTouch(e); + } + + OHOS_UnlockPage(); +} +// TODO mouse data +static void onNativeMouse(OH_NativeXComponent *component, void *window) { + onNativeTouch(component, window); +} + +static napi_value SDL_OHOS_NAPI_Init(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + { "sdlCallbackInit", NULL, sdlCallbackInit, NULL, NULL, NULL, napi_default, NULL }, + { "sdlLaunchMain", NULL, sdlLaunchMain, NULL, NULL, NULL, napi_default, NULL } + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + + napi_value exportInstance = NULL; + if (napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) { + return exports; + } + OH_NativeXComponent *nativeXComponent; + if (napi_unwrap(env, exportInstance, (void **)(&nativeXComponent)) != napi_ok) { + return exports; + } + + callback.OnSurfaceCreated = OnSurfaceCreatedCB; + callback.OnSurfaceChanged = OnSurfaceChangedCB; + callback.OnSurfaceDestroyed = OnSurfaceDestroyedCB; + callback.DispatchTouchEvent = onNativeTouch; + OH_NativeXComponent_RegisterCallback(nativeXComponent, &callback); + + mouseCallback.DispatchMouseEvent = onNativeMouse; + OH_NativeXComponent_RegisterMouseEventCallback(nativeXComponent, &mouseCallback); + + OH_NativeXComponent_RegisterKeyEventCallback(nativeXComponent, onKeyEvent); + + g_ohosPageMutex = SDL_CreateMutex(); + + return exports; +} + +napi_module OHOS_NAPI_Module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = NULL, + .nm_register_func = SDL_OHOS_NAPI_Init, + .nm_modname = "SDL3", + .nm_priv = ((void *)0), + .reserved = { 0 }, +}; + +__attribute__((constructor)) void RegisterEntryModule(void) +{ + napi_module_register(&OHOS_NAPI_Module); +} + +#endif diff --git a/src/core/ohos/SDL_ohos.h b/src/core/ohos/SDL_ohos.h new file mode 100644 index 0000000000000..817f805797882 --- /dev/null +++ b/src/core/ohos/SDL_ohos.h @@ -0,0 +1,24 @@ +#ifndef SDL_OHOS_H +#define SDL_OHOS_H + +#include "SDL3/SDL_video.h" +#include "video/SDL_sysvideo.h" +#include + +void OHOS_windowDataFill(SDL_Window* w); +void OHOS_removeWindow(SDL_Window* w); +void OHOS_LockPage(); +void OHOS_UnlockPage(); +int OHOS_FetchWidth(); +int OHOS_FetchHeight(); + +void OHOS_MessageBox(const char* title, const char* message); +const char* OHOS_Locale(); + +typedef struct SDL_VideoData { + SDL_Rect textRect; + int isPaused; + int isPausing; +} SDL_VideoData; + +#endif diff --git a/src/thread/pthread/SDL_systhread.c b/src/thread/pthread/SDL_systhread.c index ae4a94c2e273a..05ad3969560a1 100644 --- a/src/thread/pthread/SDL_systhread.c +++ b/src/thread/pthread/SDL_systhread.c @@ -169,7 +169,7 @@ void SDL_SYS_SetupThread(const char *name) pthread_sigmask(SIG_BLOCK, &mask, 0); #endif -#ifdef PTHREAD_CANCEL_ASYNCHRONOUS +#if defined(PTHREAD_CANCEL_ASYNCHRONOUS) && !defined(SDL_PLATFORM_OHOS) // Allow ourselves to be asynchronously cancelled { int oldstate; diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 42ade5e7d7639..25dbb0c3d5bdd 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -542,6 +542,7 @@ extern VideoBootStrap Emscripten_bootstrap; extern VideoBootStrap OFFSCREEN_bootstrap; extern VideoBootStrap QNX_bootstrap; extern VideoBootStrap OPENVR_bootstrap; +extern VideoBootStrap OHOS_bootstrap; extern bool SDL_UninitializedVideo(void); // Use SDL_OnVideoThread() sparingly, to avoid regressions in use cases that currently happen to work diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 44a0463f4bb2f..c2bbd7de4de42 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -107,6 +107,9 @@ static VideoBootStrap *bootstrap[] = { #ifdef SDL_VIDEO_DRIVER_ANDROID &Android_bootstrap, #endif +#ifdef SDL_VIDEO_DRIVER_OHOS + &OHOS_bootstrap, +#endif #ifdef SDL_VIDEO_DRIVER_PS2 &PS2_bootstrap, #endif diff --git a/src/video/khronos/vulkan/vulkan_ohos.h b/src/video/khronos/vulkan/vulkan_ohos.h new file mode 100644 index 0000000000000..b3e18c19c09d1 --- /dev/null +++ b/src/video/khronos/vulkan/vulkan_ohos.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VULKAN_OHOS_H +#define VULKAN_OHOS_H 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define VK_KHR_OHOS_XCOMPONENT 1 +struct ONativeWindow; + +#define VK_KHR_OHOS_XCOMPONENT_SPEC_VERSION 6 +#define VK_KHR_OHOS_XCOMPONENT_EXTENSION_NAME "VK_OHOS_surface" + +typedef VkFlags VkOHOSXComponentCreateFlagsKHR; + +typedef struct VkOHOSXComponentCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkOHOSXComponentCreateFlagsKHR flags; + struct OHNativeWindow* window; +} VkOHOSXComponentCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateOHOSXComponentKHR)(VkInstance instance, + const VkOHOSXComponentCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pXComponent); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateOHOSXComponentKHR( + VkInstance instance, + const VkOHOSXComponentCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + +#define VK_OHOS_EXTERNAL_MEMORY_OHOS_HARDWARE_BUFFER 1 +struct OHardwareBuffer; + +#define VK_OHOS_EXTERNAL_MEMORY_OHOS_HARDWARE_BUFFER_SPEC_VERSION 3 +#define VK_OHOS_EXTERNAL_MEMORY_OHOS_HARDWARE_BUFFER_EXTENSION_NAME "VK_OHOS_EXTERNAL_MEMORY_OHOS_HARDWARE_BUFFER" + +typedef struct VkOHOSHardwareBufferUsageOHOS { + VkStructureType sType; + void* pNext; + uint64_t ohosHardwareBufferUsage; +} VkOHOSHardwareBufferUsageOHOS; + +typedef struct VkOHOSHardwareBufferPropertiesOHOS { + VkStructureType sType; + void* pNext; + VkDeviceSize allocationSize; + uint32_t memoryTypeBits; +} VkOHOSHardwareBufferPropertiesOHOS; + +typedef struct VkOHOSHardwareBufferFormatPropertiesOHOS { + VkStructureType sType; + void* pNext; + VkFormat format; + uint64_t externalFormat; + VkFormatFeatureFlags formatFeatures; + VkComponentMapping samplerYcbcrConversionComponents; + VkSamplerYcbcrModelConversion suggestedYcbcrModel; + VkSamplerYcbcrRange suggestedYcbcrRange; + VkChromaLocation suggestedXChromaOffset; + VkChromaLocation suggestedYChromaOffset; +} VkOHOSHardwareBufferFormatPropertiesOHOS; + +typedef struct VkImportOHOSHardwareBufferInfoOHOS { + VkStructureType sType; + const void* pNext; + struct OHardwareBuffer* buffer; +} VkImportOHOSHardwareBufferInfoOHOS; + +typedef struct VkMemoryGetOHOSHardwareBufferInfoOHOS { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; +} VkMemoryGetOHOSHardwareBufferInfoOHOS; + +typedef struct VkExternalFormatOHOS { + VkStructureType sType; + void* pNext; + uint64_t externalFormat; +} VkExternalFormatOHOS; + + +typedef VkResult (VKAPI_PTR *PFN_vkGetOHOSHardwareBufferPropertiesOHOS)(VkDevice device, + const struct OHardwareBuffer* buffer, VkOHOSHardwareBufferPropertiesOHOS* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryOHOSHardwareBufferOHOS)(VkDevice device, + const VkMemoryGetOHOSHardwareBufferInfoOHOS* pInfo, struct OHardwareBuffer** pBuffer); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetOHOSHardwareBufferPropertiesOHOS( + VkDevice device, + const struct OHardwareBuffer* buffer, + VkOHOSHardwareBufferPropertiesOHOS* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryOHOSHardwareBufferOHOS( + VkDevice device, + const VkMemoryGetOHOSHardwareBufferInfoOHOS* pInfo, + struct OHardwareBuffer** pBuffer); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/video/ohos/SDL_ohosgl.c b/src/video/ohos/SDL_ohosgl.c new file mode 100644 index 0000000000000..53e13af30ee2d --- /dev/null +++ b/src/video/ohos/SDL_ohosgl.c @@ -0,0 +1,47 @@ +#include "SDL_internal.h" +#ifdef SDL_VIDEO_DRIVER_OHOS +#include "../../core/ohos/SDL_ohos.h" +#include "SDL_ohosvideo.h" + +bool OHOS_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context) +{ + if (window && context) { + return SDL_EGL_MakeCurrent(_this, window->internal->egl_surface, context); + } else { + return SDL_EGL_MakeCurrent(_this, NULL, NULL); + } +} + +SDL_GLContext OHOS_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window) +{ + SDL_GLContext result; + + OHOS_LockPage(); + + OHOS_windowDataFill(window); + result = SDL_EGL_CreateContext(_this, window->internal->egl_surface); + + OHOS_UnlockPage(); + + return result; +} + +bool OHOS_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window) +{ + bool result; + + OHOS_LockPage(); + + result = SDL_EGL_SwapBuffers(_this, window->internal->egl_surface); + + OHOS_UnlockPage(); + + return result; +} + +bool OHOS_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path) +{ + return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType)0, 0); +} + +#endif diff --git a/src/video/ohos/SDL_ohosgl.h b/src/video/ohos/SDL_ohosgl.h new file mode 100644 index 0000000000000..b168dbeb3dd2f --- /dev/null +++ b/src/video/ohos/SDL_ohosgl.h @@ -0,0 +1,9 @@ +#ifdef SDL_VIDEO_DRIVER_OHOS +#include "SDL_ohosvideo.h" + +bool OHOS_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context); +SDL_GLContext OHOS_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window); +bool OHOS_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window); +bool OHOS_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path); + +#endif diff --git a/src/video/ohos/SDL_ohoskeyboard.c b/src/video/ohos/SDL_ohoskeyboard.c new file mode 100644 index 0000000000000..86ee21685dcb1 --- /dev/null +++ b/src/video/ohos/SDL_ohoskeyboard.c @@ -0,0 +1,3148 @@ +#include "SDL3/SDL_scancode.h" +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_OHOS + +#include "../../events/SDL_events_c.h" + +static SDL_Scancode OHOS_Keycodes[] = { + SDL_SCANCODE_UNKNOWN, // KEY_FN + SDL_SCANCODE_AC_HOME, + SDL_SCANCODE_AC_BACK, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_MEDIA_PAUSE, + SDL_SCANCODE_MEDIA_STOP, + SDL_SCANCODE_MEDIA_NEXT_TRACK, + SDL_SCANCODE_MEDIA_PREVIOUS_TRACK, + SDL_SCANCODE_MEDIA_REWIND, + SDL_SCANCODE_UNKNOWN, // KEY_MEDIA_FAST_FORWARD + SDL_SCANCODE_VOLUMEUP, + SDL_SCANCODE_VOLUMEDOWN, + SDL_SCANCODE_POWER, + SDL_SCANCODE_UNKNOWN, // KEY_CAMERA + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_MUTE, + SDL_SCANCODE_MUTE, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_UP + SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_DOWN + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_0, + SDL_SCANCODE_1, + SDL_SCANCODE_2, + SDL_SCANCODE_3, + SDL_SCANCODE_4, + SDL_SCANCODE_5, + SDL_SCANCODE_6, + SDL_SCANCODE_7, + SDL_SCANCODE_8, + SDL_SCANCODE_9, + SDL_SCANCODE_UNKNOWN, // KEY_STAR + SDL_SCANCODE_UNKNOWN, // KEY_POUND + SDL_SCANCODE_UP, + SDL_SCANCODE_DOWN, // KEY_DPAD_DOWN + SDL_SCANCODE_LEFT, // KEY_DPAD_LEFT + SDL_SCANCODE_RIGHT, // KEY_DPAD_RIGHT + SDL_SCANCODE_SELECT, // KEY_DPAD_CENTER + SDL_SCANCODE_A, + SDL_SCANCODE_B, + SDL_SCANCODE_C, + SDL_SCANCODE_D, + SDL_SCANCODE_E, + SDL_SCANCODE_F, + SDL_SCANCODE_G, + SDL_SCANCODE_H, + SDL_SCANCODE_I, + SDL_SCANCODE_J, + SDL_SCANCODE_K, + SDL_SCANCODE_L, + SDL_SCANCODE_M, + SDL_SCANCODE_N, + SDL_SCANCODE_O, + SDL_SCANCODE_P, + SDL_SCANCODE_Q, + SDL_SCANCODE_R, + SDL_SCANCODE_S, + SDL_SCANCODE_T, + SDL_SCANCODE_U, + SDL_SCANCODE_V, + SDL_SCANCODE_W, + SDL_SCANCODE_X, + SDL_SCANCODE_Y, + SDL_SCANCODE_Z, + SDL_SCANCODE_COMMA, + SDL_SCANCODE_PERIOD, + SDL_SCANCODE_LALT, + SDL_SCANCODE_RALT, + SDL_SCANCODE_LSHIFT, + SDL_SCANCODE_RSHIFT, + SDL_SCANCODE_TAB, + SDL_SCANCODE_SPACE, + SDL_SCANCODE_UNKNOWN, // KEY_SYM + SDL_SCANCODE_UNKNOWN, // KEY_EXPLORER + SDL_SCANCODE_UNKNOWN, // KEY_ENVELOPE + SDL_SCANCODE_RETURN, + SDL_SCANCODE_BACKSPACE, + SDL_SCANCODE_GRAVE, + SDL_SCANCODE_MINUS, + SDL_SCANCODE_EQUALS, + SDL_SCANCODE_LEFTBRACKET, + SDL_SCANCODE_RIGHTBRACKET, + SDL_SCANCODE_BACKSLASH, + SDL_SCANCODE_SEMICOLON, + SDL_SCANCODE_APOSTROPHE, + SDL_SCANCODE_SLASH, + SDL_SCANCODE_UNKNOWN, // KEY_AT + SDL_SCANCODE_UNKNOWN, // KEY_PLUS + SDL_SCANCODE_MENU, + SDL_SCANCODE_PAGEUP, + SDL_SCANCODE_PAGEDOWN, + SDL_SCANCODE_ESCAPE, + SDL_SCANCODE_DELETE, + SDL_SCANCODE_LCTRL, + SDL_SCANCODE_RCTRL, + SDL_SCANCODE_CAPSLOCK, + SDL_SCANCODE_SCROLLLOCK, + SDL_SCANCODE_LGUI, // KEY_META_LEFT + SDL_SCANCODE_RGUI, // KEY_META_RIGHT + SDL_SCANCODE_UNKNOWN, // KEY_FUNCTION + SDL_SCANCODE_SYSREQ, + SDL_SCANCODE_PAUSE, // KEY_BREAK + SDL_SCANCODE_HOME, + SDL_SCANCODE_END, + SDL_SCANCODE_INSERT, + SDL_SCANCODE_AC_FORWARD, + SDL_SCANCODE_MEDIA_PLAY, + SDL_SCANCODE_MEDIA_PAUSE, + SDL_SCANCODE_UNKNOWN, // KEY_MEDIA_CLOSE + SDL_SCANCODE_MEDIA_EJECT, + SDL_SCANCODE_MEDIA_RECORD, + SDL_SCANCODE_F1, + SDL_SCANCODE_F2, + SDL_SCANCODE_F3, + SDL_SCANCODE_F4, + SDL_SCANCODE_F5, + SDL_SCANCODE_F6, + SDL_SCANCODE_F7, + SDL_SCANCODE_F8, + SDL_SCANCODE_F9, + SDL_SCANCODE_F10, + SDL_SCANCODE_F11, + SDL_SCANCODE_F12, + SDL_SCANCODE_NUMLOCKCLEAR, + SDL_SCANCODE_KP_0, + SDL_SCANCODE_KP_1, + SDL_SCANCODE_KP_2, + SDL_SCANCODE_KP_3, + SDL_SCANCODE_KP_4, + SDL_SCANCODE_KP_5, + SDL_SCANCODE_KP_6, + SDL_SCANCODE_KP_7, + SDL_SCANCODE_KP_8, + SDL_SCANCODE_KP_9, + SDL_SCANCODE_KP_DIVIDE, + SDL_SCANCODE_KP_MULTIPLY, + SDL_SCANCODE_KP_MINUS, + SDL_SCANCODE_KP_PLUS, + SDL_SCANCODE_KP_PERIOD, + SDL_SCANCODE_KP_COMMA, + SDL_SCANCODE_KP_ENTER, + SDL_SCANCODE_KP_EQUALS, + SDL_SCANCODE_KP_LEFTPAREN, + SDL_SCANCODE_KP_RIGHTPAREN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_VIRTUAL_MULTITASK + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_SLEEP, + SDL_SCANCODE_LANG5, + SDL_SCANCODE_UNKNOWN, // KEY_102ND + SDL_SCANCODE_UNKNOWN, // KEY_RO + SDL_SCANCODE_UNKNOWN, // KEY_KATAKANA + SDL_SCANCODE_UNKNOWN, // KEY_HIRAGANA + SDL_SCANCODE_INTERNATIONAL4, + SDL_SCANCODE_LANG3, + SDL_SCANCODE_INTERNATIONAL5, + SDL_SCANCODE_UNKNOWN, // KEY_LINEFEED + SDL_SCANCODE_UNKNOWN, // KEY_MACRO + SDL_SCANCODE_UNKNOWN, // KEY_PLUSMINUS + SDL_SCANCODE_UNKNOWN, // KEY_SCALE + SDL_SCANCODE_UNKNOWN, // KEY_HANGUEL + SDL_SCANCODE_UNKNOWN, // KEY_HANJA + SDL_SCANCODE_INTERNATIONAL3, + SDL_SCANCODE_UNKNOWN, // KEY_STOP + SDL_SCANCODE_UNKNOWN, // KEY_AGAIN + SDL_SCANCODE_UNKNOWN, // KEY_PROPS + SDL_SCANCODE_UNDO, + SDL_SCANCODE_COPY, + SDL_SCANCODE_UNKNOWN, // KEY_OPEN + SDL_SCANCODE_PASTE, + SDL_SCANCODE_FIND, + SDL_SCANCODE_CUT, + SDL_SCANCODE_HELP, + SDL_SCANCODE_UNKNOWN, // KEY_CALC + SDL_SCANCODE_UNKNOWN, // KEY_FILE + SDL_SCANCODE_AC_BOOKMARKS, + SDL_SCANCODE_MEDIA_NEXT_TRACK, + SDL_SCANCODE_MEDIA_PLAY_PAUSE, + SDL_SCANCODE_MEDIA_PREVIOUS_TRACK, + SDL_SCANCODE_MEDIA_STOP, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_CONFIG + SDL_SCANCODE_UNKNOWN, // KEY_REFRESH + SDL_SCANCODE_UNKNOWN, // KEY_EXIT + SDL_SCANCODE_UNKNOWN, // KEY_EDIT + SDL_SCANCODE_UP, + SDL_SCANCODE_DOWN, + SDL_SCANCODE_UNKNOWN, // KEY_NEW + SDL_SCANCODE_UNKNOWN, // KEY_REDO + SDL_SCANCODE_UNKNOWN, // KEY_CLOSE + SDL_SCANCODE_MEDIA_PLAY, + SDL_SCANCODE_UNKNOWN, // KEY_BASSBOOST + SDL_SCANCODE_PRINTSCREEN, + SDL_SCANCODE_UNKNOWN, // KEY_CHAT + SDL_SCANCODE_UNKNOWN, // KEY_FINANCE + SDL_SCANCODE_UNKNOWN, // KEY_CANCEL + SDL_SCANCODE_UNKNOWN, // KEY_KBDILLUM_TOGGLE + SDL_SCANCODE_DOWN, + SDL_SCANCODE_UP, + SDL_SCANCODE_UNKNOWN, // KEY_SEND + SDL_SCANCODE_UNKNOWN, // KEY_REPLY + SDL_SCANCODE_UNKNOWN, // KEY_FORWARDMAIL + SDL_SCANCODE_UNKNOWN, // KEY_SAVE + SDL_SCANCODE_UNKNOWN, // KEY_DOCUMENTS + SDL_SCANCODE_MEDIA_NEXT_TRACK, + SDL_SCANCODE_MEDIA_PREVIOUS_TRACK, + SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_CYCLE + SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_ZERO + SDL_SCANCODE_UNKNOWN, // KEY_DISPLAY_OFF + SDL_SCANCODE_UNKNOWN, // KEY_BTN_MISC + SDL_SCANCODE_UNKNOWN, // KEY_GOTO + SDL_SCANCODE_UNKNOWN, // KEY_INFO + SDL_SCANCODE_UNKNOWN, // KEY_PROGRAM + SDL_SCANCODE_UNKNOWN, // KEY_PVR + SDL_SCANCODE_UNKNOWN, // KEY_SUBTITLE + SDL_SCANCODE_UNKNOWN, // KEY_FULLSCREEN + SDL_SCANCODE_UNKNOWN, // KEY_KEYBOARD + SDL_SCANCODE_UNKNOWN, // KEY_ASPECT_RATIO + SDL_SCANCODE_UNKNOWN, // KEY_PC + SDL_SCANCODE_UNKNOWN, // KEY_TV + SDL_SCANCODE_UNKNOWN, // KEY_TV2 + SDL_SCANCODE_UNKNOWN, // KEY_VCR + SDL_SCANCODE_UNKNOWN, // KEY_VCR2 + SDL_SCANCODE_UNKNOWN, // KEY_SAT + SDL_SCANCODE_UNKNOWN, // KEY_CD + SDL_SCANCODE_UNKNOWN, // KEY_TAPE + SDL_SCANCODE_UNKNOWN, // KEY_TUNER + SDL_SCANCODE_UNKNOWN, // KEY_PLAYER + SDL_SCANCODE_UNKNOWN, // KEY_DVD + SDL_SCANCODE_UNKNOWN, // KEY_AUDIO + SDL_SCANCODE_UNKNOWN, // KEY_VIDEO + SDL_SCANCODE_UNKNOWN, // KEY_MEMO + SDL_SCANCODE_UNKNOWN, // KEY_CALENDER + SDL_SCANCODE_UNKNOWN, // KEY_RED + SDL_SCANCODE_UNKNOWN, // KEY_GREEN + SDL_SCANCODE_UNKNOWN, // KEY_YELLOW + SDL_SCANCODE_UNKNOWN, // KEY_BLUE + SDL_SCANCODE_CHANNEL_INCREMENT, + SDL_SCANCODE_CHANNEL_DECREMENT, + SDL_SCANCODE_UNKNOWN, // KEY_LAST + SDL_SCANCODE_UNKNOWN, // KEY_RESTART + SDL_SCANCODE_UNKNOWN, // KEY_SLOW + SDL_SCANCODE_UNKNOWN, // KEY_SHUFFLE + SDL_SCANCODE_UNKNOWN, // KEY_VIDEOPHONE + SDL_SCANCODE_UNKNOWN, // KEY_GAMES + SDL_SCANCODE_UNKNOWN, // KEY_ZOOMIN + SDL_SCANCODE_UNKNOWN, // KEY_ZOOMOUT + SDL_SCANCODE_UNKNOWN, // KEY_ZOOMRESET + SDL_SCANCODE_UNKNOWN, // KEY_WORDPROCESSOR + SDL_SCANCODE_UNKNOWN, // KEY_EDITOR + SDL_SCANCODE_UNKNOWN, // KEY_SPREADSHEET + SDL_SCANCODE_UNKNOWN, // KEY_GRAPHICSEDITOR + SDL_SCANCODE_UNKNOWN, // KEY_PRESENTATION + SDL_SCANCODE_UNKNOWN, // KEY_DATABASE + SDL_SCANCODE_UNKNOWN, // KEY_NEWS + SDL_SCANCODE_UNKNOWN, // KEY_VOICEMAIL + SDL_SCANCODE_UNKNOWN, // KEY_ADDRESSBOOK + SDL_SCANCODE_UNKNOWN, // KEY_MESSENGER + SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_TOGGLE + SDL_SCANCODE_UNKNOWN, // KEY_SPELLCHECK + SDL_SCANCODE_UNKNOWN, // KEY_COFFEE + SDL_SCANCODE_UNKNOWN, // KEY_MEDIA_REPEAT + SDL_SCANCODE_UNKNOWN, // KEY_IMAGES + SDL_SCANCODE_UNKNOWN, // KEY_BUTTONCONFIG + SDL_SCANCODE_UNKNOWN, // KEY_TASKMANAGER + SDL_SCANCODE_UNKNOWN, // KEY_JOURNAL + SDL_SCANCODE_UNKNOWN, // KEY_CONTROLPANEL + SDL_SCANCODE_UNKNOWN, // KEY_APPSELECT + SDL_SCANCODE_UNKNOWN, // KEY_SCREENSAVER + SDL_SCANCODE_UNKNOWN, // KEY_ASSISTANT + SDL_SCANCODE_UNKNOWN, // KEY_KBD_LAYOUT_NEXT + SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_MIN + SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_MAX + SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSISTANT_PREV + SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSISTANT_NEXT + SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSISTANT_PREVGROUP + SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSISTANT_NEXTGROUP + SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSISTANT_ACCEPT + SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSISTANT_CANCEL + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_FRONT + SDL_SCANCODE_UNKNOWN, // KEY_SETUP + SDL_SCANCODE_UNKNOWN, // KEY_WAKEUP + SDL_SCANCODE_UNKNOWN, // KEY_SENDFILE + SDL_SCANCODE_UNKNOWN, // KEY_XFER + SDL_SCANCODE_UNKNOWN, // KEY_PROG1 + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_PROG2 + SDL_SCANCODE_UNKNOWN, // KEY_MSDOS + SDL_SCANCODE_UNKNOWN, // KEY_SCREENLOCK + SDL_SCANCODE_UNKNOWN, // KEY_DIRECTION_ROTATE_DISPLAY + SDL_SCANCODE_UNKNOWN, // KEY_CYCLEWINDOWS + SDL_SCANCODE_UNKNOWN, // KEY_COMPUTER + SDL_SCANCODE_UNKNOWN, // KEY_EJECTCLOSECD + SDL_SCANCODE_UNKNOWN, // KEY_ISO + SDL_SCANCODE_UNKNOWN, // KEY_MOVE + SDL_SCANCODE_F13, + SDL_SCANCODE_F14, + SDL_SCANCODE_F15, + SDL_SCANCODE_F16, + SDL_SCANCODE_F17, + SDL_SCANCODE_F18, + SDL_SCANCODE_F19, + SDL_SCANCODE_F20, + SDL_SCANCODE_F21, + SDL_SCANCODE_F22, + SDL_SCANCODE_F23, + SDL_SCANCODE_F24, + SDL_SCANCODE_UNKNOWN, // KEY_PROG3 + SDL_SCANCODE_UNKNOWN, // KEY_PROG4 + SDL_SCANCODE_UNKNOWN, // KEY_DASHBOARD + SDL_SCANCODE_UNKNOWN, // KEY_SUSPEND + SDL_SCANCODE_UNKNOWN, // KEY_HP + SDL_SCANCODE_UNKNOWN, // KEY_SOUND + SDL_SCANCODE_UNKNOWN, // KEY_QUESTION + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_CONNECT + SDL_SCANCODE_UNKNOWN, // KEY_SPORT + SDL_SCANCODE_UNKNOWN, // KEY_SHOP + SDL_SCANCODE_UNKNOWN, // KEY_ALTERASE + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_SWITCHVIDEOMODE + SDL_SCANCODE_UNKNOWN, // KEY_BATTERY + SDL_SCANCODE_UNKNOWN, // KEY_BLUETOOTH + SDL_SCANCODE_UNKNOWN, // KEY_WLAN + SDL_SCANCODE_UNKNOWN, // KEY_UWB + SDL_SCANCODE_UNKNOWN, // KEY_WWAN_WIMAX + SDL_SCANCODE_UNKNOWN, // KEY_RFKILL + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_CHANNEL + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_BTN_0 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_1 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_2 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_3 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_4 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_5 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_6 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_7 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_8 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_9 +}; + +// static bool SDL_screen_keyboard_shown; + +static SDL_Scancode TranslateKeycode(int keycode) +{ + SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN; + if (keycode <= -1) { + return SDL_SCANCODE_UNKNOWN; + } + if (keycode < SDL_arraysize(OHOS_Keycodes)) { + scancode = OHOS_Keycodes[keycode]; + } + if (scancode == SDL_SCANCODE_UNKNOWN) { + SDL_Log("Unknown keycode %d", keycode); + } + return scancode; +} + +void OHOS_OnKeyDown(int keycode) +{ + SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, keycode, TranslateKeycode(keycode), true); +} + +void OHOS_OnKeyUp(int keycode) +{ + SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, keycode, TranslateKeycode(keycode), false); +} + +#endif diff --git a/src/video/ohos/SDL_ohoskeyboard.h b/src/video/ohos/SDL_ohoskeyboard.h new file mode 100644 index 0000000000000..5dd55f39c4ca8 --- /dev/null +++ b/src/video/ohos/SDL_ohoskeyboard.h @@ -0,0 +1,4 @@ +#ifdef SDL_VIDEO_DRIVER_OHOS +void OHOS_OnKeyDown(int keycode); +void OHOS_OnKeyUp(int keycode); +#endif diff --git a/src/video/ohos/SDL_ohostouch.c b/src/video/ohos/SDL_ohostouch.c new file mode 100644 index 0000000000000..a7f16bfedc757 --- /dev/null +++ b/src/video/ohos/SDL_ohostouch.c @@ -0,0 +1,34 @@ +#include "SDL_ohostouch.h" +#include "../../events/SDL_touch_c.h" +#include "SDL_internal.h" + +void OHOS_OnTouch(SDL_OHOSTouchEvent event) +{ + if (SDL_AddTouch(event.deviceId, SDL_TOUCH_DEVICE_DIRECT, "") < 0) { + SDL_Log("Cannot add touch"); + return; + } + + switch (event.type) { + case SDL_EVENT_FINGER_DOWN: + { + SDL_SendTouch(event.timestamp, event.deviceId, event.fingerId, NULL, SDL_EVENT_FINGER_DOWN, event.x, event.y, event.p); + break; + } + case SDL_EVENT_FINGER_MOTION: + { + SDL_SendTouchMotion(event.timestamp, event.deviceId, event.fingerId, NULL, event.x, event.y, event.p); + break; + } + case SDL_EVENT_FINGER_UP: + { + SDL_SendTouch(event.timestamp, event.deviceId, event.fingerId, NULL, SDL_EVENT_FINGER_UP, event.x, event.y, event.p); + break; + } + case SDL_EVENT_FINGER_CANCELED: + { + SDL_SendTouch(event.timestamp, event.deviceId, event.fingerId, NULL, SDL_EVENT_FINGER_CANCELED, event.x, event.y, event.p); + break; + } + } +} diff --git a/src/video/ohos/SDL_ohostouch.h b/src/video/ohos/SDL_ohostouch.h new file mode 100644 index 0000000000000..de33e4531688d --- /dev/null +++ b/src/video/ohos/SDL_ohostouch.h @@ -0,0 +1,17 @@ +#ifndef SDL_OHOSTOUCH_H +#define SDL_OHOSTOUCH_H + +typedef struct SDL_OHOSTouchEvent { + long long deviceId; + int fingerId; + int type; + float x; + float y; + float p; + float area; + long long timestamp; +} SDL_OHOSTouchEvent; + +void OHOS_OnTouch(SDL_OHOSTouchEvent event); + +#endif diff --git a/src/video/ohos/SDL_ohosvideo.c b/src/video/ohos/SDL_ohosvideo.c new file mode 100644 index 0000000000000..fdf676d90081b --- /dev/null +++ b/src/video/ohos/SDL_ohosvideo.c @@ -0,0 +1,90 @@ +#include "../SDL_sysvideo.h" +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_OHOS +#include "../../core/ohos/SDL_ohos.h" +#include "SDL_ohosgl.h" +#include "SDL_ohosvulkan.h" +#include "SDL_ohoswindow.h" + +bool OHOS_VideoInit(SDL_VideoDevice *_this) +{ + SDL_DisplayMode mode; + SDL_zero(mode); + mode.format = SDL_PIXELFORMAT_RGBA32; + mode.w = OHOS_FetchWidth(); + mode.h = OHOS_FetchHeight(); + mode.refresh_rate = 60; + + SDL_AddBasicVideoDisplay(&mode); + return true; +} +void OHOS_VideoQuit(SDL_VideoDevice *_this) +{ +} +void OHOS_DeviceFree(SDL_VideoDevice *device) +{ + SDL_free(device); +} +static SDL_VideoDevice *OHOS_CreateDevice(void) +{ + SDL_VideoDevice *device; + SDL_VideoData *data; + + device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); + if (!device) { + return NULL; + } + + data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); + if (!data) { + return NULL; + } + + device->internal = data; + device->free = OHOS_DeviceFree; + + device->VideoInit = OHOS_VideoInit; + device->VideoQuit = OHOS_VideoQuit; +#ifdef SDL_VIDEO_VULKAN + device->Vulkan_LoadLibrary = OHOS_Vulkan_LoadLibrary; + device->Vulkan_UnloadLibrary = OHOS_Vulkan_UnloadLibrary; + device->Vulkan_GetInstanceExtensions = OHOS_Vulkan_GetInstanceExtensions; + device->Vulkan_CreateSurface = OHOS_Vulkan_CreateSurface; + device->Vulkan_DestroySurface = OHOS_Vulkan_DestroySurface; +#endif + device->CreateSDLWindow = OHOS_CreateWindow; + device->DestroyWindow = OHOS_DestroyWindow; + +#ifdef SDL_VIDEO_OPENGL_EGL + device->GL_LoadLibrary = OHOS_GLES_LoadLibrary; + device->GL_MakeCurrent = OHOS_GLES_MakeCurrent; + device->GL_CreateContext = OHOS_GLES_CreateContext; + device->GL_SwapWindow = OHOS_GLES_SwapWindow; + device->GL_GetProcAddress = SDL_EGL_GetProcAddressInternal; + device->GL_UnloadLibrary = SDL_EGL_UnloadLibrary; + device->GL_SetSwapInterval = SDL_EGL_SetSwapInterval; + device->GL_GetSwapInterval = SDL_EGL_GetSwapInterval; + device->GL_DestroyContext = SDL_EGL_DestroyContext; +#endif + + return device; +} +bool OHOS_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID) +{ + int length1 = SDL_strlen(messageboxdata->title) + 1; + char* titlecopy = (char*)SDL_malloc(length1); + SDL_memcpy(titlecopy, messageboxdata->title, length1); + length1 = SDL_strlen(messageboxdata->message) + 1; + char* messagecopy = (char*)SDL_malloc(length1); + SDL_memcpy(messagecopy, messageboxdata->message, length1); + OHOS_MessageBox(titlecopy, messagecopy); + return true; +} +VideoBootStrap OHOS_bootstrap = { + "ohos", "OpenHarmony video driver", + OHOS_CreateDevice, + OHOS_ShowMessageBox, + false +}; +#endif diff --git a/src/video/ohos/SDL_ohosvideo.h b/src/video/ohos/SDL_ohosvideo.h new file mode 100644 index 0000000000000..a27ee2e226b0b --- /dev/null +++ b/src/video/ohos/SDL_ohosvideo.h @@ -0,0 +1,17 @@ +#ifndef SDL_OHOSVIDEO_H +#define SDL_OHOSVIDEO_H + +#include "../SDL_egl_c.h" +#include "../../core/ohos/SDL_ohos.h" +struct SDL_WindowData { +#ifdef SDL_VIDEO_OPENGL_EGL + EGLSurface egl_surface; + EGLContext egl_context; +#endif + bool backup_done; + OHNativeWindow *native_window; + uint64_t width; + uint64_t height; +}; + +#endif diff --git a/src/video/ohos/SDL_ohosvulkan.c b/src/video/ohos/SDL_ohosvulkan.c new file mode 100644 index 0000000000000..e33aece5a79c2 --- /dev/null +++ b/src/video/ohos/SDL_ohosvulkan.c @@ -0,0 +1,130 @@ +#include "SDL_ohosvulkan.h" +#include "SDL_internal.h" +#include + +#ifdef SDL_VIDEO_DRIVER_OHOS +#define VK_USE_PLATFORM_OHOS 1 +#include "../../core/ohos/SDL_ohos.h" +#include "../SDL_sysvideo.h" +#include "SDL_ohosvideo.h" +#include "vulkan/vulkan.h" +#include "vulkan/vulkan_ohos.h" +#include + +static int loadedCount = 0; +bool OHOS_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) +{ + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL; + if (_this->vulkan_config.loader_handle) { + return SDL_SetError("Vulkan already loaded"); + } + + /* Load the Vulkan loader library */ + if (!path) { + path = SDL_getenv("SDL_VULKAN_LIBRARY"); + } + if (!path) { + path = "libvulkan.so"; + } + _this->vulkan_config.loader_handle = SDL_LoadObject(path); + if (!_this->vulkan_config.loader_handle) { + return false; + } + SDL_strlcpy(_this->vulkan_config.loader_path, path, + SDL_arraysize(_this->vulkan_config.loader_path)); + vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction( + _this->vulkan_config.loader_handle, "vkGetInstanceProcAddr"); + if (!vkGetInstanceProcAddr) { + goto fail; + } + _this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr; + _this->vulkan_config.vkEnumerateInstanceExtensionProperties = + (void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)( + VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties"); + if (!_this->vulkan_config.vkEnumerateInstanceExtensionProperties) { + goto fail; + } + loadedCount++; + return true; + +fail: + SDL_UnloadObject(_this->vulkan_config.loader_handle); + _this->vulkan_config.loader_handle = NULL; + return false; +} + +void OHOS_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) +{ + if (loadedCount == 0) { + return; + } + loadedCount--; + if (_this->vulkan_config.loader_handle && loadedCount == 0) { + SDL_UnloadObject(_this->vulkan_config.loader_handle); + _this->vulkan_config.loader_handle = NULL; + } +} + +char const *const *OHOS_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count) +{ + static const char *const extensionsForOHOS[] = { + VK_KHR_SURFACE_EXTENSION_NAME, VK_OHOS_SURFACE_EXTENSION_NAME + }; + if (count) { + *count = SDL_arraysize(extensionsForOHOS); + } + return extensionsForOHOS; +} + +bool OHOS_Vulkan_CreateSurface(SDL_VideoDevice *_this, + SDL_Window *window, + VkInstance instance, + const struct VkAllocationCallbacks *allocator, + VkSurfaceKHR *surface) +{ + VkResult result; + + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = + (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr; + PFN_vkCreateSurfaceOHOS vkCreateSurfaceOHOS = + (PFN_vkCreateSurfaceOHOS)vkGetInstanceProcAddr(instance, "vkCreateSurfaceOHOS"); + VkSurfaceCreateInfoOHOS createInfo; + + if (!_this->vulkan_config.loader_handle) { + SDL_SetError("Vulkan is not loaded"); + return false; + } + + if (!vkCreateSurfaceOHOS) { + SDL_SetError(VK_OHOS_SURFACE_EXTENSION_NAME + " extension is not enabled in the Vulkan instance."); + return false; + } + + SDL_zero(createInfo); + createInfo.sType = VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS; + createInfo.pNext = NULL; + createInfo.flags = 0; + createInfo.window = window->internal->native_window; + result = vkCreateSurfaceOHOS(instance, &createInfo, NULL, surface); + if (result != VK_SUCCESS) { + SDL_SetError("vkCreateSurfaceOHOS failed: %d", result); + return false; + } + return true; +} + +void OHOS_Vulkan_DestroySurface(SDL_VideoDevice *_this, + VkInstance instance, + VkSurfaceKHR surface, + const struct VkAllocationCallbacks *allocator) +{ + if (_this->vulkan_config.loader_handle) { + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = + (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr; + PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)vkGetInstanceProcAddr(instance, "vkDestroySurfaceKHR"); + vkDestroySurfaceKHR(instance, surface, allocator); + } +} + +#endif diff --git a/src/video/ohos/SDL_ohosvulkan.h b/src/video/ohos/SDL_ohosvulkan.h new file mode 100644 index 0000000000000..5700c29866fa7 --- /dev/null +++ b/src/video/ohos/SDL_ohosvulkan.h @@ -0,0 +1,21 @@ +#ifndef SDL_OHOSVULKAN_H +#define SDL_OHOSVULKAN_H + +#ifdef SDL_VIDEO_DRIVER_OHOS +#include "../SDL_sysvideo.h" + +bool OHOS_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path); +void OHOS_Vulkan_UnloadLibrary(SDL_VideoDevice *_this); +char const* const* OHOS_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count); +bool OHOS_Vulkan_CreateSurface(SDL_VideoDevice *_this, + SDL_Window *window, + VkInstance instance, + const struct VkAllocationCallbacks *allocator, + VkSurfaceKHR *surface); +void OHOS_Vulkan_DestroySurface(SDL_VideoDevice *_this, + VkInstance instance, + VkSurfaceKHR surface, + const struct VkAllocationCallbacks *allocator); +#endif + +#endif diff --git a/src/video/ohos/SDL_ohoswindow.c b/src/video/ohos/SDL_ohoswindow.c new file mode 100644 index 0000000000000..b74c72555865f --- /dev/null +++ b/src/video/ohos/SDL_ohoswindow.c @@ -0,0 +1,20 @@ +#include "SDL_ohoswindow.h" +#include "SDL_internal.h" +#include + +#ifdef SDL_VIDEO_DRIVER_OHOS +#include "../../core/ohos/SDL_ohos.h" +#include "SDL_ohosvideo.h" +bool OHOS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) +{ + OHOS_windowDataFill(window); + + return true; +} + +void OHOS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) +{ + OHOS_removeWindow(window); +} + +#endif diff --git a/src/video/ohos/SDL_ohoswindow.h b/src/video/ohos/SDL_ohoswindow.h new file mode 100644 index 0000000000000..b611951a79bec --- /dev/null +++ b/src/video/ohos/SDL_ohoswindow.h @@ -0,0 +1,8 @@ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_OHOS +#include "../SDL_sysvideo.h" +bool OHOS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); +void OHOS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); + +#endif