mirror of https://github.com/libsdl-org/SDL
N3DS port (squashed)
A dedicated renderer using Citro3D would likely allow for better much better graphical performances.
This commit is contained in:
parent
61b5360e17
commit
655275378d
|
@ -0,0 +1,40 @@
|
||||||
|
name: Build (Nintendo 3DS)
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
n3ds:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: devkitpro/devkitarm:latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install build requirements
|
||||||
|
run: |
|
||||||
|
apt update
|
||||||
|
apt install ninja-build
|
||||||
|
- name: Configure CMake
|
||||||
|
run: |
|
||||||
|
cmake -S . -B build -G Ninja \
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE=${DEVKITPRO}/cmake/3DS.cmake \
|
||||||
|
-DSDL_TESTS=ON \
|
||||||
|
-DSDL_INSTALL_TESTS=ON \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=prefix
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build build --verbose
|
||||||
|
- name: Install CMake
|
||||||
|
run: |
|
||||||
|
echo "SDL2_DIR=$(pwd)/prefix" >> $GITHUB_ENV
|
||||||
|
cmake --install build/
|
||||||
|
( cd prefix; find ) | LC_ALL=C sort -u
|
||||||
|
- name: Verify CMake configuration files
|
||||||
|
run: |
|
||||||
|
cmake -S cmake/test -B cmake_config_build -G Ninja \
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE=${DEVKITPRO}/cmake/3DS.cmake \
|
||||||
|
-DTEST_SHARED=FALSE \
|
||||||
|
-DCMAKE_PREFIX_PATH=${{ env.SDL2_DIR }} \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release
|
||||||
|
cmake --build cmake_config_build --verbose
|
||||||
|
# Not running test_pkgconfig.sh and test_sdlconfig.sh
|
||||||
|
# as invoking the compiler manually is not supported
|
|
@ -196,6 +196,8 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "BeOS.*")
|
||||||
message_error("BeOS support has been removed as of SDL 2.0.2.")
|
message_error("BeOS support has been removed as of SDL 2.0.2.")
|
||||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Haiku.*")
|
elseif(CMAKE_SYSTEM_NAME MATCHES "Haiku.*")
|
||||||
set(HAIKU TRUE)
|
set(HAIKU TRUE)
|
||||||
|
elseif(NINTENDO_3DS)
|
||||||
|
set(N3DS TRUE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Don't mistake osx for unix
|
# Don't mistake osx for unix
|
||||||
|
@ -277,7 +279,7 @@ if(APPLE OR ARCH_64 OR MSVC_CLANG)
|
||||||
set(OPT_DEF_SSEMATH ON)
|
set(OPT_DEF_SSEMATH ON)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
if(UNIX OR MINGW OR MSYS OR (USE_CLANG AND NOT WINDOWS) OR VITA OR PSP OR PS2)
|
if(UNIX OR MINGW OR MSYS OR (USE_CLANG AND NOT WINDOWS) OR VITA OR PSP OR PS2 OR N3DS)
|
||||||
set(OPT_DEF_LIBC ON)
|
set(OPT_DEF_LIBC ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -381,7 +383,7 @@ if(EMSCRIPTEN)
|
||||||
set(SDL_TEST_ENABLED_BY_DEFAULT OFF)
|
set(SDL_TEST_ENABLED_BY_DEFAULT OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(VITA OR PSP OR PS2)
|
if(VITA OR PSP OR PS2 OR N3DS)
|
||||||
set(SDL_SHARED_ENABLED_BY_DEFAULT OFF)
|
set(SDL_SHARED_ENABLED_BY_DEFAULT OFF)
|
||||||
set(SDL_LOADSO_ENABLED_BY_DEFAULT OFF)
|
set(SDL_LOADSO_ENABLED_BY_DEFAULT OFF)
|
||||||
endif()
|
endif()
|
||||||
|
@ -2734,6 +2736,74 @@ elseif(OS2)
|
||||||
if(SDL_HIDAPI)
|
if(SDL_HIDAPI)
|
||||||
CheckHIDAPI()
|
CheckHIDAPI()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
elseif(N3DS)
|
||||||
|
file(GLOB N3DS_MAIN_SOURCES ${SDL2_SOURCE_DIR}/src/main/n3ds/*.c)
|
||||||
|
set(SDLMAIN_SOURCES ${SDLMAIN_SOURCES} ${N3DS_MAIN_SOURCES})
|
||||||
|
|
||||||
|
if(SDL_AUDIO)
|
||||||
|
set(SDL_AUDIO_DRIVER_N3DS 1)
|
||||||
|
file(GLOB N3DS_AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/n3ds/*.c)
|
||||||
|
list(APPEND SOURCE_FILES ${N3DS_AUDIO_SOURCES})
|
||||||
|
set(HAVE_SDL_AUDIO TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SDL_FILESYSTEM)
|
||||||
|
set(SDL_FILESYSTEM_N3DS 1)
|
||||||
|
file(GLOB N3DS_FILESYSTEM_SOURCES ${SDL2_SOURCE_DIR}/src/filesystem/n3ds/*.c)
|
||||||
|
list(APPEND SOURCE_FILES ${N3DS_FILESYSTEM_SOURCES})
|
||||||
|
set(HAVE_SDL_FILESYSTEM TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SDL_JOYSTICK)
|
||||||
|
set(SDL_JOYSTICK_N3DS 1)
|
||||||
|
file(GLOB N3DS_JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/n3ds/*.c)
|
||||||
|
list(APPEND SOURCE_FILES ${N3DS_JOYSTICK_SOURCES})
|
||||||
|
set(HAVE_SDL_JOYSTICK TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SDL_POWER)
|
||||||
|
set(SDL_POWER_N3DS 1)
|
||||||
|
file(GLOB N3DS_POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/n3ds/*.c)
|
||||||
|
list(APPEND SOURCE_FILES ${N3DS_POWER_SOURCES})
|
||||||
|
set(HAVE_SDL_POWER TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SDL_THREADS)
|
||||||
|
set(SDL_THREAD_N3DS 1)
|
||||||
|
file(GLOB N3DS_THREAD_SOURCES ${SDL2_SOURCE_DIR}/src/thread/n3ds/*.c)
|
||||||
|
list(APPEND SOURCE_FILES ${N3DS_THREAD_SOURCES} ${SDL2_SOURCE_DIR}/src/thread/generic/SDL_systls.c)
|
||||||
|
set(HAVE_SDL_THREADS TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SDL_TIMERS)
|
||||||
|
set(SDL_TIMER_N3DS 1)
|
||||||
|
file(GLOB TIMER_SOURCES ${SDL2_SOURCE_DIR}/src/timer/n3ds/*.c)
|
||||||
|
list(APPEND SOURCE_FILES ${TIMER_SOURCES})
|
||||||
|
set(HAVE_SDL_TIMERS TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SDL_VIDEO)
|
||||||
|
set(SDL_VIDEO_DRIVER_N3DS 1)
|
||||||
|
file(GLOB N3DS_VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/n3ds/*.c)
|
||||||
|
list(APPEND SOURCE_FILES ${N3DS_VIDEO_SOURCES})
|
||||||
|
set(HAVE_SDL_VIDEO TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SDL_LOCALE)
|
||||||
|
file(GLOB N3DS_LOCALE_SOURCES ${SDL2_SOURCE_DIR}/src/locale/n3ds/*.c)
|
||||||
|
list(APPEND SOURCE_FILES ${N3DS_LOCALE_SOURCES})
|
||||||
|
set(HAVE_SDL_LOCALE TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Requires the n3ds file implementation
|
||||||
|
if(SDL_FILE)
|
||||||
|
file(GLOB N3DS_FILE_SOURCES ${SDL2_SOURCE_DIR}/src/file/n3ds/*.c)
|
||||||
|
list(APPEND SOURCE_FILES ${N3DS_FILE_SOURCES})
|
||||||
|
set(HAVE_SDL_FILE TRUE)
|
||||||
|
else()
|
||||||
|
message_error("SDL_FILE must be enabled to build on N3DS")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(HAVE_VULKAN AND NOT SDL_LOADSO)
|
if(HAVE_VULKAN AND NOT SDL_LOADSO)
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Nintendo 3DS
|
||||||
|
|
||||||
|
SDL port for the Nintendo 3DS [Homebrew toolchain](https://devkitpro.org/) contributed by:
|
||||||
|
|
||||||
|
- [Pierre Wendling](https://github.com/FtZPetruska)
|
||||||
|
|
||||||
|
Credits to:
|
||||||
|
|
||||||
|
- The awesome people who ported SDL to other homebrew platforms.
|
||||||
|
- The Devkitpro team for making all the tools necessary to achieve this.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
To build for the Nintendo 3DS, make sure you have devkitARM and cmake installed and run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE="$DEVKITPRO/cmake/3DS.cmake" -DCMAKE_BUILD_TYPE=Release
|
||||||
|
cmake --build build
|
||||||
|
cmake --install build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Currently only software rendering is supported.
|
||||||
|
- Window are created on the top screen by default, use the `SDL_WINDOW_N3DS_BOTTOM` flag to put them on the bottom screen.
|
||||||
|
- SDL2main should be used to ensure all the necessary services are initialised.
|
||||||
|
- By default, the extra L2 cache and higher clock speeds of the New 2/3DS lineup are enabled. If you wish to turn it off, [use the PTMSYSM service](https://libctru.devkitpro.org/ptmsysm_8h.html#ae3a437bfd0de05fbc5ba9a460d148430) to turn it off in your program.
|
|
@ -325,6 +325,7 @@
|
||||||
#cmakedefine SDL_AUDIO_DRIVER_VITA @SDL_AUDIO_DRIVER_VITA@
|
#cmakedefine SDL_AUDIO_DRIVER_VITA @SDL_AUDIO_DRIVER_VITA@
|
||||||
#cmakedefine SDL_AUDIO_DRIVER_PSP @SDL_AUDIO_DRIVER_PSP@
|
#cmakedefine SDL_AUDIO_DRIVER_PSP @SDL_AUDIO_DRIVER_PSP@
|
||||||
#cmakedefine SDL_AUDIO_DRIVER_PS2 @SDL_AUDIO_DRIVER_PS2@
|
#cmakedefine SDL_AUDIO_DRIVER_PS2 @SDL_AUDIO_DRIVER_PS2@
|
||||||
|
#cmakedefine SDL_AUDIO_DRIVER_N3DS @SDL_AUDIO_DRIVER_N3DS@
|
||||||
|
|
||||||
/* Enable various input drivers */
|
/* Enable various input drivers */
|
||||||
#cmakedefine SDL_INPUT_LINUXEV @SDL_INPUT_LINUXEV@
|
#cmakedefine SDL_INPUT_LINUXEV @SDL_INPUT_LINUXEV@
|
||||||
|
@ -349,6 +350,7 @@
|
||||||
#cmakedefine SDL_JOYSTICK_VITA @SDL_JOYSTICK_VITA@
|
#cmakedefine SDL_JOYSTICK_VITA @SDL_JOYSTICK_VITA@
|
||||||
#cmakedefine SDL_JOYSTICK_PSP @SDL_JOYSTICK_PSP@
|
#cmakedefine SDL_JOYSTICK_PSP @SDL_JOYSTICK_PSP@
|
||||||
#cmakedefine SDL_JOYSTICK_PS2 @SDL_JOYSTICK_PS2@
|
#cmakedefine SDL_JOYSTICK_PS2 @SDL_JOYSTICK_PS2@
|
||||||
|
#cmakedefine SDL_JOYSTICK_N3DS @SDL_JOYSTICK_N3DS@
|
||||||
#cmakedefine SDL_HAPTIC_DUMMY @SDL_HAPTIC_DUMMY@
|
#cmakedefine SDL_HAPTIC_DUMMY @SDL_HAPTIC_DUMMY@
|
||||||
#cmakedefine SDL_HAPTIC_LINUX @SDL_HAPTIC_LINUX@
|
#cmakedefine SDL_HAPTIC_LINUX @SDL_HAPTIC_LINUX@
|
||||||
#cmakedefine SDL_HAPTIC_IOKIT @SDL_HAPTIC_IOKIT@
|
#cmakedefine SDL_HAPTIC_IOKIT @SDL_HAPTIC_IOKIT@
|
||||||
|
@ -381,6 +383,7 @@
|
||||||
#cmakedefine SDL_THREAD_VITA @SDL_THREAD_VITA@
|
#cmakedefine SDL_THREAD_VITA @SDL_THREAD_VITA@
|
||||||
#cmakedefine SDL_THREAD_PSP @SDL_THREAD_PSP@
|
#cmakedefine SDL_THREAD_PSP @SDL_THREAD_PSP@
|
||||||
#cmakedefine SDL_THREAD_PS2 @SDL_THREAD_PS2@
|
#cmakedefine SDL_THREAD_PS2 @SDL_THREAD_PS2@
|
||||||
|
#cmakedefine SDL_THREAD_N3DS @SDL_THREAD_N3DS@
|
||||||
|
|
||||||
/* Enable various timer systems */
|
/* Enable various timer systems */
|
||||||
#cmakedefine SDL_TIMER_HAIKU @SDL_TIMER_HAIKU@
|
#cmakedefine SDL_TIMER_HAIKU @SDL_TIMER_HAIKU@
|
||||||
|
@ -391,6 +394,7 @@
|
||||||
#cmakedefine SDL_TIMER_VITA @SDL_TIMER_VITA@
|
#cmakedefine SDL_TIMER_VITA @SDL_TIMER_VITA@
|
||||||
#cmakedefine SDL_TIMER_PSP @SDL_TIMER_PSP@
|
#cmakedefine SDL_TIMER_PSP @SDL_TIMER_PSP@
|
||||||
#cmakedefine SDL_TIMER_PS2 @SDL_TIMER_PS2@
|
#cmakedefine SDL_TIMER_PS2 @SDL_TIMER_PS2@
|
||||||
|
#cmakedefine SDL_TIMER_N3DS @SDL_TIMER_N3DS@
|
||||||
|
|
||||||
/* Enable various video drivers */
|
/* Enable various video drivers */
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@
|
#cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@
|
||||||
|
@ -444,6 +448,7 @@
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS @SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS@
|
#cmakedefine SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS @SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS@
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM @SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM@
|
#cmakedefine SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM @SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM@
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_VITA @SDL_VIDEO_DRIVER_VITA@
|
#cmakedefine SDL_VIDEO_DRIVER_VITA @SDL_VIDEO_DRIVER_VITA@
|
||||||
|
#cmakedefine SDL_VIDEO_DRIVER_N3DS @SDL_VIDEO_DRIVER_N3DS@
|
||||||
|
|
||||||
#cmakedefine SDL_VIDEO_RENDER_D3D @SDL_VIDEO_RENDER_D3D@
|
#cmakedefine SDL_VIDEO_RENDER_D3D @SDL_VIDEO_RENDER_D3D@
|
||||||
#cmakedefine SDL_VIDEO_RENDER_D3D11 @SDL_VIDEO_RENDER_D3D11@
|
#cmakedefine SDL_VIDEO_RENDER_D3D11 @SDL_VIDEO_RENDER_D3D11@
|
||||||
|
@ -487,6 +492,7 @@
|
||||||
#cmakedefine SDL_POWER_HARDWIRED @SDL_POWER_HARDWIRED@
|
#cmakedefine SDL_POWER_HARDWIRED @SDL_POWER_HARDWIRED@
|
||||||
#cmakedefine SDL_POWER_VITA @SDL_POWER_VITA@
|
#cmakedefine SDL_POWER_VITA @SDL_POWER_VITA@
|
||||||
#cmakedefine SDL_POWER_PSP @SDL_POWER_PSP@
|
#cmakedefine SDL_POWER_PSP @SDL_POWER_PSP@
|
||||||
|
#cmakedefine SDL_POWER_N3DS @SDL_POWER_N3DS@
|
||||||
|
|
||||||
/* Enable system filesystem support */
|
/* Enable system filesystem support */
|
||||||
#cmakedefine SDL_FILESYSTEM_ANDROID @SDL_FILESYSTEM_ANDROID@
|
#cmakedefine SDL_FILESYSTEM_ANDROID @SDL_FILESYSTEM_ANDROID@
|
||||||
|
@ -501,6 +507,7 @@
|
||||||
#cmakedefine SDL_FILESYSTEM_VITA @SDL_FILESYSTEM_VITA@
|
#cmakedefine SDL_FILESYSTEM_VITA @SDL_FILESYSTEM_VITA@
|
||||||
#cmakedefine SDL_FILESYSTEM_PSP @SDL_FILESYSTEM_PSP@
|
#cmakedefine SDL_FILESYSTEM_PSP @SDL_FILESYSTEM_PSP@
|
||||||
#cmakedefine SDL_FILESYSTEM_PS2 @SDL_FILESYSTEM_PS2@
|
#cmakedefine SDL_FILESYSTEM_PS2 @SDL_FILESYSTEM_PS2@
|
||||||
|
#cmakedefine SDL_FILESYSTEM_N3DS @SDL_FILESYSTEM_N3DS@
|
||||||
|
|
||||||
/* Enable misc subsystem */
|
/* Enable misc subsystem */
|
||||||
#cmakedefine SDL_MISC_DUMMY @SDL_MISC_DUMMY@
|
#cmakedefine SDL_MISC_DUMMY @SDL_MISC_DUMMY@
|
||||||
|
|
|
@ -108,6 +108,15 @@
|
||||||
void reset_IOP(); \
|
void reset_IOP(); \
|
||||||
void reset_IOP() {}
|
void reset_IOP() {}
|
||||||
|
|
||||||
|
#elif defined(__3DS__)
|
||||||
|
/*
|
||||||
|
On N3DS, SDL provides a main function that sets up the screens
|
||||||
|
and storage.
|
||||||
|
|
||||||
|
If you provide this yourself, you may define SDL_MAIN_HANDLED
|
||||||
|
*/
|
||||||
|
#define SDL_MAIN_AVAILABLE
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif /* SDL_MAIN_HANDLED */
|
#endif /* SDL_MAIN_HANDLED */
|
||||||
|
|
||||||
|
|
|
@ -221,6 +221,11 @@
|
||||||
#define __VITA__ 1
|
#define __VITA__ 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__3DS__)
|
||||||
|
#undef __3DS__
|
||||||
|
#define __3DS__ 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "begin_code.h"
|
#include "begin_code.h"
|
||||||
/* Set up for C function definitions, even when using C++ */
|
/* Set up for C function definitions, even when using C++ */
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -410,7 +410,7 @@ SDL_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8);
|
||||||
|
|
||||||
/** \cond */
|
/** \cond */
|
||||||
#ifndef DOXYGEN_SHOULD_IGNORE_THIS
|
#ifndef DOXYGEN_SHOULD_IGNORE_THIS
|
||||||
#if !defined(__ANDROID__) && !defined(__VITA__)
|
#if !defined(__ANDROID__) && !defined(__VITA__) && !defined(__3DS__)
|
||||||
/* TODO: include/SDL_stdinc.h:174: error: size of array 'SDL_dummy_enum' is negative */
|
/* TODO: include/SDL_stdinc.h:174: error: size of array 'SDL_dummy_enum' is negative */
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
|
|
@ -126,6 +126,7 @@ typedef enum
|
||||||
SDL_WINDOW_KEYBOARD_GRABBED = 0x00100000, /**< window has grabbed keyboard input */
|
SDL_WINDOW_KEYBOARD_GRABBED = 0x00100000, /**< window has grabbed keyboard input */
|
||||||
SDL_WINDOW_VULKAN = 0x10000000, /**< window usable for Vulkan surface */
|
SDL_WINDOW_VULKAN = 0x10000000, /**< window usable for Vulkan surface */
|
||||||
SDL_WINDOW_METAL = 0x20000000, /**< window usable for Metal view */
|
SDL_WINDOW_METAL = 0x20000000, /**< window usable for Metal view */
|
||||||
|
SDL_WINDOW_N3DS_BOTTOM = 0x40000000, /**< window should be on the bottom screen (N3DS only) */
|
||||||
|
|
||||||
SDL_WINDOW_INPUT_GRABBED = SDL_WINDOW_MOUSE_GRABBED /**< equivalent to SDL_WINDOW_MOUSE_GRABBED for compatibility */
|
SDL_WINDOW_INPUT_GRABBED = SDL_WINDOW_MOUSE_GRABBED /**< equivalent to SDL_WINDOW_MOUSE_GRABBED for compatibility */
|
||||||
} SDL_WindowFlags;
|
} SDL_WindowFlags;
|
||||||
|
|
|
@ -609,6 +609,8 @@ SDL_GetPlatform(void)
|
||||||
return "PlayStation Vita";
|
return "PlayStation Vita";
|
||||||
#elif __NGAGE__
|
#elif __NGAGE__
|
||||||
return "Nokia N-Gage";
|
return "Nokia N-Gage";
|
||||||
|
#elif __3DS__
|
||||||
|
return "Nintendo 3DS";
|
||||||
#else
|
#else
|
||||||
return "Unknown (see SDL_platform.h)";
|
return "Unknown (see SDL_platform.h)";
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -485,6 +485,13 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
|
||||||
fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
|
fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
|
||||||
fclose (pFile);
|
fclose (pFile);
|
||||||
}
|
}
|
||||||
|
#elif defined(__3DS__)
|
||||||
|
{
|
||||||
|
FILE* pFile;
|
||||||
|
pFile = fopen ("/SDL_Log.txt", "a");
|
||||||
|
fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
|
||||||
|
fclose (pFile);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_STDIO_H && \
|
#if HAVE_STDIO_H && \
|
||||||
!(defined(__APPLE__) && (defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT)))
|
!(defined(__APPLE__) && (defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT)))
|
||||||
|
|
|
@ -105,6 +105,9 @@ static const AudioBootStrap *const bootstrap[] = {
|
||||||
#if SDL_AUDIO_DRIVER_VITA
|
#if SDL_AUDIO_DRIVER_VITA
|
||||||
&VITAAUD_bootstrap,
|
&VITAAUD_bootstrap,
|
||||||
#endif
|
#endif
|
||||||
|
#if SDL_AUDIO_DRIVER_N3DS
|
||||||
|
&N3DSAUDIO_bootstrap,
|
||||||
|
#endif
|
||||||
#if SDL_AUDIO_DRIVER_EMSCRIPTEN
|
#if SDL_AUDIO_DRIVER_EMSCRIPTEN
|
||||||
&EMSCRIPTENAUDIO_bootstrap,
|
&EMSCRIPTENAUDIO_bootstrap,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -209,6 +209,7 @@ extern AudioBootStrap ANDROIDAUDIO_bootstrap;
|
||||||
extern AudioBootStrap PS2AUDIO_bootstrap;
|
extern AudioBootStrap PS2AUDIO_bootstrap;
|
||||||
extern AudioBootStrap PSPAUDIO_bootstrap;
|
extern AudioBootStrap PSPAUDIO_bootstrap;
|
||||||
extern AudioBootStrap VITAAUD_bootstrap;
|
extern AudioBootStrap VITAAUD_bootstrap;
|
||||||
|
extern AudioBootStrap N3DSAUDIO_bootstrap;
|
||||||
extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
|
extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
|
||||||
extern AudioBootStrap OS2AUDIO_bootstrap;
|
extern AudioBootStrap OS2AUDIO_bootstrap;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,363 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifdef SDL_AUDIO_DRIVER_N3DS
|
||||||
|
|
||||||
|
#include "SDL_audio.h"
|
||||||
|
|
||||||
|
/* N3DS Audio driver */
|
||||||
|
|
||||||
|
#include "../SDL_sysaudio.h"
|
||||||
|
#include "SDL_n3dsaudio.h"
|
||||||
|
#include "SDL_timer.h"
|
||||||
|
|
||||||
|
#define N3DSAUDIO_DRIVER_NAME "n3ds"
|
||||||
|
|
||||||
|
static dspHookCookie dsp_hook;
|
||||||
|
static SDL_AudioDevice *audio_device;
|
||||||
|
|
||||||
|
static void FreePrivateData(_THIS);
|
||||||
|
static int FindAudioFormat(_THIS);
|
||||||
|
|
||||||
|
static SDL_INLINE void
|
||||||
|
contextLock(_THIS)
|
||||||
|
{
|
||||||
|
LightLock_Lock(&this->hidden->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_INLINE void
|
||||||
|
contextUnlock(_THIS)
|
||||||
|
{
|
||||||
|
LightLock_Unlock(&this->hidden->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DSAUD_LockAudio(_THIS)
|
||||||
|
{
|
||||||
|
contextLock(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DSAUD_UnlockAudio(_THIS)
|
||||||
|
{
|
||||||
|
contextUnlock(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DSAUD_DspHook(DSP_HookType hook)
|
||||||
|
{
|
||||||
|
if (hook == DSPHOOK_ONCANCEL) {
|
||||||
|
contextLock(audio_device);
|
||||||
|
audio_device->hidden->isCancelled = SDL_TRUE;
|
||||||
|
SDL_AtomicSet(&audio_device->enabled, SDL_FALSE);
|
||||||
|
CondVar_Broadcast(&audio_device->hidden->cv);
|
||||||
|
contextUnlock(audio_device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
AudioFrameFinished(void *device)
|
||||||
|
{
|
||||||
|
bool shouldBroadcast = false;
|
||||||
|
unsigned i;
|
||||||
|
SDL_AudioDevice *this = (SDL_AudioDevice *) device;
|
||||||
|
|
||||||
|
contextLock(this);
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_BUFFERS; i++) {
|
||||||
|
if (this->hidden->waveBuf[i].status == NDSP_WBUF_DONE) {
|
||||||
|
this->hidden->waveBuf[i].status = NDSP_WBUF_FREE;
|
||||||
|
shouldBroadcast = SDL_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldBroadcast) {
|
||||||
|
CondVar_Broadcast(&this->hidden->cv);
|
||||||
|
}
|
||||||
|
|
||||||
|
contextUnlock(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
N3DSAUDIO_OpenDevice(_THIS, const char *devname)
|
||||||
|
{
|
||||||
|
Result ndsp_init_res;
|
||||||
|
Uint8 *data_vaddr;
|
||||||
|
float mix[12];
|
||||||
|
this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof *this->hidden);
|
||||||
|
|
||||||
|
if (this->hidden == NULL) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialise the DSP service */
|
||||||
|
ndsp_init_res = ndspInit();
|
||||||
|
if (R_FAILED(ndsp_init_res)) {
|
||||||
|
if ((R_SUMMARY(ndsp_init_res) == RS_NOTFOUND) && (R_MODULE(ndsp_init_res) == RM_DSP)) {
|
||||||
|
SDL_SetError("DSP init failed: dspfirm.cdc missing!");
|
||||||
|
} else {
|
||||||
|
SDL_SetError("DSP init failed. Error code: 0x%lX", ndsp_init_res);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialise internal state */
|
||||||
|
LightLock_Init(&this->hidden->lock);
|
||||||
|
CondVar_Init(&this->hidden->cv);
|
||||||
|
|
||||||
|
if (this->spec.channels > 2) {
|
||||||
|
this->spec.channels = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Should not happen but better be safe. */
|
||||||
|
if (FindAudioFormat(this) < 0) {
|
||||||
|
return SDL_SetError("No supported audio format found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the fragment size as size in bytes */
|
||||||
|
SDL_CalculateAudioSpec(&this->spec);
|
||||||
|
|
||||||
|
/* Allocate mixing buffer */
|
||||||
|
if (this->spec.size >= SDL_MAX_UINT32 / 2) {
|
||||||
|
return SDL_SetError("Mixing buffer is too large.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->hidden->mixlen = this->spec.size;
|
||||||
|
this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->spec.size);
|
||||||
|
if (this->hidden->mixbuf == NULL) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
|
||||||
|
|
||||||
|
data_vaddr = (Uint8 *) linearAlloc(this->hidden->mixlen * NUM_BUFFERS);
|
||||||
|
if (data_vaddr == NULL) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_memset(data_vaddr, 0, this->hidden->mixlen * NUM_BUFFERS);
|
||||||
|
DSP_FlushDataCache(data_vaddr, this->hidden->mixlen * NUM_BUFFERS);
|
||||||
|
|
||||||
|
this->hidden->nextbuf = 0;
|
||||||
|
this->hidden->channels = this->spec.channels;
|
||||||
|
this->hidden->samplerate = this->spec.freq;
|
||||||
|
|
||||||
|
ndspChnReset(0);
|
||||||
|
|
||||||
|
ndspChnSetInterp(0, NDSP_INTERP_LINEAR);
|
||||||
|
ndspChnSetRate(0, this->spec.freq);
|
||||||
|
ndspChnSetFormat(0, this->hidden->format);
|
||||||
|
|
||||||
|
SDL_memset(mix, 0, sizeof(mix));
|
||||||
|
mix[0] = 1.0;
|
||||||
|
mix[1] = 1.0;
|
||||||
|
ndspChnSetMix(0, mix);
|
||||||
|
|
||||||
|
SDL_memset(this->hidden->waveBuf, 0, sizeof(ndspWaveBuf) * NUM_BUFFERS);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < NUM_BUFFERS; i++) {
|
||||||
|
this->hidden->waveBuf[i].data_vaddr = data_vaddr;
|
||||||
|
this->hidden->waveBuf[i].nsamples = this->hidden->mixlen / this->hidden->bytePerSample;
|
||||||
|
data_vaddr += this->hidden->mixlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup callback */
|
||||||
|
audio_device = this;
|
||||||
|
ndspSetCallback(AudioFrameFinished, this);
|
||||||
|
dspHook(&dsp_hook, N3DSAUD_DspHook);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
N3DSAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
|
||||||
|
{
|
||||||
|
/* Delay to make this sort of simulate real audio input. */
|
||||||
|
SDL_Delay((this->spec.samples * 1000) / this->spec.freq);
|
||||||
|
|
||||||
|
/* always return a full buffer of silence. */
|
||||||
|
SDL_memset(buffer, this->spec.silence, buflen);
|
||||||
|
return buflen;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DSAUDIO_PlayDevice(_THIS)
|
||||||
|
{
|
||||||
|
size_t nextbuf;
|
||||||
|
size_t sampleLen;
|
||||||
|
contextLock(this);
|
||||||
|
|
||||||
|
nextbuf = this->hidden->nextbuf;
|
||||||
|
sampleLen = this->hidden->mixlen;
|
||||||
|
|
||||||
|
if (this->hidden->isCancelled ||
|
||||||
|
this->hidden->waveBuf[nextbuf].status != NDSP_WBUF_FREE) {
|
||||||
|
contextUnlock(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->hidden->nextbuf = (nextbuf + 1) % NUM_BUFFERS;
|
||||||
|
|
||||||
|
contextUnlock(this);
|
||||||
|
|
||||||
|
memcpy((void *) this->hidden->waveBuf[nextbuf].data_vaddr,
|
||||||
|
this->hidden->mixbuf, sampleLen);
|
||||||
|
DSP_FlushDataCache(this->hidden->waveBuf[nextbuf].data_vaddr, sampleLen);
|
||||||
|
|
||||||
|
ndspChnWaveBufAdd(0, &this->hidden->waveBuf[nextbuf]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DSAUDIO_WaitDevice(_THIS)
|
||||||
|
{
|
||||||
|
contextLock(this);
|
||||||
|
while (!this->hidden->isCancelled &&
|
||||||
|
this->hidden->waveBuf[this->hidden->nextbuf].status != NDSP_WBUF_FREE) {
|
||||||
|
CondVar_Wait(&this->hidden->cv, &this->hidden->lock);
|
||||||
|
}
|
||||||
|
contextUnlock(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Uint8 *
|
||||||
|
N3DSAUDIO_GetDeviceBuf(_THIS)
|
||||||
|
{
|
||||||
|
return this->hidden->mixbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DSAUDIO_CloseDevice(_THIS)
|
||||||
|
{
|
||||||
|
contextLock(this);
|
||||||
|
|
||||||
|
dspUnhook(&dsp_hook);
|
||||||
|
ndspSetCallback(NULL, NULL);
|
||||||
|
|
||||||
|
if (!this->hidden->isCancelled) {
|
||||||
|
ndspChnReset(0);
|
||||||
|
memset(this->hidden->waveBuf, 0, sizeof(ndspWaveBuf) * NUM_BUFFERS);
|
||||||
|
CondVar_Broadcast(&this->hidden->cv);
|
||||||
|
}
|
||||||
|
|
||||||
|
contextUnlock(this);
|
||||||
|
|
||||||
|
ndspExit();
|
||||||
|
|
||||||
|
FreePrivateData(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DSAUDIO_ThreadInit(_THIS)
|
||||||
|
{
|
||||||
|
s32 current_priority;
|
||||||
|
svcGetThreadPriority(¤t_priority, CUR_THREAD_HANDLE);
|
||||||
|
current_priority--;
|
||||||
|
/* 0x18 is reserved for video, 0x30 is the default for main thread */
|
||||||
|
current_priority = SDL_clamp(current_priority, 0x19, 0x2F);
|
||||||
|
svcSetThreadPriority(CUR_THREAD_HANDLE, current_priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_bool
|
||||||
|
N3DSAUDIO_Init(SDL_AudioDriverImpl *impl)
|
||||||
|
{
|
||||||
|
/* Set the function pointers */
|
||||||
|
impl->OpenDevice = N3DSAUDIO_OpenDevice;
|
||||||
|
impl->PlayDevice = N3DSAUDIO_PlayDevice;
|
||||||
|
impl->WaitDevice = N3DSAUDIO_WaitDevice;
|
||||||
|
impl->GetDeviceBuf = N3DSAUDIO_GetDeviceBuf;
|
||||||
|
impl->CloseDevice = N3DSAUDIO_CloseDevice;
|
||||||
|
impl->ThreadInit = N3DSAUDIO_ThreadInit;
|
||||||
|
impl->LockDevice = N3DSAUD_LockAudio;
|
||||||
|
impl->UnlockDevice = N3DSAUD_UnlockAudio;
|
||||||
|
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
|
||||||
|
|
||||||
|
/* Should be possible, but micInit would fail */
|
||||||
|
impl->HasCaptureSupport = SDL_FALSE;
|
||||||
|
impl->CaptureFromDevice = N3DSAUDIO_CaptureFromDevice;
|
||||||
|
|
||||||
|
return SDL_TRUE; /* this audio target is available. */
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioBootStrap N3DSAUDIO_bootstrap = {
|
||||||
|
N3DSAUDIO_DRIVER_NAME,
|
||||||
|
"SDL N3DS audio driver",
|
||||||
|
N3DSAUDIO_Init,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans up all allocated memory, safe to call with null pointers
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
FreePrivateData(_THIS)
|
||||||
|
{
|
||||||
|
if (!this->hidden) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->hidden->waveBuf[0].data_vaddr) {
|
||||||
|
linearFree((void *) this->hidden->waveBuf[0].data_vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->hidden->mixbuf) {
|
||||||
|
SDL_free(this->hidden->mixbuf);
|
||||||
|
this->hidden->mixbuf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_free(this->hidden);
|
||||||
|
this->hidden = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
FindAudioFormat(_THIS)
|
||||||
|
{
|
||||||
|
SDL_bool found_valid_format = SDL_FALSE;
|
||||||
|
Uint16 test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||||
|
|
||||||
|
while (!found_valid_format && test_format) {
|
||||||
|
this->spec.format = test_format;
|
||||||
|
switch (test_format) {
|
||||||
|
case AUDIO_S8:
|
||||||
|
/* Signed 8-bit audio supported */
|
||||||
|
this->hidden->format = (this->spec.channels == 2) ? NDSP_FORMAT_STEREO_PCM8 : NDSP_FORMAT_MONO_PCM8;
|
||||||
|
this->hidden->isSigned = 1;
|
||||||
|
this->hidden->bytePerSample = this->spec.channels;
|
||||||
|
found_valid_format = SDL_TRUE;
|
||||||
|
break;
|
||||||
|
case AUDIO_S16:
|
||||||
|
/* Signed 16-bit audio supported */
|
||||||
|
this->hidden->format = (this->spec.channels == 2) ? NDSP_FORMAT_STEREO_PCM16 : NDSP_FORMAT_MONO_PCM16;
|
||||||
|
this->hidden->isSigned = 1;
|
||||||
|
this->hidden->bytePerSample = this->spec.channels * 2;
|
||||||
|
found_valid_format = SDL_TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
test_format = SDL_NextAudioFormat();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found_valid_format ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SDL_AUDIO_DRIVER_N3DS */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SDL_n3dsaudio_h_
|
||||||
|
#define _SDL_n3dsaudio_h_
|
||||||
|
|
||||||
|
#include <3ds.h>
|
||||||
|
|
||||||
|
/* Hidden "this" pointer for the audio functions */
|
||||||
|
#define _THIS SDL_AudioDevice *this
|
||||||
|
|
||||||
|
#define NUM_BUFFERS 2 /* -- Don't lower this! */
|
||||||
|
|
||||||
|
struct SDL_PrivateAudioData
|
||||||
|
{
|
||||||
|
/* Speaker data */
|
||||||
|
Uint8 *mixbuf;
|
||||||
|
Uint32 mixlen;
|
||||||
|
Uint32 format;
|
||||||
|
Uint32 samplerate;
|
||||||
|
Uint32 channels;
|
||||||
|
Uint8 bytePerSample;
|
||||||
|
Uint32 isSigned;
|
||||||
|
Uint32 nextbuf;
|
||||||
|
ndspWaveBuf waveBuf[NUM_BUFFERS];
|
||||||
|
LightLock lock;
|
||||||
|
CondVar cv;
|
||||||
|
SDL_bool isCancelled;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _SDL_n3dsaudio_h_ */
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -468,6 +468,8 @@ CPU_haveNEON(void)
|
||||||
return 1; /* ARMv8 always has non-optional NEON support. */
|
return 1; /* ARMv8 always has non-optional NEON support. */
|
||||||
#elif __VITA__
|
#elif __VITA__
|
||||||
return 1;
|
return 1;
|
||||||
|
#elif __3DS__
|
||||||
|
return 1;
|
||||||
#elif defined(__APPLE__) && defined(__ARM_ARCH) && (__ARM_ARCH >= 7)
|
#elif defined(__APPLE__) && defined(__ARM_ARCH) && (__ARM_ARCH >= 7)
|
||||||
/* (note that sysctlbyname("hw.optional.neon") doesn't work!) */
|
/* (note that sysctlbyname("hw.optional.neon") doesn't work!) */
|
||||||
return 1; /* all Apple ARMv7 chips and later have NEON. */
|
return 1; /* all Apple ARMv7 chips and later have NEON. */
|
||||||
|
|
|
@ -63,6 +63,8 @@
|
||||||
#define SDL_DYNAMIC_API 0 /* vitasdk doesn't support dynamic linking */
|
#define SDL_DYNAMIC_API 0 /* vitasdk doesn't support dynamic linking */
|
||||||
#elif defined(__NGAGE__)
|
#elif defined(__NGAGE__)
|
||||||
#define SDL_DYNAMIC_API 0 /* The N-Gage doesn't support dynamic linking either */
|
#define SDL_DYNAMIC_API 0 /* The N-Gage doesn't support dynamic linking either */
|
||||||
|
#elif defined(__3DS__)
|
||||||
|
#define SDL_DYNAMIC_API 0 /* devkitARM doesn't support dynamic linking */
|
||||||
#elif defined(DYNAPI_NEEDS_DLOPEN) && !defined(HAVE_DLOPEN)
|
#elif defined(DYNAPI_NEEDS_DLOPEN) && !defined(HAVE_DLOPEN)
|
||||||
#define SDL_DYNAMIC_API 0 /* we need dlopen(), but don't have it.... */
|
#define SDL_DYNAMIC_API 0 /* we need dlopen(), but don't have it.... */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -53,6 +53,10 @@
|
||||||
#include "cocoa/SDL_rwopsbundlesupport.h"
|
#include "cocoa/SDL_rwopsbundlesupport.h"
|
||||||
#endif /* __APPLE__ */
|
#endif /* __APPLE__ */
|
||||||
|
|
||||||
|
#ifdef __3DS__
|
||||||
|
#include "n3ds/SDL_rwopsromfs.h"
|
||||||
|
#endif /* __3DS__ */
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
#include "../core/android/SDL_android.h"
|
#include "../core/android/SDL_android.h"
|
||||||
#include "SDL_system.h"
|
#include "SDL_system.h"
|
||||||
|
@ -601,6 +605,8 @@ SDL_RWFromFile(const char *file, const char *mode)
|
||||||
#elif __WINRT__
|
#elif __WINRT__
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
fopen_s(&fp, file, mode);
|
fopen_s(&fp, file, mode);
|
||||||
|
#elif __3DS__
|
||||||
|
FILE *fp = N3DS_FileOpen(file, mode);
|
||||||
#else
|
#else
|
||||||
FILE *fp = fopen(file, mode);
|
FILE *fp = fopen(file, mode);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SDL_rwopsromfs.h"
|
||||||
|
|
||||||
|
/* Nintendo 3DS applications may embed resources in the executable. The
|
||||||
|
resources are stored in a special read-only partition prefixed with
|
||||||
|
'romfs:/'. As such, when opening a file, we should first try the romfs
|
||||||
|
unless sdmc is specifically mentionned.
|
||||||
|
*/
|
||||||
|
FILE *
|
||||||
|
N3DS_FileOpen(const char *file, const char *mode)
|
||||||
|
{
|
||||||
|
FILE *fp = NULL;
|
||||||
|
char romfs_path[4096];
|
||||||
|
|
||||||
|
/* romfs are read-only */
|
||||||
|
if (SDL_strchr(mode, 'r') == NULL) {
|
||||||
|
return fopen(file, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the path has an explicit prefix, we skip the guess work */
|
||||||
|
if (SDL_strncmp("romfs:/", file, 7) == 0 ||
|
||||||
|
SDL_strncmp("sdmc:/", file, 6) == 0) {
|
||||||
|
return fopen(file, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_snprintf(romfs_path, 4096, "romfs:/%s", file);
|
||||||
|
|
||||||
|
fp = fopen(romfs_path, mode);
|
||||||
|
if (fp == NULL) {
|
||||||
|
fp = fopen(file, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifndef SDL_rwopsromfs_h_
|
||||||
|
#define SDL_rwopsromfs_h_
|
||||||
|
|
||||||
|
FILE *N3DS_FileOpen(const char *file, const char *mode);
|
||||||
|
|
||||||
|
#endif /* SDL_rwopsromfs_h_ */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifdef SDL_FILESYSTEM_N3DS
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
/* System dependent filesystem routines */
|
||||||
|
|
||||||
|
#include <3ds.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "SDL_error.h"
|
||||||
|
#include "SDL_filesystem.h"
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE char *MakePrefPath(const char *app);
|
||||||
|
SDL_FORCE_INLINE int CreatePrefPathDir(const char *pref);
|
||||||
|
|
||||||
|
char *
|
||||||
|
SDL_GetBasePath(void)
|
||||||
|
{
|
||||||
|
char *base_path = SDL_strdup("romfs:/");
|
||||||
|
return base_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
SDL_GetPrefPath(const char *org, const char *app)
|
||||||
|
{
|
||||||
|
char *pref_path = NULL;
|
||||||
|
if (app == NULL) {
|
||||||
|
SDL_InvalidParamError("app");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pref_path = MakePrefPath(app);
|
||||||
|
if (CreatePrefPathDir(pref_path) < 0) {
|
||||||
|
SDL_free(pref_path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pref_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE char *
|
||||||
|
MakePrefPath(const char *app)
|
||||||
|
{
|
||||||
|
static const char *FMT = "/3ds/%s/";
|
||||||
|
size_t length = SDL_snprintf(NULL, 0, FMT, app) + 1;
|
||||||
|
char *pref_path = (char *) SDL_calloc(length, sizeof(char));
|
||||||
|
SDL_snprintf(pref_path, length, FMT, app);
|
||||||
|
return pref_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE int
|
||||||
|
CreatePrefPathDir(const char *pref)
|
||||||
|
{
|
||||||
|
int result = mkdir(pref, 0666);
|
||||||
|
|
||||||
|
if (result == -1 && errno != EEXIST) {
|
||||||
|
return SDL_SetError("Failed to create '%s' (%s)", pref, strerror(errno));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SDL_FILESYSTEM_N3DS */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -977,6 +977,9 @@ static const char *s_ControllerMappings [] =
|
||||||
#endif
|
#endif
|
||||||
#if SDL_JOYSTICK_VITA
|
#if SDL_JOYSTICK_VITA
|
||||||
"0000000050535669746120436f6e7400,PSVita Controller,crc:d598,a:b2,b:b1,back:b10,dpdown:b6,dpleft:b7,dpright:b9,dpup:b8,leftshoulder:b4,leftstick:b14,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,",
|
"0000000050535669746120436f6e7400,PSVita Controller,crc:d598,a:b2,b:b1,back:b10,dpdown:b6,dpleft:b7,dpright:b9,dpup:b8,leftshoulder:b4,leftstick:b14,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,",
|
||||||
|
#endif
|
||||||
|
#if SDL_JOYSTICK_N3DS
|
||||||
|
"4e696e74656e646f20334453206d6170,Nintendo 3DS,a:b0,b:b1,back:b2,dpdown:b7,dpleft:b5,dpright:b4,dpup:b6,leftshoulder:b9,leftstick:b14,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b15,rightx:a2,righty:a3,start:b3,x:b10,y:b11,",
|
||||||
#endif
|
#endif
|
||||||
"hidapi,*,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
|
"hidapi,*,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
|
||||||
NULL
|
NULL
|
||||||
|
|
|
@ -102,6 +102,9 @@ static SDL_JoystickDriver *SDL_joystick_drivers[] = {
|
||||||
#ifdef SDL_JOYSTICK_VITA
|
#ifdef SDL_JOYSTICK_VITA
|
||||||
&SDL_VITA_JoystickDriver,
|
&SDL_VITA_JoystickDriver,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef SDL_JOYSTICK_N3DS
|
||||||
|
&SDL_N3DS_JoystickDriver
|
||||||
|
#endif
|
||||||
#if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED)
|
#if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED)
|
||||||
&SDL_DUMMY_JoystickDriver
|
&SDL_DUMMY_JoystickDriver
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -238,6 +238,7 @@ extern SDL_JoystickDriver SDL_OS2_JoystickDriver;
|
||||||
extern SDL_JoystickDriver SDL_PS2_JoystickDriver;
|
extern SDL_JoystickDriver SDL_PS2_JoystickDriver;
|
||||||
extern SDL_JoystickDriver SDL_PSP_JoystickDriver;
|
extern SDL_JoystickDriver SDL_PSP_JoystickDriver;
|
||||||
extern SDL_JoystickDriver SDL_VITA_JoystickDriver;
|
extern SDL_JoystickDriver SDL_VITA_JoystickDriver;
|
||||||
|
extern SDL_JoystickDriver SDL_N3DS_JoystickDriver;
|
||||||
|
|
||||||
/* Ends C function definitions when using C++ */
|
/* Ends C function definitions when using C++ */
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -0,0 +1,367 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifdef SDL_JOYSTICK_N3DS
|
||||||
|
|
||||||
|
/* This is the N3DS implementation of the SDL joystick API */
|
||||||
|
|
||||||
|
#include <3ds.h>
|
||||||
|
|
||||||
|
#include "../SDL_sysjoystick.h"
|
||||||
|
#include "SDL_events.h"
|
||||||
|
|
||||||
|
#define NB_BUTTONS 23
|
||||||
|
|
||||||
|
/*
|
||||||
|
N3DS sticks values are roughly within +/-160
|
||||||
|
which is too small to pass the jitter tolerance.
|
||||||
|
This correction factor is applied to axis values
|
||||||
|
so they fit better in SDL's value range.
|
||||||
|
*/
|
||||||
|
#define CORRECTION_FACTOR_X SDL_JOYSTICK_AXIS_MAX / 160
|
||||||
|
|
||||||
|
/*
|
||||||
|
The Y axis needs to be flipped because SDL's "up"
|
||||||
|
is reversed compared to libctru's "up"
|
||||||
|
*/
|
||||||
|
#define CORRECTION_FACTOR_Y -CORRECTION_FACTOR_X
|
||||||
|
|
||||||
|
/*
|
||||||
|
Factors used to convert touchscreen coordinates to
|
||||||
|
SDL's 0-1 values. Note that the N3DS's screen is
|
||||||
|
internally in a portrait disposition so the
|
||||||
|
GSP_SCREEN constants are flipped.
|
||||||
|
*/
|
||||||
|
#define TOUCHPAD_SCALE_X 1.0f / GSP_SCREEN_HEIGHT_BOTTOM
|
||||||
|
#define TOUCHPAD_SCALE_Y 1.0f / GSP_SCREEN_WIDTH
|
||||||
|
|
||||||
|
typedef struct N3DSJoystickState
|
||||||
|
{
|
||||||
|
u32 kDown;
|
||||||
|
u32 kUp;
|
||||||
|
circlePosition circlePos;
|
||||||
|
circlePosition cStickPos;
|
||||||
|
accelVector acceleration;
|
||||||
|
angularRate rate;
|
||||||
|
} N3DSJoystickState;
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE void UpdateAxis(SDL_Joystick *joystick, N3DSJoystickState *previous_state);
|
||||||
|
SDL_FORCE_INLINE void UpdateButtons(SDL_Joystick *joystick, N3DSJoystickState *previous_state);
|
||||||
|
SDL_FORCE_INLINE void UpdateSensors(SDL_Joystick *joystick, N3DSJoystickState *previous_state);
|
||||||
|
SDL_FORCE_INLINE void UpdateTouch(SDL_Joystick *joystick);
|
||||||
|
|
||||||
|
static N3DSJoystickState current_state;
|
||||||
|
static SDL_bool sensors_enabled = SDL_FALSE;
|
||||||
|
|
||||||
|
static int
|
||||||
|
N3DS_JoystickInit(void)
|
||||||
|
{
|
||||||
|
hidInit();
|
||||||
|
HIDUSER_EnableAccelerometer();
|
||||||
|
HIDUSER_EnableGyroscope();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
N3DS_JoystickGetDeviceName(int device_index)
|
||||||
|
{
|
||||||
|
return "Nintendo 3DS";
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
N3DS_JoystickGetCount(void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_JoystickGUID
|
||||||
|
N3DS_JoystickGetDeviceGUID(int device_index)
|
||||||
|
{
|
||||||
|
/* GUID corresponds to the name "Nintendo 3DS map" */
|
||||||
|
SDL_JoystickGUID guid = { { 0x4e, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x6f, 0x20, 0x33, 0x44, 0x53, 0x20, 0x6d, 0x61, 0x70 } };
|
||||||
|
return guid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_JoystickID
|
||||||
|
N3DS_JoystickGetDeviceInstanceID(int device_index)
|
||||||
|
{
|
||||||
|
return device_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
N3DS_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
||||||
|
{
|
||||||
|
joystick->nbuttons = NB_BUTTONS;
|
||||||
|
joystick->naxes = 4;
|
||||||
|
joystick->nhats = 0;
|
||||||
|
joystick->instance_id = device_index;
|
||||||
|
|
||||||
|
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 0.0f);
|
||||||
|
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 0.0f);
|
||||||
|
SDL_PrivateJoystickAddTouchpad(joystick, 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
N3DS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
|
||||||
|
{
|
||||||
|
sensors_enabled = enabled;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DS_JoystickUpdate(SDL_Joystick *joystick)
|
||||||
|
{
|
||||||
|
N3DSJoystickState previous_state = current_state;
|
||||||
|
hidScanInput();
|
||||||
|
|
||||||
|
UpdateAxis(joystick, &previous_state);
|
||||||
|
UpdateButtons(joystick, &previous_state);
|
||||||
|
UpdateTouch(joystick);
|
||||||
|
|
||||||
|
if (sensors_enabled) {
|
||||||
|
UpdateSensors(joystick, &previous_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE void
|
||||||
|
UpdateAxis(SDL_Joystick *joystick, N3DSJoystickState *previous_state)
|
||||||
|
{
|
||||||
|
hidCircleRead(¤t_state.circlePos);
|
||||||
|
if (previous_state->circlePos.dx != current_state.circlePos.dx) {
|
||||||
|
SDL_PrivateJoystickAxis(joystick,
|
||||||
|
0,
|
||||||
|
current_state.circlePos.dx * CORRECTION_FACTOR_X);
|
||||||
|
}
|
||||||
|
if (previous_state->circlePos.dy != current_state.circlePos.dy) {
|
||||||
|
SDL_PrivateJoystickAxis(joystick,
|
||||||
|
1,
|
||||||
|
current_state.circlePos.dy * CORRECTION_FACTOR_Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
hidCstickRead(¤t_state.cStickPos);
|
||||||
|
if (previous_state->cStickPos.dx != current_state.cStickPos.dx) {
|
||||||
|
SDL_PrivateJoystickAxis(joystick,
|
||||||
|
2,
|
||||||
|
current_state.cStickPos.dx * CORRECTION_FACTOR_X);
|
||||||
|
}
|
||||||
|
if (previous_state->cStickPos.dy != current_state.cStickPos.dy) {
|
||||||
|
SDL_PrivateJoystickAxis(joystick,
|
||||||
|
3,
|
||||||
|
current_state.cStickPos.dy * CORRECTION_FACTOR_Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE void
|
||||||
|
UpdateButtons(SDL_Joystick *joystick, N3DSJoystickState *previous_state)
|
||||||
|
{
|
||||||
|
u32 updated_down, updated_up;
|
||||||
|
|
||||||
|
current_state.kDown = hidKeysDown();
|
||||||
|
updated_down = previous_state->kDown ^ current_state.kDown;
|
||||||
|
if (updated_down) {
|
||||||
|
for (Uint8 i = 0; i < joystick->nbuttons; i++) {
|
||||||
|
if (current_state.kDown & BIT(i) & updated_down) {
|
||||||
|
SDL_PrivateJoystickButton(joystick, i, SDL_PRESSED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
current_state.kUp = hidKeysUp();
|
||||||
|
updated_up = previous_state->kUp ^ current_state.kUp;
|
||||||
|
if (updated_up) {
|
||||||
|
for (Uint8 i = 0; i < joystick->nbuttons; i++) {
|
||||||
|
if (current_state.kUp & BIT(i) & updated_up) {
|
||||||
|
SDL_PrivateJoystickButton(joystick, i, SDL_RELEASED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE void
|
||||||
|
UpdateTouch(SDL_Joystick *joystick)
|
||||||
|
{
|
||||||
|
touchPosition touch;
|
||||||
|
Uint8 state;
|
||||||
|
hidTouchRead(&touch);
|
||||||
|
state = (touch.px == 0 && touch.py == 0) ? SDL_RELEASED : SDL_PRESSED;
|
||||||
|
|
||||||
|
SDL_PrivateJoystickTouchpad(joystick,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
state,
|
||||||
|
touch.px * TOUCHPAD_SCALE_X,
|
||||||
|
touch.py * TOUCHPAD_SCALE_Y,
|
||||||
|
state == SDL_PRESSED ? 1.0f : 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE void
|
||||||
|
UpdateSensors(SDL_Joystick *joystick, N3DSJoystickState *previous_state)
|
||||||
|
{
|
||||||
|
float data[3];
|
||||||
|
|
||||||
|
hidAccelRead(¤t_state.acceleration);
|
||||||
|
if (SDL_memcmp(&previous_state->acceleration, ¤t_state.acceleration, sizeof(accelVector)) != 0) {
|
||||||
|
SDL_memcpy(&previous_state->acceleration, ¤t_state.acceleration, sizeof(accelVector));
|
||||||
|
data[0] = (float) current_state.acceleration.x * SDL_STANDARD_GRAVITY;
|
||||||
|
data[1] = (float) current_state.acceleration.y * SDL_STANDARD_GRAVITY;
|
||||||
|
data[2] = (float) current_state.acceleration.z * SDL_STANDARD_GRAVITY;
|
||||||
|
SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, data, sizeof data);
|
||||||
|
}
|
||||||
|
|
||||||
|
hidGyroRead(¤t_state.rate);
|
||||||
|
if (SDL_memcmp(&previous_state->rate, ¤t_state.rate, sizeof(angularRate)) != 0) {
|
||||||
|
SDL_memcpy(&previous_state->rate, ¤t_state.rate, sizeof(angularRate));
|
||||||
|
data[0] = (float) current_state.rate.y;
|
||||||
|
data[1] = (float) current_state.rate.z;
|
||||||
|
data[2] = (float) current_state.rate.x;
|
||||||
|
SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, data, sizeof data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DS_JoystickClose(SDL_Joystick *joystick)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DS_JoystickQuit(void)
|
||||||
|
{
|
||||||
|
HIDUSER_DisableGyroscope();
|
||||||
|
HIDUSER_DisableAccelerometer();
|
||||||
|
hidExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_bool
|
||||||
|
N3DS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
|
||||||
|
{
|
||||||
|
/* There is only one possible mapping. */
|
||||||
|
*out = (SDL_GamepadMapping){
|
||||||
|
.a = { EMappingKind_Button, 0 },
|
||||||
|
.b = { EMappingKind_Button, 1 },
|
||||||
|
.x = { EMappingKind_Button, 10 },
|
||||||
|
.y = { EMappingKind_Button, 11 },
|
||||||
|
.back = { EMappingKind_Button, 2 },
|
||||||
|
.guide = { EMappingKind_None, 255 },
|
||||||
|
.start = { EMappingKind_Button, 3 },
|
||||||
|
.leftstick = { EMappingKind_None, 255 },
|
||||||
|
.rightstick = { EMappingKind_None, 255 },
|
||||||
|
.leftshoulder = { EMappingKind_Button, 9 },
|
||||||
|
.rightshoulder = { EMappingKind_Button, 8 },
|
||||||
|
.dpup = { EMappingKind_Button, 6 },
|
||||||
|
.dpdown = { EMappingKind_Button, 7 },
|
||||||
|
.dpleft = { EMappingKind_Button, 5 },
|
||||||
|
.dpright = { EMappingKind_Button, 4 },
|
||||||
|
.misc1 = { EMappingKind_None, 255 },
|
||||||
|
.paddle1 = { EMappingKind_None, 255 },
|
||||||
|
.paddle2 = { EMappingKind_None, 255 },
|
||||||
|
.paddle3 = { EMappingKind_None, 255 },
|
||||||
|
.paddle4 = { EMappingKind_None, 255 },
|
||||||
|
.leftx = { EMappingKind_Axis, 0 },
|
||||||
|
.lefty = { EMappingKind_Axis, 1 },
|
||||||
|
.rightx = { EMappingKind_Axis, 2 },
|
||||||
|
.righty = { EMappingKind_Axis, 3 },
|
||||||
|
.lefttrigger = { EMappingKind_Button, 14 },
|
||||||
|
.righttrigger = { EMappingKind_Button, 15 },
|
||||||
|
};
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DS_JoystickDetect(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
N3DS_JoystickGetDevicePath(int device_index)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
N3DS_JoystickGetDevicePlayerIndex(int device_index)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DS_JoystickSetDevicePlayerIndex(int device_index, int player_index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static Uint32
|
||||||
|
N3DS_JoystickGetCapabilities(SDL_Joystick *joystick)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
N3DS_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
|
||||||
|
{
|
||||||
|
return SDL_Unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
N3DS_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
|
||||||
|
{
|
||||||
|
return SDL_Unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
N3DS_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
|
||||||
|
{
|
||||||
|
return SDL_Unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
N3DS_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size)
|
||||||
|
{
|
||||||
|
return SDL_Unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_JoystickDriver SDL_N3DS_JoystickDriver = {
|
||||||
|
N3DS_JoystickInit,
|
||||||
|
N3DS_JoystickGetCount,
|
||||||
|
N3DS_JoystickDetect,
|
||||||
|
N3DS_JoystickGetDeviceName,
|
||||||
|
N3DS_JoystickGetDevicePath,
|
||||||
|
N3DS_JoystickGetDevicePlayerIndex,
|
||||||
|
N3DS_JoystickSetDevicePlayerIndex,
|
||||||
|
N3DS_JoystickGetDeviceGUID,
|
||||||
|
N3DS_JoystickGetDeviceInstanceID,
|
||||||
|
N3DS_JoystickOpen,
|
||||||
|
N3DS_JoystickRumble,
|
||||||
|
N3DS_JoystickRumbleTriggers,
|
||||||
|
N3DS_JoystickGetCapabilities,
|
||||||
|
N3DS_JoystickSetLED,
|
||||||
|
N3DS_JoystickSendEffect,
|
||||||
|
N3DS_JoystickSetSensorsEnabled,
|
||||||
|
N3DS_JoystickUpdate,
|
||||||
|
N3DS_JoystickClose,
|
||||||
|
N3DS_JoystickQuit,
|
||||||
|
N3DS_JoystickGetGamepadMapping
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* SDL_JOYSTICK_N3DS */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -27,7 +27,7 @@
|
||||||
#define libm_hidden_def(x)
|
#define libm_hidden_def(x)
|
||||||
#define strong_alias(x, y)
|
#define strong_alias(x, y)
|
||||||
|
|
||||||
#if !defined(__HAIKU__) && !defined(__PSP__) && !defined(__PS2__) /* already defined in a system header. */
|
#if !defined(__HAIKU__) && !defined(__PSP__) && !defined(__3DS__) && !defined(__PS2__) /* already defined in a system header. */
|
||||||
typedef unsigned int u_int32_t;
|
typedef unsigned int u_int32_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../SDL_syslocale.h"
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#include <3ds.h>
|
||||||
|
|
||||||
|
/* Used when the CFGU fails to work. */
|
||||||
|
#define BAD_LOCALE 255
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE u8 GetLocaleIndex(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_SYS_GetPreferredLocales(char *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
/* The 3DS only supports these 12 languages, only one can be active at a time */
|
||||||
|
static const char AVAILABLE_LOCALES[][6] = { "ja_JP", "en_US", "fr_FR", "de_DE",
|
||||||
|
"it_IT", "es_ES", "zn_CN", "ko_KR",
|
||||||
|
"nl_NL", "pt_PT", "ru_RU", "zh_TW" };
|
||||||
|
u8 current_locale = GetLocaleIndex();
|
||||||
|
if (current_locale != BAD_LOCALE) {
|
||||||
|
SDL_strlcpy(buf, AVAILABLE_LOCALES[current_locale], buflen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE u8
|
||||||
|
GetLocaleIndex(void)
|
||||||
|
{
|
||||||
|
u8 current_locale;
|
||||||
|
if (R_FAILED(cfguInit())) {
|
||||||
|
return BAD_LOCALE;
|
||||||
|
}
|
||||||
|
if (R_FAILED(CFGU_GetSystemLanguage(¤t_locale))) {
|
||||||
|
return BAD_LOCALE;
|
||||||
|
}
|
||||||
|
cfguExit();
|
||||||
|
return current_locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifdef __3DS__
|
||||||
|
|
||||||
|
#include "SDL_main.h"
|
||||||
|
#include <3ds.h>
|
||||||
|
|
||||||
|
#ifdef main
|
||||||
|
#undef main
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE void N3DS_Init(void);
|
||||||
|
SDL_FORCE_INLINE void N3DS_SetCPUSpeed(void);
|
||||||
|
SDL_FORCE_INLINE void N3DS_Quit(void);
|
||||||
|
|
||||||
|
#define HIGH_CLOCK 1
|
||||||
|
#define L2_CACHE 2
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
N3DS_Init();
|
||||||
|
SDL_SetMainReady();
|
||||||
|
result = SDL_main(argc, argv);
|
||||||
|
N3DS_Quit();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE void
|
||||||
|
N3DS_Init(void)
|
||||||
|
{
|
||||||
|
N3DS_SetCPUSpeed();
|
||||||
|
romfsInit();
|
||||||
|
gfxInit(GSP_RGBA8_OES, GSP_RGBA8_OES, false);
|
||||||
|
hidInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If available, enable L2 cache and high CPU clock */
|
||||||
|
SDL_FORCE_INLINE void
|
||||||
|
N3DS_SetCPUSpeed(void)
|
||||||
|
{
|
||||||
|
if (R_SUCCEEDED(ptmSysmInit())) {
|
||||||
|
if (R_SUCCEEDED(PTMSYSM_CheckNew3DS())) {
|
||||||
|
PTMSYSM_ConfigureNew3DSCPU(HIGH_CLOCK | L2_CACHE);
|
||||||
|
}
|
||||||
|
ptmSysmExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE void
|
||||||
|
N3DS_Quit(void)
|
||||||
|
{
|
||||||
|
hidExit();
|
||||||
|
gfxExit();
|
||||||
|
romfsExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __3DS__ */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -71,6 +71,9 @@ static SDL_GetPowerInfo_Impl implementations[] = {
|
||||||
#ifdef SDL_POWER_VITA /* handles PSVita. */
|
#ifdef SDL_POWER_VITA /* handles PSVita. */
|
||||||
SDL_GetPowerInfo_VITA,
|
SDL_GetPowerInfo_VITA,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef SDL_POWER_N3DS /* handles N3DS. */
|
||||||
|
SDL_GetPowerInfo_N3DS,
|
||||||
|
#endif
|
||||||
#ifdef SDL_POWER_WINRT /* handles WinRT */
|
#ifdef SDL_POWER_WINRT /* handles WinRT */
|
||||||
SDL_GetPowerInfo_WinRT,
|
SDL_GetPowerInfo_WinRT,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,6 +39,7 @@ SDL_bool SDL_GetPowerInfo_Haiku(SDL_PowerState *, int *, int *);
|
||||||
SDL_bool SDL_GetPowerInfo_Android(SDL_PowerState *, int *, int *);
|
SDL_bool SDL_GetPowerInfo_Android(SDL_PowerState *, int *, int *);
|
||||||
SDL_bool SDL_GetPowerInfo_PSP(SDL_PowerState *, int *, int *);
|
SDL_bool SDL_GetPowerInfo_PSP(SDL_PowerState *, int *, int *);
|
||||||
SDL_bool SDL_GetPowerInfo_VITA(SDL_PowerState *, int *, int *);
|
SDL_bool SDL_GetPowerInfo_VITA(SDL_PowerState *, int *, int *);
|
||||||
|
SDL_bool SDL_GetPowerInfo_N3DS(SDL_PowerState *, int *, int *);
|
||||||
SDL_bool SDL_GetPowerInfo_WinRT(SDL_PowerState *, int *, int *);
|
SDL_bool SDL_GetPowerInfo_WinRT(SDL_PowerState *, int *, int *);
|
||||||
SDL_bool SDL_GetPowerInfo_Emscripten(SDL_PowerState *, int *, int *);
|
SDL_bool SDL_GetPowerInfo_Emscripten(SDL_PowerState *, int *, int *);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#if !defined(SDL_POWER_DISABLED) && defined(SDL_POWER_N3DS)
|
||||||
|
|
||||||
|
#include <3ds.h>
|
||||||
|
|
||||||
|
#include "SDL_error.h"
|
||||||
|
#include "SDL_power.h"
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE SDL_PowerState GetPowerState(void);
|
||||||
|
SDL_FORCE_INLINE int ReadStateFromPTMU(bool *is_plugged, u8 *is_charging);
|
||||||
|
SDL_FORCE_INLINE int GetBatteryPercentage(void);
|
||||||
|
|
||||||
|
#define BATTERY_PERCENT_REG 0xB
|
||||||
|
#define BATTERY_PERCENT_REG_SIZE 2
|
||||||
|
|
||||||
|
SDL_bool
|
||||||
|
SDL_GetPowerInfo_N3DS(SDL_PowerState *state, int *seconds, int *percent)
|
||||||
|
{
|
||||||
|
*state = GetPowerState();
|
||||||
|
*percent = GetBatteryPercentage();
|
||||||
|
*seconds = -1; /* libctru doesn't provide a way to estimate battery life */
|
||||||
|
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE SDL_PowerState
|
||||||
|
GetPowerState(void)
|
||||||
|
{
|
||||||
|
bool is_plugged;
|
||||||
|
u8 is_charging;
|
||||||
|
|
||||||
|
if (ReadStateFromPTMU(&is_plugged, &is_charging) < 0) {
|
||||||
|
return SDL_POWERSTATE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_charging) {
|
||||||
|
return SDL_POWERSTATE_CHARGING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_plugged) {
|
||||||
|
return SDL_POWERSTATE_CHARGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SDL_POWERSTATE_ON_BATTERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE int
|
||||||
|
ReadStateFromPTMU(bool *is_plugged, u8 *is_charging)
|
||||||
|
{
|
||||||
|
if (R_FAILED(ptmuInit())) {
|
||||||
|
return SDL_SetError("Failed to initialise PTMU service");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_FAILED(PTMU_GetAdapterState(is_plugged))) {
|
||||||
|
ptmuExit();
|
||||||
|
return SDL_SetError("Failed to read adapter state");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_FAILED(PTMU_GetBatteryChargeState(is_charging))) {
|
||||||
|
ptmuExit();
|
||||||
|
return SDL_SetError("Failed to read battery charge state");
|
||||||
|
}
|
||||||
|
|
||||||
|
ptmuExit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE int
|
||||||
|
GetBatteryPercentage(void)
|
||||||
|
{
|
||||||
|
u8 data[BATTERY_PERCENT_REG_SIZE];
|
||||||
|
|
||||||
|
if (R_FAILED(mcuHwcInit())) {
|
||||||
|
return SDL_SetError("Failed to initialise mcuHwc service");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_FAILED(MCUHWC_ReadRegister(BATTERY_PERCENT_REG, data, BATTERY_PERCENT_REG_SIZE))) {
|
||||||
|
mcuHwcExit();
|
||||||
|
return SDL_SetError("Failed to read battery register");
|
||||||
|
}
|
||||||
|
|
||||||
|
mcuHwcExit();
|
||||||
|
|
||||||
|
return (int) SDL_round(data[0] + data[1] / 256.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !SDL_POWER_DISABLED && SDL_POWER_N3DS */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -38,6 +38,8 @@
|
||||||
#include "psp/SDL_systhread_c.h"
|
#include "psp/SDL_systhread_c.h"
|
||||||
#elif SDL_THREAD_VITA
|
#elif SDL_THREAD_VITA
|
||||||
#include "vita/SDL_systhread_c.h"
|
#include "vita/SDL_systhread_c.h"
|
||||||
|
#elif SDL_THREAD_N3DS
|
||||||
|
#include "n3ds/SDL_systhread_c.h"
|
||||||
#elif SDL_THREAD_STDCPP
|
#elif SDL_THREAD_STDCPP
|
||||||
#include "stdcpp/SDL_systhread_c.h"
|
#include "stdcpp/SDL_systhread_c.h"
|
||||||
#elif SDL_THREAD_OS2
|
#elif SDL_THREAD_OS2
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifdef SDL_THREAD_N3DS
|
||||||
|
|
||||||
|
/* An implementation of condition variables using libctru's CondVar */
|
||||||
|
|
||||||
|
#include "SDL_sysmutex_c.h"
|
||||||
|
|
||||||
|
struct SDL_cond
|
||||||
|
{
|
||||||
|
CondVar cond_variable;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Create a condition variable */
|
||||||
|
SDL_cond *
|
||||||
|
SDL_CreateCond(void)
|
||||||
|
{
|
||||||
|
SDL_cond *cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
|
||||||
|
if (cond) {
|
||||||
|
CondVar_Init(&cond->cond_variable);
|
||||||
|
} else {
|
||||||
|
SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
return cond;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Destroy a condition variable */
|
||||||
|
void
|
||||||
|
SDL_DestroyCond(SDL_cond *cond)
|
||||||
|
{
|
||||||
|
if (cond) {
|
||||||
|
SDL_free(cond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart one of the threads that are waiting on the condition variable */
|
||||||
|
int
|
||||||
|
SDL_CondSignal(SDL_cond *cond)
|
||||||
|
{
|
||||||
|
if (!cond) {
|
||||||
|
return SDL_SetError("Passed a NULL condition variable");
|
||||||
|
}
|
||||||
|
|
||||||
|
CondVar_Signal(&cond->cond_variable);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart all threads that are waiting on the condition variable */
|
||||||
|
int
|
||||||
|
SDL_CondBroadcast(SDL_cond *cond)
|
||||||
|
{
|
||||||
|
if (!cond) {
|
||||||
|
return SDL_SetError("Passed a NULL condition variable");
|
||||||
|
}
|
||||||
|
|
||||||
|
CondVar_Broadcast(&cond->cond_variable);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait on the condition variable for at most 'ms' milliseconds.
|
||||||
|
The mutex must be locked before entering this function!
|
||||||
|
The mutex is unlocked during the wait, and locked again after the wait.
|
||||||
|
|
||||||
|
Typical use:
|
||||||
|
|
||||||
|
Thread A:
|
||||||
|
SDL_LockMutex(lock);
|
||||||
|
while ( ! condition ) {
|
||||||
|
SDL_CondWait(cond, lock);
|
||||||
|
}
|
||||||
|
SDL_UnlockMutex(lock);
|
||||||
|
|
||||||
|
Thread B:
|
||||||
|
SDL_LockMutex(lock);
|
||||||
|
...
|
||||||
|
condition = true;
|
||||||
|
...
|
||||||
|
SDL_CondSignal(cond);
|
||||||
|
SDL_UnlockMutex(lock);
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
|
||||||
|
{
|
||||||
|
Result res;
|
||||||
|
|
||||||
|
if (!cond) {
|
||||||
|
return SDL_SetError("Passed a NULL condition variable");
|
||||||
|
}
|
||||||
|
if (!mutex) {
|
||||||
|
return SDL_SetError("Passed a NULL mutex");
|
||||||
|
}
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
if (ms == SDL_MUTEX_MAXWAIT) {
|
||||||
|
CondVar_Wait(&cond->cond_variable, &mutex->lock.lock);
|
||||||
|
} else {
|
||||||
|
res = CondVar_WaitTimeout(&cond->cond_variable, &mutex->lock.lock,
|
||||||
|
(s64) ms * 1000000LL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return R_SUCCEEDED(res) ? 0 : SDL_MUTEX_TIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait on the condition variable forever */
|
||||||
|
int
|
||||||
|
SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
|
||||||
|
{
|
||||||
|
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SDL_THREAD_N3DS */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifdef SDL_THREAD_N3DS
|
||||||
|
|
||||||
|
/* An implementation of mutexes using libctru's RecursiveLock */
|
||||||
|
|
||||||
|
#include "SDL_sysmutex_c.h"
|
||||||
|
|
||||||
|
/* Create a mutex */
|
||||||
|
SDL_mutex *
|
||||||
|
SDL_CreateMutex(void)
|
||||||
|
{
|
||||||
|
SDL_mutex *mutex;
|
||||||
|
|
||||||
|
/* Allocate mutex memory */
|
||||||
|
mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
|
||||||
|
if (mutex) {
|
||||||
|
RecursiveLock_Init(&mutex->lock);
|
||||||
|
} else {
|
||||||
|
SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
return mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the mutex */
|
||||||
|
void
|
||||||
|
SDL_DestroyMutex(SDL_mutex *mutex)
|
||||||
|
{
|
||||||
|
if (mutex) {
|
||||||
|
SDL_free(mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lock the mutex */
|
||||||
|
int
|
||||||
|
SDL_LockMutex(SDL_mutex *mutex)
|
||||||
|
{
|
||||||
|
if (mutex == NULL) {
|
||||||
|
return SDL_SetError("Passed a NULL mutex");
|
||||||
|
}
|
||||||
|
|
||||||
|
RecursiveLock_Lock(&mutex->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try Lock the mutex */
|
||||||
|
int
|
||||||
|
SDL_TryLockMutex(SDL_mutex *mutex)
|
||||||
|
{
|
||||||
|
if (mutex == NULL) {
|
||||||
|
return SDL_SetError("Passed a NULL mutex");
|
||||||
|
}
|
||||||
|
|
||||||
|
return RecursiveLock_TryLock(&mutex->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlock the mutex */
|
||||||
|
int
|
||||||
|
SDL_mutexV(SDL_mutex *mutex)
|
||||||
|
{
|
||||||
|
if (mutex == NULL) {
|
||||||
|
return SDL_SetError("Passed a NULL mutex");
|
||||||
|
}
|
||||||
|
|
||||||
|
RecursiveLock_Unlock(&mutex->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SDL_THREAD_N3DS */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifndef SDL_sysmutex_c_h_
|
||||||
|
#define SDL_sysmutex_c_h_
|
||||||
|
|
||||||
|
#include <3ds.h>
|
||||||
|
|
||||||
|
#include "SDL_mutex.h"
|
||||||
|
|
||||||
|
struct SDL_mutex
|
||||||
|
{
|
||||||
|
RecursiveLock lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* SDL_sysmutex_c_h */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifdef SDL_THREAD_N3DS
|
||||||
|
|
||||||
|
/* An implementation of semaphores using libctru's LightSemaphore */
|
||||||
|
|
||||||
|
#include <3ds.h>
|
||||||
|
|
||||||
|
#include "SDL_thread.h"
|
||||||
|
|
||||||
|
struct SDL_semaphore
|
||||||
|
{
|
||||||
|
LightSemaphore semaphore;
|
||||||
|
};
|
||||||
|
|
||||||
|
SDL_sem *
|
||||||
|
SDL_CreateSemaphore(Uint32 initial_value)
|
||||||
|
{
|
||||||
|
SDL_sem *sem;
|
||||||
|
|
||||||
|
if (initial_value > SDL_MAX_SINT16) {
|
||||||
|
SDL_SetError("Initial semaphore value too high for this platform");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sem = (SDL_sem *) SDL_malloc(sizeof(*sem));
|
||||||
|
if (!sem) {
|
||||||
|
SDL_OutOfMemory();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
LightSemaphore_Init(&sem->semaphore, initial_value, SDL_MAX_SINT16);
|
||||||
|
|
||||||
|
return sem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WARNING:
|
||||||
|
You cannot call this function when another thread is using the semaphore.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
SDL_DestroySemaphore(SDL_sem *sem)
|
||||||
|
{
|
||||||
|
if (sem) {
|
||||||
|
SDL_free(sem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SDL_SemTryWait(SDL_sem *sem)
|
||||||
|
{
|
||||||
|
if (!sem) {
|
||||||
|
return SDL_SetError("Passed a NULL semaphore");
|
||||||
|
}
|
||||||
|
|
||||||
|
return SDL_SemWaitTimeout(sem, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
if (!sem) {
|
||||||
|
return SDL_SetError("Passed a NULL semaphore");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout == SDL_MUTEX_MAXWAIT) {
|
||||||
|
LightSemaphore_Acquire(&sem->semaphore, 1);
|
||||||
|
retval = 0;
|
||||||
|
} else {
|
||||||
|
int return_code = LightSemaphore_TryAcquire(&sem->semaphore, 1);
|
||||||
|
if (return_code != 0) {
|
||||||
|
for (u32 i = 0; i < timeout; i++) {
|
||||||
|
svcSleepThread(1000000LL);
|
||||||
|
return_code = LightSemaphore_TryAcquire(&sem->semaphore, 1);
|
||||||
|
if (return_code == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retval = return_code != 0 ? SDL_MUTEX_TIMEDOUT : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SDL_SemWait(SDL_sem *sem)
|
||||||
|
{
|
||||||
|
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint32
|
||||||
|
SDL_SemValue(SDL_sem *sem)
|
||||||
|
{
|
||||||
|
if (!sem) {
|
||||||
|
return SDL_SetError("Passed a NULL semaphore");
|
||||||
|
}
|
||||||
|
return sem->semaphore.current_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SDL_SemPost(SDL_sem *sem)
|
||||||
|
{
|
||||||
|
if (!sem) {
|
||||||
|
return SDL_SetError("Passed a NULL semaphore");
|
||||||
|
}
|
||||||
|
LightSemaphore_Release(&sem->semaphore, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SDL_THREAD_N3DS */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifdef SDL_THREAD_N3DS
|
||||||
|
|
||||||
|
/* Thread management routines for SDL */
|
||||||
|
|
||||||
|
#include "../SDL_systhread.h"
|
||||||
|
|
||||||
|
/* N3DS has very limited RAM (128MB), so we put a limit on thread stack size. */
|
||||||
|
#define N3DS_THREAD_STACK_SIZE_MAX (16 * 1024)
|
||||||
|
#define N3DS_THREAD_STACK_SIZE_DEFAULT (4 * 1024)
|
||||||
|
|
||||||
|
#define N3DS_THREAD_PRIORITY_LOW 0x3F /**< Minimum priority */
|
||||||
|
#define N3DS_THREAD_PRIORITY_MEDIUM 0x2F /**< Slightly higher than main thread (0x30) */
|
||||||
|
#define N3DS_THREAD_PRIORITY_HIGH 0x19 /**< High priority for non-video work */
|
||||||
|
#define N3DS_THREAD_PRIORITY_TIME_CRITICAL 0x18 /**< Highest priority */
|
||||||
|
|
||||||
|
static size_t GetStackSize(size_t requested_size);
|
||||||
|
|
||||||
|
static void
|
||||||
|
ThreadEntry(void *arg)
|
||||||
|
{
|
||||||
|
SDL_RunThread((SDL_Thread *) arg);
|
||||||
|
threadExit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
|
||||||
|
#error "SDL_PASSED_BEGINTHREAD_ENDTHREAD is not supported on N3DS"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
SDL_SYS_CreateThread(SDL_Thread *thread)
|
||||||
|
{
|
||||||
|
s32 priority = N3DS_THREAD_PRIORITY_MEDIUM;
|
||||||
|
size_t stack_size = GetStackSize(thread->stacksize);
|
||||||
|
|
||||||
|
thread->handle = threadCreate(ThreadEntry,
|
||||||
|
thread,
|
||||||
|
stack_size,
|
||||||
|
priority,
|
||||||
|
-1,
|
||||||
|
false);
|
||||||
|
|
||||||
|
if (thread->handle == NULL) {
|
||||||
|
return SDL_SetError("Couldn't create thread");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
GetStackSize(size_t requested_size)
|
||||||
|
{
|
||||||
|
if (requested_size == 0) {
|
||||||
|
return N3DS_THREAD_STACK_SIZE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requested_size > N3DS_THREAD_STACK_SIZE_MAX) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_SYSTEM,
|
||||||
|
"Requested a thread size of %zu,"
|
||||||
|
" falling back to the maximum supported of %zu\n",
|
||||||
|
requested_size,
|
||||||
|
N3DS_THREAD_STACK_SIZE_MAX);
|
||||||
|
requested_size = N3DS_THREAD_STACK_SIZE_MAX;
|
||||||
|
}
|
||||||
|
return requested_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_SYS_SetupThread(const char *name)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_threadID
|
||||||
|
SDL_ThreadID(void)
|
||||||
|
{
|
||||||
|
u32 thread_ID = 0;
|
||||||
|
svcGetThreadId(&thread_ID, CUR_THREAD_HANDLE);
|
||||||
|
return (SDL_threadID) thread_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SDL_SYS_SetThreadPriority(SDL_ThreadPriority sdl_priority)
|
||||||
|
{
|
||||||
|
s32 svc_priority;
|
||||||
|
switch (sdl_priority) {
|
||||||
|
case SDL_THREAD_PRIORITY_LOW:
|
||||||
|
svc_priority = N3DS_THREAD_PRIORITY_LOW;
|
||||||
|
break;
|
||||||
|
case SDL_THREAD_PRIORITY_NORMAL:
|
||||||
|
svc_priority = N3DS_THREAD_PRIORITY_MEDIUM;
|
||||||
|
break;
|
||||||
|
case SDL_THREAD_PRIORITY_HIGH:
|
||||||
|
svc_priority = N3DS_THREAD_PRIORITY_HIGH;
|
||||||
|
break;
|
||||||
|
case SDL_THREAD_PRIORITY_TIME_CRITICAL:
|
||||||
|
svc_priority = N3DS_THREAD_PRIORITY_TIME_CRITICAL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
svc_priority = N3DS_THREAD_PRIORITY_MEDIUM;
|
||||||
|
}
|
||||||
|
return (int) svcSetThreadPriority(CUR_THREAD_HANDLE, svc_priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_SYS_WaitThread(SDL_Thread *thread)
|
||||||
|
{
|
||||||
|
Result res = threadJoin(thread->handle, U64_MAX);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Detached threads can be waited on, but should NOT be cleaned manually
|
||||||
|
as it would result in a fatal error.
|
||||||
|
*/
|
||||||
|
if (R_SUCCEEDED(res) && SDL_AtomicGet(&thread->state) != SDL_THREAD_STATE_DETACHED) {
|
||||||
|
threadFree(thread->handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_SYS_DetachThread(SDL_Thread *thread)
|
||||||
|
{
|
||||||
|
threadDetach(thread->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SDL_THREAD_N3DS */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifndef SDL_systhread_c_h_
|
||||||
|
#define SDL_systhread_c_h_
|
||||||
|
|
||||||
|
#include <3ds.h>
|
||||||
|
|
||||||
|
typedef Thread SYS_ThreadHandle;
|
||||||
|
|
||||||
|
#endif /* SDL_systhread_c_h_ */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifdef SDL_TIMER_N3DS
|
||||||
|
|
||||||
|
#include <3ds.h>
|
||||||
|
|
||||||
|
static SDL_bool ticks_started = SDL_FALSE;
|
||||||
|
static u64 start_tick;
|
||||||
|
|
||||||
|
#define NSEC_PER_MSEC 1000000ULL
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_TicksInit(void)
|
||||||
|
{
|
||||||
|
if (ticks_started) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ticks_started = SDL_TRUE;
|
||||||
|
|
||||||
|
start_tick = svcGetSystemTick();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_TicksQuit(void)
|
||||||
|
{
|
||||||
|
ticks_started = SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint64
|
||||||
|
SDL_GetTicks64(void)
|
||||||
|
{
|
||||||
|
u64 elapsed;
|
||||||
|
if (!ticks_started) {
|
||||||
|
SDL_TicksInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
elapsed = svcGetSystemTick() - start_tick;
|
||||||
|
return elapsed / CPU_TICKS_PER_MSEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint64
|
||||||
|
SDL_GetPerformanceCounter(void)
|
||||||
|
{
|
||||||
|
return svcGetSystemTick();
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint64
|
||||||
|
SDL_GetPerformanceFrequency(void)
|
||||||
|
{
|
||||||
|
return SYSCLOCK_ARM11;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_Delay(Uint32 ms)
|
||||||
|
{
|
||||||
|
svcSleepThread(ms * NSEC_PER_MSEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SDL_TIMER_N3DS */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -461,6 +461,7 @@ extern VideoBootStrap PS2_bootstrap;
|
||||||
extern VideoBootStrap PSP_bootstrap;
|
extern VideoBootStrap PSP_bootstrap;
|
||||||
extern VideoBootStrap VITA_bootstrap;
|
extern VideoBootStrap VITA_bootstrap;
|
||||||
extern VideoBootStrap RISCOS_bootstrap;
|
extern VideoBootStrap RISCOS_bootstrap;
|
||||||
|
extern VideoBootStrap N3DS_bootstrap;
|
||||||
extern VideoBootStrap RPI_bootstrap;
|
extern VideoBootStrap RPI_bootstrap;
|
||||||
extern VideoBootStrap KMSDRM_bootstrap;
|
extern VideoBootStrap KMSDRM_bootstrap;
|
||||||
extern VideoBootStrap KMSDRM_LEGACY_bootstrap;
|
extern VideoBootStrap KMSDRM_LEGACY_bootstrap;
|
||||||
|
|
|
@ -100,6 +100,9 @@ static VideoBootStrap *bootstrap[] = {
|
||||||
#if SDL_VIDEO_DRIVER_VITA
|
#if SDL_VIDEO_DRIVER_VITA
|
||||||
&VITA_bootstrap,
|
&VITA_bootstrap,
|
||||||
#endif
|
#endif
|
||||||
|
#if SDL_VIDEO_DRIVER_N3DS
|
||||||
|
&N3DS_bootstrap,
|
||||||
|
#endif
|
||||||
#if SDL_VIDEO_DRIVER_KMSDRM
|
#if SDL_VIDEO_DRIVER_KMSDRM
|
||||||
&KMSDRM_bootstrap,
|
&KMSDRM_bootstrap,
|
||||||
#endif
|
#endif
|
||||||
|
@ -1498,7 +1501,7 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CREATE_FLAGS \
|
#define CREATE_FLAGS \
|
||||||
(SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED | SDL_WINDOW_METAL)
|
(SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED | SDL_WINDOW_METAL | SDL_WINDOW_N3DS_BOTTOM)
|
||||||
|
|
||||||
static SDL_INLINE SDL_bool
|
static SDL_INLINE SDL_bool
|
||||||
IsAcceptingDragAndDrop(void)
|
IsAcceptingDragAndDrop(void)
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifdef SDL_VIDEO_DRIVER_N3DS
|
||||||
|
|
||||||
|
/* Pumping the events for the Home and Power buttons. */
|
||||||
|
|
||||||
|
#include <3ds.h>
|
||||||
|
|
||||||
|
#include "../../events/SDL_events_c.h"
|
||||||
|
#include "SDL_n3dsevents_c.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
N3DS_PumpEvents(_THIS)
|
||||||
|
{
|
||||||
|
if (!aptMainLoop()) {
|
||||||
|
SDL_Event ev;
|
||||||
|
ev.type = SDL_QUIT;
|
||||||
|
SDL_PushEvent(&ev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SDL_VIDEO_DRIVER_N3DS */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SDL_n3dsevents_c_h_
|
||||||
|
#define SDL_n3dsevents_c_h_
|
||||||
|
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
extern void N3DS_PumpEvents(_THIS);
|
||||||
|
|
||||||
|
#endif /* SDL_n3dsevents_c_h_ */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifdef SDL_VIDEO_DRIVER_N3DS
|
||||||
|
|
||||||
|
#include "../SDL_sysvideo.h"
|
||||||
|
#include "SDL_n3dsframebuffer_c.h"
|
||||||
|
#include "SDL_n3dsvideo.h"
|
||||||
|
|
||||||
|
#define N3DS_SURFACE "_SDL_N3DSSurface"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
} Dimensions;
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE void FreePreviousWindowFramebuffer(SDL_Window *window);
|
||||||
|
SDL_FORCE_INLINE SDL_Surface *CreateNewWindowFramebuffer(SDL_Window *window);
|
||||||
|
SDL_FORCE_INLINE void CopyFramebuffertoN3DS(u32 *dest, const Dimensions dest_dim, const u32 *source, const Dimensions source_dim);
|
||||||
|
SDL_FORCE_INLINE int GetDestOffset(int x, int y, int dest_width);
|
||||||
|
SDL_FORCE_INLINE int GetSourceOffset(int x, int y, int source_width);
|
||||||
|
SDL_FORCE_INLINE void FlushN3DSBuffer(const void *buffer, u32 bufsize, gfxScreen_t screen);
|
||||||
|
|
||||||
|
int
|
||||||
|
SDL_N3DS_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format, void **pixels, int *pitch)
|
||||||
|
{
|
||||||
|
SDL_Surface *framebuffer;
|
||||||
|
|
||||||
|
FreePreviousWindowFramebuffer(window);
|
||||||
|
framebuffer = CreateNewWindowFramebuffer(window);
|
||||||
|
|
||||||
|
if (!framebuffer) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetWindowData(window, N3DS_SURFACE, framebuffer);
|
||||||
|
*format = FRAMEBUFFER_FORMAT;
|
||||||
|
*pixels = framebuffer->pixels;
|
||||||
|
*pitch = framebuffer->pitch;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE void
|
||||||
|
FreePreviousWindowFramebuffer(SDL_Window *window)
|
||||||
|
{
|
||||||
|
SDL_Surface *surface = (SDL_Surface *) SDL_GetWindowData(window, N3DS_SURFACE);
|
||||||
|
SDL_FreeSurface(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE SDL_Surface *
|
||||||
|
CreateNewWindowFramebuffer(SDL_Window *window)
|
||||||
|
{
|
||||||
|
int w, h, bpp;
|
||||||
|
Uint32 Rmask, Gmask, Bmask, Amask;
|
||||||
|
SDL_PixelFormatEnumToMasks(FRAMEBUFFER_FORMAT, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
|
||||||
|
SDL_GetWindowSize(window, &w, &h);
|
||||||
|
return SDL_CreateRGBSurface(0, w, h, bpp, Rmask, Gmask, Bmask, Amask);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SDL_N3DS_UpdateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects, int numrects)
|
||||||
|
{
|
||||||
|
SDL_WindowData *drv_data = (SDL_WindowData *) window->driverdata;
|
||||||
|
SDL_Surface *surface;
|
||||||
|
u16 width, height;
|
||||||
|
u32 *framebuffer;
|
||||||
|
u32 bufsize;
|
||||||
|
|
||||||
|
surface = (SDL_Surface *) SDL_GetWindowData(window, N3DS_SURFACE);
|
||||||
|
if (!surface) {
|
||||||
|
return SDL_SetError("%s: Unable to get the window surface.", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the N3DS internal framebuffer and its size */
|
||||||
|
framebuffer = (u32 *) gfxGetFramebuffer(drv_data->screen, GFX_LEFT, &width, &height);
|
||||||
|
bufsize = width * height * 4;
|
||||||
|
|
||||||
|
CopyFramebuffertoN3DS(framebuffer, (Dimensions){ width, height },
|
||||||
|
surface->pixels, (Dimensions){ surface->w, surface->h });
|
||||||
|
FlushN3DSBuffer(framebuffer, bufsize, drv_data->screen);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE void
|
||||||
|
CopyFramebuffertoN3DS(u32 *dest, const Dimensions dest_dim, const u32 *source, const Dimensions source_dim)
|
||||||
|
{
|
||||||
|
int rows = SDL_min(dest_dim.width, source_dim.height);
|
||||||
|
int cols = SDL_min(dest_dim.height, source_dim.width);
|
||||||
|
for (int y = 0; y < rows; ++y) {
|
||||||
|
for (int x = 0; x < cols; ++x) {
|
||||||
|
SDL_memcpy(
|
||||||
|
dest + GetDestOffset(x, y, dest_dim.width),
|
||||||
|
source + GetSourceOffset(x, y, source_dim.width),
|
||||||
|
4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE int
|
||||||
|
GetDestOffset(int x, int y, int dest_width)
|
||||||
|
{
|
||||||
|
return dest_width - y - 1 + dest_width * x;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE int
|
||||||
|
GetSourceOffset(int x, int y, int source_width)
|
||||||
|
{
|
||||||
|
return x + y * source_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE void
|
||||||
|
FlushN3DSBuffer(const void *buffer, u32 bufsize, gfxScreen_t screen)
|
||||||
|
{
|
||||||
|
GSPGPU_FlushDataCache(buffer, bufsize);
|
||||||
|
gfxScreenSwapBuffers(screen, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_N3DS_DestroyWindowFramebuffer(_THIS, SDL_Window *window)
|
||||||
|
{
|
||||||
|
SDL_Surface *surface;
|
||||||
|
surface = (SDL_Surface *) SDL_SetWindowData(window, N3DS_SURFACE, NULL);
|
||||||
|
SDL_FreeSurface(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SDL_VIDEO_DRIVER_N3DS */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SDL_n3dsframebuffer_c_h_
|
||||||
|
#define SDL_n3dsframebuffer_c_h_
|
||||||
|
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
int SDL_N3DS_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format, void **pixels, int *pitch);
|
||||||
|
int SDL_N3DS_UpdateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects, int numrects);
|
||||||
|
void SDL_N3DS_DestroyWindowFramebuffer(_THIS, SDL_Window *window);
|
||||||
|
|
||||||
|
#endif /* SDL_n3dsframebuffer_c_h_ */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifdef SDL_VIDEO_DRIVER_N3DS
|
||||||
|
|
||||||
|
#include <3ds.h>
|
||||||
|
|
||||||
|
#include "SDL_n3dsswkb.h"
|
||||||
|
|
||||||
|
static SwkbdState sw_keyboard;
|
||||||
|
const static size_t BUFFER_SIZE = 256;
|
||||||
|
|
||||||
|
void
|
||||||
|
N3DS_SwkbInit()
|
||||||
|
{
|
||||||
|
swkbdInit(&sw_keyboard, SWKBD_TYPE_NORMAL, 2, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
N3DS_SwkbPoll()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
N3DS_SwkbQuit()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_bool
|
||||||
|
N3DS_HasScreenKeyboardSupport(_THIS)
|
||||||
|
{
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
N3DS_StartTextInput(_THIS)
|
||||||
|
{
|
||||||
|
char buffer[BUFFER_SIZE];
|
||||||
|
SwkbdButton button_pressed;
|
||||||
|
button_pressed = swkbdInputText(&sw_keyboard, buffer, BUFFER_SIZE);
|
||||||
|
if (button_pressed == SWKBD_BUTTON_CONFIRM) {
|
||||||
|
SDL_SendKeyboardText(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
N3DS_StopTextInput(_THIS)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SDL_VIDEO_DRIVER_N3DS */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SDL_n3dskeyboard_h_
|
||||||
|
#define SDL_n3dskeyboard_h_
|
||||||
|
|
||||||
|
#include "../../events/SDL_events_c.h"
|
||||||
|
|
||||||
|
void N3DS_SwkbInit();
|
||||||
|
void N3DS_SwkbPoll();
|
||||||
|
void N3DS_SwkbQuit();
|
||||||
|
|
||||||
|
SDL_bool N3DS_HasScreenKeyboardSupport(_THIS);
|
||||||
|
|
||||||
|
void N3DS_StartTextInput(_THIS);
|
||||||
|
void N3DS_StopTextInput(_THIS);
|
||||||
|
|
||||||
|
#endif /* SDL_n3dskeyboard_h_ */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,163 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifdef SDL_VIDEO_DRIVER_N3DS
|
||||||
|
|
||||||
|
#include "../SDL_sysvideo.h"
|
||||||
|
#include "SDL_n3dsevents_c.h"
|
||||||
|
#include "SDL_n3dsframebuffer_c.h"
|
||||||
|
#include "SDL_n3dsswkb.h"
|
||||||
|
#include "SDL_n3dsvideo.h"
|
||||||
|
|
||||||
|
#define N3DSVID_DRIVER_NAME "n3ds"
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE void AddN3DSDisplay(gfxScreen_t screen);
|
||||||
|
|
||||||
|
static int N3DS_VideoInit(_THIS);
|
||||||
|
static void N3DS_VideoQuit(_THIS);
|
||||||
|
static void N3DS_GetDisplayModes(_THIS, SDL_VideoDisplay *display);
|
||||||
|
static int N3DS_CreateWindow(_THIS, SDL_Window *window);
|
||||||
|
static void N3DS_DestroyWindow(_THIS, SDL_Window *window);
|
||||||
|
|
||||||
|
/* N3DS driver bootstrap functions */
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DS_DeleteDevice(SDL_VideoDevice *device)
|
||||||
|
{
|
||||||
|
SDL_free(device->displays);
|
||||||
|
SDL_free(device->driverdata);
|
||||||
|
SDL_free(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_VideoDevice *
|
||||||
|
N3DS_CreateDevice(void)
|
||||||
|
{
|
||||||
|
SDL_VideoDevice *device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
|
||||||
|
if (!device) {
|
||||||
|
SDL_OutOfMemory();
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
device->VideoInit = N3DS_VideoInit;
|
||||||
|
device->VideoQuit = N3DS_VideoQuit;
|
||||||
|
|
||||||
|
device->GetDisplayModes = N3DS_GetDisplayModes;
|
||||||
|
|
||||||
|
device->CreateSDLWindow = N3DS_CreateWindow;
|
||||||
|
device->DestroyWindow = N3DS_DestroyWindow;
|
||||||
|
|
||||||
|
device->HasScreenKeyboardSupport = N3DS_HasScreenKeyboardSupport;
|
||||||
|
device->StartTextInput = N3DS_StartTextInput;
|
||||||
|
device->StopTextInput = N3DS_StopTextInput;
|
||||||
|
|
||||||
|
device->PumpEvents = N3DS_PumpEvents;
|
||||||
|
|
||||||
|
device->CreateWindowFramebuffer = SDL_N3DS_CreateWindowFramebuffer;
|
||||||
|
device->UpdateWindowFramebuffer = SDL_N3DS_UpdateWindowFramebuffer;
|
||||||
|
device->DestroyWindowFramebuffer = SDL_N3DS_DestroyWindowFramebuffer;
|
||||||
|
|
||||||
|
device->num_displays = 2;
|
||||||
|
|
||||||
|
device->free = N3DS_DeleteDevice;
|
||||||
|
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoBootStrap N3DS_bootstrap = { N3DSVID_DRIVER_NAME, "N3DS Video Driver", N3DS_CreateDevice };
|
||||||
|
|
||||||
|
static int
|
||||||
|
N3DS_VideoInit(_THIS)
|
||||||
|
{
|
||||||
|
AddN3DSDisplay(GFX_TOP);
|
||||||
|
AddN3DSDisplay(GFX_BOTTOM);
|
||||||
|
|
||||||
|
N3DS_SwkbInit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FORCE_INLINE void
|
||||||
|
AddN3DSDisplay(gfxScreen_t screen)
|
||||||
|
{
|
||||||
|
SDL_DisplayMode mode;
|
||||||
|
SDL_VideoDisplay display;
|
||||||
|
|
||||||
|
SDL_zero(mode);
|
||||||
|
SDL_zero(display);
|
||||||
|
|
||||||
|
mode.w = (screen == GFX_TOP) ? GSP_SCREEN_HEIGHT_TOP : GSP_SCREEN_HEIGHT_BOTTOM;
|
||||||
|
mode.h = GSP_SCREEN_WIDTH;
|
||||||
|
mode.refresh_rate = 60;
|
||||||
|
mode.format = FRAMEBUFFER_FORMAT;
|
||||||
|
mode.driverdata = NULL;
|
||||||
|
|
||||||
|
display.desktop_mode = mode;
|
||||||
|
display.current_mode = mode;
|
||||||
|
display.driverdata = NULL;
|
||||||
|
|
||||||
|
SDL_AddVideoDisplay(&display, SDL_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DS_VideoQuit(_THIS)
|
||||||
|
{
|
||||||
|
N3DS_SwkbQuit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DS_GetDisplayModes(_THIS, SDL_VideoDisplay *display)
|
||||||
|
{
|
||||||
|
/* Each display only has a single mode */
|
||||||
|
SDL_AddDisplayMode(display, &display->current_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
N3DS_CreateWindow(_THIS, SDL_Window *window)
|
||||||
|
{
|
||||||
|
SDL_WindowData *drv_data = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
|
||||||
|
if (drv_data == NULL) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->flags & SDL_WINDOW_N3DS_BOTTOM) {
|
||||||
|
drv_data->screen = GFX_BOTTOM;
|
||||||
|
} else {
|
||||||
|
drv_data->screen = GFX_TOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->driverdata = drv_data;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
N3DS_DestroyWindow(_THIS, SDL_Window *window)
|
||||||
|
{
|
||||||
|
if (window == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SDL_free(window->driverdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SDL_VIDEO_DRIVER_N3DS */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifndef SDL_n3dsvideo_h_
|
||||||
|
#define SDL_n3dsvideo_h_
|
||||||
|
|
||||||
|
#include <3ds.h>
|
||||||
|
|
||||||
|
#include "../SDL_sysvideo.h"
|
||||||
|
typedef struct SDL_WindowData
|
||||||
|
{
|
||||||
|
gfxScreen_t screen; /**< Keeps track of which N3DS screen is targetted */
|
||||||
|
} SDL_WindowData;
|
||||||
|
|
||||||
|
#define FRAMEBUFFER_FORMAT SDL_PIXELFORMAT_RGBA8888
|
||||||
|
|
||||||
|
#endif /* SDL_n3dsvideo_h_ */
|
||||||
|
|
||||||
|
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
|
@ -14,6 +14,10 @@ if(SDL_INSTALL_TESTS)
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(N3DS)
|
||||||
|
link_libraries(SDL2::SDL2main)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(PSP)
|
if(PSP)
|
||||||
link_libraries(
|
link_libraries(
|
||||||
SDL2::SDL2main
|
SDL2::SDL2main
|
||||||
|
@ -430,6 +434,27 @@ if(PSP)
|
||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(N3DS)
|
||||||
|
set(ROMFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/romfs")
|
||||||
|
file(COPY ${RESOURCE_FILES} DESTINATION "${ROMFS_DIR}")
|
||||||
|
|
||||||
|
foreach(APP IN LISTS ALL_TESTS)
|
||||||
|
get_target_property(TARGET_BINARY_DIR ${APP} BINARY_DIR)
|
||||||
|
set(SMDH_FILE "${TARGET_BINARY_DIR}/${APP}.smdh")
|
||||||
|
ctr_generate_smdh("${SMDH_FILE}"
|
||||||
|
NAME "SDL-${APP}"
|
||||||
|
DESCRIPTION "SDL2 Test suite"
|
||||||
|
AUTHOR "SDL2 Contributors"
|
||||||
|
ICON "${CMAKE_CURRENT_SOURCE_DIR}/n3ds/logo48x48.png"
|
||||||
|
)
|
||||||
|
ctr_create_3dsx(
|
||||||
|
${APP}
|
||||||
|
ROMFS "${ROMFS_DIR}"
|
||||||
|
SMDH "${SMDH_FILE}"
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(RISCOS)
|
if(RISCOS)
|
||||||
set(ALL_TESTS_AIF "")
|
set(ALL_TESTS_AIF "")
|
||||||
foreach(APP IN LISTS ALL_TESTS)
|
foreach(APP IN LISTS ALL_TESTS)
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
Loading…
Reference in New Issue