From 4a022b6dfb289db0179a23007fe390bc9a398aaa Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Wed, 19 Aug 2026 22:54:55 +0100 Subject: [PATCH 01/19] some kind of switch port that uses the new thing --- .github/workflows/build.yml | 39 +++++++++++++++++++++++++++++ CMakeLists.txt | 41 +++++++++++++++++++++++++++---- src/gl/gl_renderer.c | 8 +++--- src/gl/gl_renderer.h | 2 +- src/gl_common/gl_common.h | 2 +- src/gl_common/gl_wrappers.h | 2 +- src/loop.c | 4 +-- src/switch/log.c | 27 ++++++++++++++++++++ src/switch/main.c | 49 +++++++++++++++++++++++++++++++++++++ src/switch/stb_impl.c | 5 ++++ 10 files changed, 165 insertions(+), 14 deletions(-) create mode 100644 src/switch/log.c create mode 100644 src/switch/main.c create mode 100644 src/switch/stb_impl.c diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 16228cd98..607be0006 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -607,6 +607,45 @@ jobs: name: butterscotch-vita path: build/Butterscotch.vpk + build-switch: + name: Build (Nintendo Switch) + runs-on: ubuntu-24.04 + container: + image: devkitpro/devkita64:latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up ccache + uses: actions/cache@v4 + with: + path: ~/.cache/ccache + key: switch-ccache-${{ github.sha }} + restore-keys: | + switch-ccache- + + - name: Install ccache + run: | + apt-get update && apt-get install -y --no-install-recommends ccache + + - name: Configure and build + run: | + cmake -B build -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE=$DEVKITPRO/cmake/Switch.cmake \ + -DWERROR=ON \ + -DPLATFORM=switch \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + + cmake --build build + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: butterscotch-switch + path: build/butterscotch.nro + build-android: name: Build (Android) runs-on: ubuntu-24.04 diff --git a/CMakeLists.txt b/CMakeLists.txt index cef563fbc..38f56d723 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,16 @@ endif() set(BACKEND "sdl2") +elseif(PLATFORM STREQUAL "switch") +if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) + if(NOT DEFINED ENV{DEVKITPRO}) + message(FATAL_ERROR "Please define DEVKITPRO to point to your SDK path!") + endif() + set(CMAKE_TOOLCHAIN_FILE "$ENV{DEVKITPRO}/switch.cmake" CACHE PATH "toolchain file") +endif() + +set(BACKEND "sdl2") + endif() project(butterscotch C) @@ -96,6 +106,10 @@ option(ENABLE_WAD16 "Enable support for WAD Version 15/16" ON) option(ENABLE_WAD17 "Enable support for WAD Version 17" ON) option(ENABLE_LEGACY_GL "Enable the legacy OpenGL renderer" ON) option(ENABLE_MODERN_GL "Enable the modern OpenGL renderer" ON) +if(PLATFORM STREQUAL "switch") + # The Switch only supports the modern GL renderer (GLES3 via SDL2) + set(ENABLE_LEGACY_GL OFF CACHE BOOL "Enable the legacy OpenGL renderer" FORCE) +endif() if(NOT ENABLE_WAD14 AND NOT ENABLE_WAD16 AND NOT ENABLE_WAD17) message(FATAL_ERROR "You need to build Butterscotch with at least one WAD version enabled!") endif() @@ -148,7 +162,7 @@ if(AUDIO_BACKEND STREQUAL "openal") add_compile_definitions(USE_OPENAL) if(APPLE) set(AUDIO_LIBRARIES "-framework OpenAL") - elseif(PLATFORM STREQUAL "vita") + elseif(PLATFORM STREQUAL "vita" OR PLATFORM STREQUAL "switch") set(AUDIO_LIBRARIES openal pthread) elseif(NOT PLATFORM STREQUAL "ps3") find_package(OpenAL REQUIRED) @@ -217,7 +231,7 @@ if(ENABLE_VM_EXCEPTIONS_LOGS) add_compile_definitions(ENABLE_VM_EXCEPTIONS_LOGS) endif() -if(PLATFORM STREQUAL "cli" OR PLATFORM STREQUAL "vita") +if(PLATFORM STREQUAL "cli" OR PLATFORM STREQUAL "vita" OR PLATFORM STREQUAL "switch") if(PLATFORM STREQUAL "vita") if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") add_compile_options(-ffast-math) @@ -229,6 +243,18 @@ if(PLATFORM STREQUAL "cli" OR PLATFORM STREQUAL "vita") add_compile_definitions(__VITA__) add_compile_definitions(PLATFORM_VITA) + set(VM_GML_PROFILER_DEFAULT OFF) + set(VM_TRACING_DEFAULT OFF) + set(VM_OPCODE_PROFILER_DEFAULT OFF) + set(VM_STUB_LOGS_DEFAULT OFF) + elseif(PLATFORM STREQUAL "switch") + if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + add_compile_options(-ffast-math) + endif() + + add_compile_definitions(__SWITCH__) + add_compile_definitions(PLATFORM_SWITCH) + set(VM_GML_PROFILER_DEFAULT OFF) set(VM_TRACING_DEFAULT OFF) set(VM_OPCODE_PROFILER_DEFAULT OFF) @@ -291,7 +317,7 @@ if(PLATFORM STREQUAL "cli" OR PLATFORM STREQUAL "vita") target_include_directories(butterscotch PUBLIC vendor/stb/image) set(PLATFORM_LIBRARIES bzip2 stb_ds sha1 stb_vorbis) - if(NOT PLATFORM STREQUAL "vita") + if(NOT PLATFORM STREQUAL "vita" AND NOT PLATFORM STREQUAL "switch") # GLAD add_library(glad STATIC vendor/glad/src/glad.c) target_include_directories(glad PUBLIC vendor/glad/include) @@ -303,7 +329,7 @@ if(PLATFORM STREQUAL "cli" OR PLATFORM STREQUAL "vita") endif() if(WIN32) set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} opengl32 gdi32 winmm) - elseif(NOT PLATFORM STREQUAL "vita") + elseif(NOT PLATFORM STREQUAL "vita" AND NOT PLATFORM STREQUAL "switch") set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} ${CMAKE_DL_LIBS}) endif() @@ -382,7 +408,12 @@ if(PLATFORM STREQUAL "cli" OR PLATFORM STREQUAL "vita") NAME ${VITA_APP_NAME} ) else() - target_link_libraries(butterscotch PRIVATE ${BACKEND_LIBRARIES} ${AUDIO_LIBRARIES} ${PLATFORM_LIBRARIES}) + target_link_libraries(butterscotch PRIVATE ${BACKEND_LIBRARIES} ${AUDIO_LIBRARIES} ${PLATFORM_LIBRARIES} GLESv2) + + if (PLATFORM STREQUAL "switch") + nx_generate_nacp(OUTPUT Butterscotch.nacp NAME "Butterscotch" AUTHOR "Butterscotch" VERSION "1.0.0") + nx_create_nro(butterscotch NACP Butterscotch.nacp) + endif() endif() if(BACKEND STREQUAL "appkit") target_sources(butterscotch PRIVATE src/backends/${BACKEND}.m) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 071dcadbc..13801f4d5 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -2,7 +2,7 @@ #include "matrix_math.h" #include "text_utils.h" -#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) +#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) || defined(__SWITCH__) #include #elif PLATFORM_VITA #include @@ -56,7 +56,7 @@ static const char* baseFragmentShader = // ===[ Runtime OpenGL extension checks ]=== static bool hasFBO() { -#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !defined(__VITA__) +#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !defined(__VITA__) && !defined(__SWITCH__) return glGenFramebuffers; #else return true; @@ -64,7 +64,7 @@ static bool hasFBO() { } static bool hasVAO() { -#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !defined(__VITA__) +#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !defined(__VITA__) && !defined(__SWITCH__) return glGenVertexArrays; #else return true; @@ -439,7 +439,7 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { gl->isGL3 = (ver.major >= 3); gl->isGLES = ver.isGLES; -#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !defined(PLATFORM_VITA) +#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !defined(PLATFORM_VITA) && !defined(__SWITCH__) gl_init_wrappers(); #endif diff --git a/src/gl/gl_renderer.h b/src/gl/gl_renderer.h index d6600fef4..9266d17f1 100644 --- a/src/gl/gl_renderer.h +++ b/src/gl/gl_renderer.h @@ -4,7 +4,7 @@ #include "common.h" #include "renderer.h" #include "runner.h" -#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) +#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) || defined(__SWITCH__) #include #elif PLATFORM_VITA #include diff --git a/src/gl_common/gl_common.h b/src/gl_common/gl_common.h index 0c6081823..d8a881985 100644 --- a/src/gl_common/gl_common.h +++ b/src/gl_common/gl_common.h @@ -4,7 +4,7 @@ #include "common.h" #include -#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) +#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) || defined(__SWITCH__) #include #elif PLATFORM_PS3 #include "ps3gl.h" diff --git a/src/gl_common/gl_wrappers.h b/src/gl_common/gl_wrappers.h index 01ffbaf2e..ffa92bb10 100644 --- a/src/gl_common/gl_wrappers.h +++ b/src/gl_common/gl_wrappers.h @@ -1,4 +1,4 @@ -#if !defined(_BS_GL_WRAPPERS_H_) && !defined(__EMSCRIPTEN__) && !defined(PLATFORM_PS3) && !defined(PLATFORM_VITA) && !defined(__ANDROID__) +#if !defined(_BS_GL_WRAPPERS_H_) && !defined(__EMSCRIPTEN__) && !defined(PLATFORM_PS3) && !defined(PLATFORM_VITA) && !defined(__ANDROID__) && !defined(__SWITCH__) #define _BS_GL_WRAPPERS_H_ static inline void gl_init_wrappers(void) { diff --git a/src/loop.c b/src/loop.c index e3cab6117..7a1ae4a91 100644 --- a/src/loop.c +++ b/src/loop.c @@ -33,7 +33,7 @@ #include "input_recording.h" #include "debug_overlay.h" #if (defined(ENABLE_LEGACY_GL) || defined(ENABLE_MODERN_GL) || ((defined(USE_GLFW3) || defined(USE_GLFW2)) && defined(ENABLE_SW_RENDERER))) && \ - !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !defined(PLATFORM_PS3) && !defined(PLATFORM_VITA) + !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !defined(PLATFORM_PS3) && !defined(PLATFORM_VITA) && !defined(__SWITCH__) #define USE_GLAD #include #endif @@ -404,7 +404,7 @@ void saveInputRecording() { } } -#if !defined(_WIN32) && !defined(PLATFORM_VITA) +#if !defined(_WIN32) && !defined(PLATFORM_VITA) && !defined(__SWITCH__) #define USE_CRASH_SIGNAL_HANDLER typedef struct { int key; struct sigaction value; } PreviousSignalActionEntry; static PreviousSignalActionEntry* previousSignalActions = nullptr; diff --git a/src/switch/log.c b/src/switch/log.c new file mode 100644 index 000000000..0e3e1df99 --- /dev/null +++ b/src/switch/log.c @@ -0,0 +1,27 @@ +#include + +#include "log.h" + +void platformLog(const logType type, const char *format, va_list va) { + const char* colourPrefix = ANSI_COLOUR_CODE_RESET; + const char* textPrefix = ""; + switch (type) { + case LOG_TYPE_NORMAL: + break; + case LOG_TYPE_WARNING: + colourPrefix = ANSI_COLOUR_CODE_BOLD_YELLOW; + textPrefix = "Warning: "; + break; + case LOG_TYPE_ERROR: + colourPrefix = ANSI_COLOUR_CODE_BOLD_RED; + textPrefix = "Error: "; + break; + case LOG_TYPE_DEBUG: + colourPrefix = ANSI_COLOUR_CODE_BOLD_PURPLE; + textPrefix = "Debug: "; + break; + } + + printf("%s%s%s", colourPrefix, textPrefix, ANSI_COLOUR_CODE_RESET); + vprintf(format, va); +} diff --git a/src/switch/main.c b/src/switch/main.c new file mode 100644 index 000000000..3a9708700 --- /dev/null +++ b/src/switch/main.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +/* For SDL_main */ +#if defined(USE_SDL1) +#include +#elif defined(USE_SDL2) +#include +#elif defined(USE_SDL3) +#include +#endif + +int main(int argc, char* argv[]) { + (void)argc; + setbuf(stderr, NULL); + setbuf(stdout, NULL); + + fsdevMountSdmc(); + + CommandLineArgs args = {0}; + + args.exitAtFrame = -1; +#ifdef ENABLE_VM_TRACING + args.traceBytecodeAfterFrame = 0; +#endif + args.speedMultiplier = 1.0; + args.fastForwardSpeed = 0.0; + args.osType = OS_SWITCH; + args.profilerFramesBetween = 0; + args.loadType = DATAWINLOADTYPE_LOAD_IN_MEMORY_AHEAD_OF_TIME; + args.lazyRooms = false; + args.lazyTextures = false; + args.lazyAudio = false; +#if defined(ENABLE_MODERN_GL) + args.renderer = MODERN_GL; +#elif defined(ENABLE_LEGACY_GL) + args.renderer = LEGACY_GL; +#else + args.renderer = SOFTWARE; +#endif + args.dataWinPath = "sdmc:/data/butterscotch/data.win"; + args.saveFolder = "sdmc:/data/butterscotch"; + + int ret = loop(args, argv[0]); + freeCommandLineArgs(&args); + return ret; +} diff --git a/src/switch/stb_impl.c b/src/switch/stb_impl.c new file mode 100644 index 000000000..82928fa0f --- /dev/null +++ b/src/switch/stb_impl.c @@ -0,0 +1,5 @@ +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" From 79f95c8ccf78e7cbb3302388d33e9ce5751cfcbb Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Wed, 19 Aug 2026 22:56:49 +0100 Subject: [PATCH 02/19] who invited my man blud --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 38f56d723..b1bc9c55d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -408,9 +408,10 @@ if(PLATFORM STREQUAL "cli" OR PLATFORM STREQUAL "vita" OR PLATFORM STREQUAL "swi NAME ${VITA_APP_NAME} ) else() - target_link_libraries(butterscotch PRIVATE ${BACKEND_LIBRARIES} ${AUDIO_LIBRARIES} ${PLATFORM_LIBRARIES} GLESv2) + target_link_libraries(butterscotch PRIVATE ${BACKEND_LIBRARIES} ${AUDIO_LIBRARIES} ${PLATFORM_LIBRARIES}) if (PLATFORM STREQUAL "switch") + target_link_libraries(butterscotch PRIVATE GLESv2) nx_generate_nacp(OUTPUT Butterscotch.nacp NAME "Butterscotch" AUTHOR "Butterscotch" VERSION "1.0.0") nx_create_nro(butterscotch NACP Butterscotch.nacp) endif() From 62905c9d55561c8061139ce814169dd773d570fa Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Wed, 19 Aug 2026 23:05:29 +0100 Subject: [PATCH 03/19] fix audio --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b1bc9c55d..4aa1721fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,7 +73,7 @@ if(AUDIO_BACKEND STREQUAL "") set(AUDIO_BACKEND "web") elseif(PLATFORM STREQUAL "web-meta") set(AUDIO_BACKEND "none") - elseif(PLATFORM STREQUAL "ps3" OR PLATFORM STREQUAL "vita") + elseif(PLATFORM STREQUAL "ps3" OR PLATFORM STREQUAL "vita" OR PLATFORM STREQUAL "switch") set(AUDIO_BACKEND "openal") elseif(PLATFORM STREQUAL "ps2") set(AUDIO_BACKEND "ps2") @@ -411,7 +411,7 @@ if(PLATFORM STREQUAL "cli" OR PLATFORM STREQUAL "vita" OR PLATFORM STREQUAL "swi target_link_libraries(butterscotch PRIVATE ${BACKEND_LIBRARIES} ${AUDIO_LIBRARIES} ${PLATFORM_LIBRARIES}) if (PLATFORM STREQUAL "switch") - target_link_libraries(butterscotch PRIVATE GLESv2) + target_link_libraries(butterscotch PRIVATE GLESv2 stdc++) nx_generate_nacp(OUTPUT Butterscotch.nacp NAME "Butterscotch" AUTHOR "Butterscotch" VERSION "1.0.0") nx_create_nro(butterscotch NACP Butterscotch.nacp) endif() From 1ced18e6434734c97af557d6ad637bdfbc5eddae Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Thu, 20 Aug 2026 09:26:20 +0100 Subject: [PATCH 04/19] switch: don't use gamecontrollerdb --- src/backends/sdl2.c | 2 +- src/switch/log.c | 19 ++++++++++++++++--- src/switch/main.c | 5 +++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/backends/sdl2.c b/src/backends/sdl2.c index 67290aaea..86b51ca68 100644 --- a/src/backends/sdl2.c +++ b/src/backends/sdl2.c @@ -218,7 +218,7 @@ bool platformInit(int reqW, int reqH, const char *title, bool headless) { // If we don't do this, the window will be larger than it should be on HiDPI displays. platformSetWindowSize(reqW, reqH); -#ifndef PLATFORM_VITA +#if !defined(PLATFORM_VITA) && !defined(PLATFORM_SWITCH) // init gamepad mappings const char* dbPath = "gamecontrollerdb.txt"; if (SDL_GameControllerAddMappingsFromFile(dbPath) >= 0) { diff --git a/src/switch/log.c b/src/switch/log.c index 0e3e1df99..1ad3d1824 100644 --- a/src/switch/log.c +++ b/src/switch/log.c @@ -1,10 +1,16 @@ #include +#include +#include #include "log.h" +#define LOG_BUFFER_SIZE 1024 + void platformLog(const logType type, const char *format, va_list va) { const char* colourPrefix = ANSI_COLOUR_CODE_RESET; const char* textPrefix = ""; + char buffer[LOG_BUFFER_SIZE]; + switch (type) { case LOG_TYPE_NORMAL: break; @@ -21,7 +27,14 @@ void platformLog(const logType type, const char *format, va_list va) { textPrefix = "Debug: "; break; } - - printf("%s%s%s", colourPrefix, textPrefix, ANSI_COLOUR_CODE_RESET); - vprintf(format, va); + int written = snprintf(buffer, sizeof(buffer), "%s", textPrefix); + + if (written >= 0 && written < (int)sizeof(buffer)) { + vsnprintf(buffer + written, (int)sizeof(buffer) - written, format, va); + } + buffer[sizeof(buffer) - 1] = '\0'; + + printf("%s%s%s", colourPrefix, buffer, ANSI_COLOUR_CODE_RESET); + + svcOutputDebugString(buffer, strlen(buffer)); } diff --git a/src/switch/main.c b/src/switch/main.c index 3a9708700..6c6b16d91 100644 --- a/src/switch/main.c +++ b/src/switch/main.c @@ -14,8 +14,8 @@ int main(int argc, char* argv[]) { (void)argc; - setbuf(stderr, NULL); - setbuf(stdout, NULL); + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); fsdevMountSdmc(); @@ -45,5 +45,6 @@ int main(int argc, char* argv[]) { int ret = loop(args, argv[0]); freeCommandLineArgs(&args); + romfsExit(); return ret; } From a20197f21ce0aa6c40371050d2a21bfadc76c54c Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Thu, 20 Aug 2026 09:34:06 +0100 Subject: [PATCH 05/19] pls help --- src/switch/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/switch/main.c b/src/switch/main.c index 6c6b16d91..cbc8b13bd 100644 --- a/src/switch/main.c +++ b/src/switch/main.c @@ -14,8 +14,8 @@ int main(int argc, char* argv[]) { (void)argc; - setvbuf(stdout, NULL, _IONBF, 0); - setvbuf(stderr, NULL, _IONBF, 0); + setbuf(stdout, NULL); + setbuf(stderr, NULL); fsdevMountSdmc(); @@ -27,7 +27,7 @@ int main(int argc, char* argv[]) { #endif args.speedMultiplier = 1.0; args.fastForwardSpeed = 0.0; - args.osType = OS_SWITCH; + args.osType = OS_WINDOWS; args.profilerFramesBetween = 0; args.loadType = DATAWINLOADTYPE_LOAD_IN_MEMORY_AHEAD_OF_TIME; args.lazyRooms = false; From 554fd11d1d89ea8cc220d8379bb02ee580cd3743 Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Thu, 20 Aug 2026 09:34:52 +0100 Subject: [PATCH 06/19] remove dupe args --- src/switch/main.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/switch/main.c b/src/switch/main.c index cbc8b13bd..f698e62d7 100644 --- a/src/switch/main.c +++ b/src/switch/main.c @@ -29,10 +29,6 @@ int main(int argc, char* argv[]) { args.fastForwardSpeed = 0.0; args.osType = OS_WINDOWS; args.profilerFramesBetween = 0; - args.loadType = DATAWINLOADTYPE_LOAD_IN_MEMORY_AHEAD_OF_TIME; - args.lazyRooms = false; - args.lazyTextures = false; - args.lazyAudio = false; #if defined(ENABLE_MODERN_GL) args.renderer = MODERN_GL; #elif defined(ENABLE_LEGACY_GL) From 96730b0600b707f5f1f67014fdf5a8eb9bed988f Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Thu, 20 Aug 2026 09:40:35 +0100 Subject: [PATCH 07/19] correct dkp cmake toolchain path --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4aa1721fa..73e13d916 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) if(NOT DEFINED ENV{DEVKITPRO}) message(FATAL_ERROR "Please define DEVKITPRO to point to your SDK path!") endif() - set(CMAKE_TOOLCHAIN_FILE "$ENV{DEVKITPRO}/switch.cmake" CACHE PATH "toolchain file") + set(CMAKE_TOOLCHAIN_FILE "$ENV{DEVKITPRO}/cmake/Switch.cmake" CACHE PATH "toolchain file") endif() set(BACKEND "sdl2") From 4cea0bc5d5abbabcdf7244bae60f08dc94617a50 Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Thu, 20 Aug 2026 09:41:13 +0100 Subject: [PATCH 08/19] load in memory aot --- src/switch/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/switch/main.c b/src/switch/main.c index f698e62d7..90372c3f1 100644 --- a/src/switch/main.c +++ b/src/switch/main.c @@ -29,6 +29,7 @@ int main(int argc, char* argv[]) { args.fastForwardSpeed = 0.0; args.osType = OS_WINDOWS; args.profilerFramesBetween = 0; + args.loadType = DATAWINLOADTYPE_LOAD_IN_MEMORY_AHEAD_OF_TIME; #if defined(ENABLE_MODERN_GL) args.renderer = MODERN_GL; #elif defined(ENABLE_LEGACY_GL) From 51d47869730522780448f60391ec8c13c3b22acb Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Thu, 20 Aug 2026 09:44:47 +0100 Subject: [PATCH 09/19] we already set the cmake toolchain for dkp, no need for this --- .github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 607be0006..6457acb70 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -631,7 +631,6 @@ jobs: - name: Configure and build run: | cmake -B build -G Ninja \ - -DCMAKE_TOOLCHAIN_FILE=$DEVKITPRO/cmake/Switch.cmake \ -DWERROR=ON \ -DPLATFORM=switch \ -DCMAKE_BUILD_TYPE=Release \ From cd52c60c5f1a3799ad7879eeadae97d746c67237 Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Thu, 20 Aug 2026 19:06:35 +0100 Subject: [PATCH 10/19] make switch use glad --- CMakeLists.txt | 2 +- src/gl/gl_renderer.c | 2 +- src/gl/gl_renderer.h | 2 +- src/gl_common/gl_common.h | 2 +- src/loop.c | 12 +++++++++--- src/switch/main.c | 2 +- 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73e13d916..5853ec295 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -411,7 +411,7 @@ if(PLATFORM STREQUAL "cli" OR PLATFORM STREQUAL "vita" OR PLATFORM STREQUAL "swi target_link_libraries(butterscotch PRIVATE ${BACKEND_LIBRARIES} ${AUDIO_LIBRARIES} ${PLATFORM_LIBRARIES}) if (PLATFORM STREQUAL "switch") - target_link_libraries(butterscotch PRIVATE GLESv2 stdc++) + target_link_libraries(butterscotch PRIVATE glad stdc++) nx_generate_nacp(OUTPUT Butterscotch.nacp NAME "Butterscotch" AUTHOR "Butterscotch" VERSION "1.0.0") nx_create_nro(butterscotch NACP Butterscotch.nacp) endif() diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 13801f4d5..49ac13fc5 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -2,7 +2,7 @@ #include "matrix_math.h" #include "text_utils.h" -#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) || defined(__SWITCH__) +#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) #include #elif PLATFORM_VITA #include diff --git a/src/gl/gl_renderer.h b/src/gl/gl_renderer.h index 9266d17f1..d6600fef4 100644 --- a/src/gl/gl_renderer.h +++ b/src/gl/gl_renderer.h @@ -4,7 +4,7 @@ #include "common.h" #include "renderer.h" #include "runner.h" -#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) || defined(__SWITCH__) +#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) #include #elif PLATFORM_VITA #include diff --git a/src/gl_common/gl_common.h b/src/gl_common/gl_common.h index d8a881985..0c6081823 100644 --- a/src/gl_common/gl_common.h +++ b/src/gl_common/gl_common.h @@ -4,7 +4,7 @@ #include "common.h" #include -#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) || defined(__SWITCH__) +#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) #include #elif PLATFORM_PS3 #include "ps3gl.h" diff --git a/src/loop.c b/src/loop.c index 7a1ae4a91..58f625b0b 100644 --- a/src/loop.c +++ b/src/loop.c @@ -33,7 +33,7 @@ #include "input_recording.h" #include "debug_overlay.h" #if (defined(ENABLE_LEGACY_GL) || defined(ENABLE_MODERN_GL) || ((defined(USE_GLFW3) || defined(USE_GLFW2)) && defined(ENABLE_SW_RENDERER))) && \ - !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !defined(PLATFORM_PS3) && !defined(PLATFORM_VITA) && !defined(__SWITCH__) + !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !defined(PLATFORM_PS3) && !defined(PLATFORM_VITA) #define USE_GLAD #include #endif @@ -139,11 +139,15 @@ static size_t get_used_memory(void) { static bool platformInitGlad(void) { glGetString = (PFNGLGETSTRINGPROC)platformGetProcAddress("glGetString"); if (!glGetString) - return 0; + return false; logInfo("OpenGL Version: %s\n", (const char*)glGetString(GL_VERSION)); - GLVer ver = GLCommon_getGLVersion(); + #ifdef PLATFORM_SWITCH + if (!gladLoadGLLoader(platformGetProcAddress)) + return false; + #else + GLVer ver = GLCommon_getGLVersion(); if (ver.isGLES) { if (!gladLoadGLES2Loader(platformGetProcAddress)) return false; @@ -151,6 +155,8 @@ static bool platformInitGlad(void) { if (!gladLoadGLLoader(platformGetProcAddress)) return false; } + #endif + return true; } #endif diff --git a/src/switch/main.c b/src/switch/main.c index 90372c3f1..0cd7c6240 100644 --- a/src/switch/main.c +++ b/src/switch/main.c @@ -27,7 +27,7 @@ int main(int argc, char* argv[]) { #endif args.speedMultiplier = 1.0; args.fastForwardSpeed = 0.0; - args.osType = OS_WINDOWS; + args.osType = OS_SWITCH; args.profilerFramesBetween = 0; args.loadType = DATAWINLOADTYPE_LOAD_IN_MEMORY_AHEAD_OF_TIME; #if defined(ENABLE_MODERN_GL) From 365dc23702bb9755a2ac41694936810f6c15e27a Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Thu, 20 Aug 2026 19:52:13 +0100 Subject: [PATCH 11/19] nvm, stick to glesv2 --- CMakeLists.txt | 6 +----- src/gl/gl_renderer.c | 2 +- src/gl/gl_renderer.h | 2 +- src/gl_common/gl_common.h | 2 +- src/loop.c | 12 +++--------- src/switch/main.c | 4 +--- 6 files changed, 8 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5853ec295..3b2e545e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,10 +106,6 @@ option(ENABLE_WAD16 "Enable support for WAD Version 15/16" ON) option(ENABLE_WAD17 "Enable support for WAD Version 17" ON) option(ENABLE_LEGACY_GL "Enable the legacy OpenGL renderer" ON) option(ENABLE_MODERN_GL "Enable the modern OpenGL renderer" ON) -if(PLATFORM STREQUAL "switch") - # The Switch only supports the modern GL renderer (GLES3 via SDL2) - set(ENABLE_LEGACY_GL OFF CACHE BOOL "Enable the legacy OpenGL renderer" FORCE) -endif() if(NOT ENABLE_WAD14 AND NOT ENABLE_WAD16 AND NOT ENABLE_WAD17) message(FATAL_ERROR "You need to build Butterscotch with at least one WAD version enabled!") endif() @@ -411,7 +407,7 @@ if(PLATFORM STREQUAL "cli" OR PLATFORM STREQUAL "vita" OR PLATFORM STREQUAL "swi target_link_libraries(butterscotch PRIVATE ${BACKEND_LIBRARIES} ${AUDIO_LIBRARIES} ${PLATFORM_LIBRARIES}) if (PLATFORM STREQUAL "switch") - target_link_libraries(butterscotch PRIVATE glad stdc++) + target_link_libraries(butterscotch PRIVATE GLESv2 stdc++) nx_generate_nacp(OUTPUT Butterscotch.nacp NAME "Butterscotch" AUTHOR "Butterscotch" VERSION "1.0.0") nx_create_nro(butterscotch NACP Butterscotch.nacp) endif() diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 49ac13fc5..13801f4d5 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -2,7 +2,7 @@ #include "matrix_math.h" #include "text_utils.h" -#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) +#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) || defined(__SWITCH__) #include #elif PLATFORM_VITA #include diff --git a/src/gl/gl_renderer.h b/src/gl/gl_renderer.h index d6600fef4..9266d17f1 100644 --- a/src/gl/gl_renderer.h +++ b/src/gl/gl_renderer.h @@ -4,7 +4,7 @@ #include "common.h" #include "renderer.h" #include "runner.h" -#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) +#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) || defined(__SWITCH__) #include #elif PLATFORM_VITA #include diff --git a/src/gl_common/gl_common.h b/src/gl_common/gl_common.h index 0c6081823..d8a881985 100644 --- a/src/gl_common/gl_common.h +++ b/src/gl_common/gl_common.h @@ -4,7 +4,7 @@ #include "common.h" #include -#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) +#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) || defined(__SWITCH__) #include #elif PLATFORM_PS3 #include "ps3gl.h" diff --git a/src/loop.c b/src/loop.c index 58f625b0b..7a1ae4a91 100644 --- a/src/loop.c +++ b/src/loop.c @@ -33,7 +33,7 @@ #include "input_recording.h" #include "debug_overlay.h" #if (defined(ENABLE_LEGACY_GL) || defined(ENABLE_MODERN_GL) || ((defined(USE_GLFW3) || defined(USE_GLFW2)) && defined(ENABLE_SW_RENDERER))) && \ - !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !defined(PLATFORM_PS3) && !defined(PLATFORM_VITA) + !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !defined(PLATFORM_PS3) && !defined(PLATFORM_VITA) && !defined(__SWITCH__) #define USE_GLAD #include #endif @@ -139,15 +139,11 @@ static size_t get_used_memory(void) { static bool platformInitGlad(void) { glGetString = (PFNGLGETSTRINGPROC)platformGetProcAddress("glGetString"); if (!glGetString) - return false; + return 0; logInfo("OpenGL Version: %s\n", (const char*)glGetString(GL_VERSION)); - - #ifdef PLATFORM_SWITCH - if (!gladLoadGLLoader(platformGetProcAddress)) - return false; - #else GLVer ver = GLCommon_getGLVersion(); + if (ver.isGLES) { if (!gladLoadGLES2Loader(platformGetProcAddress)) return false; @@ -155,8 +151,6 @@ static bool platformInitGlad(void) { if (!gladLoadGLLoader(platformGetProcAddress)) return false; } - #endif - return true; } #endif diff --git a/src/switch/main.c b/src/switch/main.c index 0cd7c6240..874ff9fdc 100644 --- a/src/switch/main.c +++ b/src/switch/main.c @@ -27,13 +27,11 @@ int main(int argc, char* argv[]) { #endif args.speedMultiplier = 1.0; args.fastForwardSpeed = 0.0; - args.osType = OS_SWITCH; + args.osType = OS_WINDOWS; args.profilerFramesBetween = 0; args.loadType = DATAWINLOADTYPE_LOAD_IN_MEMORY_AHEAD_OF_TIME; #if defined(ENABLE_MODERN_GL) args.renderer = MODERN_GL; -#elif defined(ENABLE_LEGACY_GL) - args.renderer = LEGACY_GL; #else args.renderer = SOFTWARE; #endif From 503f531a51462b075956e60d49966fee2446f8a7 Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Thu, 20 Aug 2026 19:55:32 +0100 Subject: [PATCH 12/19] force off legacy gl on switch --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b2e545e5..56056ab06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,6 +105,9 @@ option(ENABLE_WAD14 "Enable support for WAD Version 14 and below" ON) option(ENABLE_WAD16 "Enable support for WAD Version 15/16" ON) option(ENABLE_WAD17 "Enable support for WAD Version 17" ON) option(ENABLE_LEGACY_GL "Enable the legacy OpenGL renderer" ON) +if(PLATFORM STREQUAL "switch") + set(ENABLE_LEGACY_GL OFF CACHE BOOL "Enable the legacy OpenGL renderer" FORCE) +endif() option(ENABLE_MODERN_GL "Enable the modern OpenGL renderer" ON) if(NOT ENABLE_WAD14 AND NOT ENABLE_WAD16 AND NOT ENABLE_WAD17) message(FATAL_ERROR "You need to build Butterscotch with at least one WAD version enabled!") From bd057a9b99b8a29a3f0bdc1e56fa5ac3efba022b Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Mon, 24 Aug 2026 08:55:28 +0100 Subject: [PATCH 13/19] try this --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 41a977b3f..e3fc8f7eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -263,7 +263,6 @@ if(PLATFORM STREQUAL "cli" OR PLATFORM STREQUAL "vita" OR PLATFORM STREQUAL "swi add_compile_options(-ffast-math) endif() - add_compile_definitions(__SWITCH__) add_compile_definitions(PLATFORM_SWITCH) set(VM_GML_PROFILER_DEFAULT OFF) From be74ded1af8b2687edccb7ae955acdba5c8a6fda Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Tue, 25 Aug 2026 15:33:56 +0100 Subject: [PATCH 14/19] fix segv --- src/loop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/loop.c b/src/loop.c index e9533beda..2f4ad008d 100644 --- a/src/loop.c +++ b/src/loop.c @@ -466,7 +466,7 @@ int loop(CommandLineArgs args, const char *argv0) { arrput(currentGameArgs, args.gameArgs[i]); } // The first argument will ALWAYS be the argv[0] - arrins(currentGameArgs, 0, safeStrdup(argv0)); + arrins(currentGameArgs, 0, safeStrdup(argv0 != nullptr ? argv0 : "")); bool platformInitialized = false; int32_t inputFrameCount = 0; From de0826b0f62cbfc58506c5f44cdbff89124dddf1 Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Tue, 25 Aug 2026 15:54:56 +0100 Subject: [PATCH 15/19] libnx input and sdl2 window size --- src/backends/sdl2.c | 16 +++++++ src/switch/switch_input.c | 91 +++++++++++++++++++++++++++++++++++++++ src/switch/switch_input.h | 10 +++++ 3 files changed, 117 insertions(+) create mode 100644 src/switch/switch_input.c create mode 100644 src/switch/switch_input.h diff --git a/src/backends/sdl2.c b/src/backends/sdl2.c index 86b51ca68..a1e6db3ce 100644 --- a/src/backends/sdl2.c +++ b/src/backends/sdl2.c @@ -8,6 +8,10 @@ #include "platformdefs.h" #include "gettime.h" #include "runner_mouse.h" +#ifdef PLATFORM_SWITCH +#include +#include "switch_input.h" +#endif static Runner *g_runner; static SDL_Surface* scr; @@ -139,6 +143,12 @@ static float platformGetWindowScale(void) { void platformSetWindowSize(int32_t width, int32_t height) { if (width <= 0 || height <= 0) return; +#ifdef PLATFORM_SWITCH + u32 operationMode = appletGetOperationMode(); + width = (operationMode == AppletOperationMode_Console) ? 1920 : 1280; + height = (operationMode == AppletOperationMode_Console) ? 1080 : 720; +#endif + float scale = platformGetWindowScale(); SDL_SetWindowSize(window, (int)(width / scale), (int)(height / scale)); @@ -323,6 +333,7 @@ void *platformGetProcAddress(const char *name) { #endif +#ifndef PLATFORM_SWITCH static int32_t SDLKeyToGml(int sdlkey) { // Letters and numbers are the same as GML if (sdlkey >= 'a' && sdlkey <= 'z') return toupper(sdlkey); @@ -449,8 +460,12 @@ static void mapSdl2ToGml(SDL_GameController* gc, GamepadSlot* slot) { slot->buttonValue[i] = slot->buttonDown[i] ? 1.0f : 0.0f; } } +#endif bool platformHandleEvents(void) { +#ifdef PLATFORM_SWITCH + return SwitchInput_handleEvents(g_runner); +#else SDL_Event e; while (SDL_PollEvent(&e)) { switch (e.type) { @@ -574,6 +589,7 @@ bool platformHandleEvents(void) { } return false; +#endif } void platformSleepUntil(uint64_t time) { diff --git a/src/switch/switch_input.c b/src/switch/switch_input.c new file mode 100644 index 000000000..2fb8a58eb --- /dev/null +++ b/src/switch/switch_input.c @@ -0,0 +1,91 @@ +#include +#include +#include + +#include "switch_input.h" +#include "platformdefs.h" + +#define SWITCH_NPAD_COUNT 8 + +static PadState pads[SWITCH_NPAD_COUNT]; +static bool initialized = false; + +static void mapLibnxToGml(GamepadSlot* slot, PadState* pad, u64 cur) { + if (cur & HidNpadButton_B) slot->buttonDown[0] = true; + if (cur & HidNpadButton_A) slot->buttonDown[1] = true; + if (cur & HidNpadButton_X) slot->buttonDown[2] = true; + if (cur & HidNpadButton_Y) slot->buttonDown[3] = true; + if (cur & HidNpadButton_L) slot->buttonDown[4] = true; + if (cur & HidNpadButton_R) slot->buttonDown[5] = true; + slot->buttonValue[6] = (cur & HidNpadButton_ZL) ? 1.0f : 0.0f; + slot->buttonValue[7] = (cur & HidNpadButton_ZR) ? 1.0f : 0.0f; + if (cur & HidNpadButton_Minus) slot->buttonDown[8] = true; + if (cur & HidNpadButton_Plus) slot->buttonDown[9] = true; + if (cur & HidNpadButton_StickL) slot->buttonDown[10] = true; + if (cur & HidNpadButton_StickR) slot->buttonDown[11] = true; + if (cur & HidNpadButton_AnyUp) slot->buttonDown[12] = true; + if (cur & HidNpadButton_AnyDown) slot->buttonDown[13] = true; + if (cur & HidNpadButton_AnyLeft) slot->buttonDown[14] = true; + if (cur & HidNpadButton_AnyRight) slot->buttonDown[15] = true; + + HidAnalogStickState l = padGetStickPos(pad, 0); + HidAnalogStickState r = padGetStickPos(pad, 1); + slot->axisValue[0] = l.x / 32767.0f; + slot->axisValue[1] = -l.y / 32767.0f; + slot->axisValue[2] = r.x / 32767.0f; + slot->axisValue[3] = -r.y / 32767.0f; +} + +static void fillGamepadSlot(GamepadSlot* slot, PadState* pad, u64 cur, bool connected, int jid, const char* guid) { + memcpy(slot->buttonDownPrev, slot->buttonDown, sizeof(slot->buttonDownPrev)); + memset(slot->buttonDown, 0, sizeof(slot->buttonDown)); + memset(slot->buttonPressed, 0, sizeof(slot->buttonPressed)); + memset(slot->buttonReleased, 0, sizeof(slot->buttonReleased)); + memset(slot->buttonValue, 0, sizeof(slot->buttonValue)); + memset(slot->axisValue, 0, sizeof(slot->axisValue)); + + slot->connected = connected; + slot->jid = jid; + strncpy(slot->description, "Nintendo Switch Controller", sizeof(slot->description) - 1); + strncpy(slot->guid, guid, sizeof(slot->guid) - 1); + + if (connected) { + mapLibnxToGml(slot, pad, cur); + } + + for (int btn = 0; GP_BUTTON_COUNT > btn; btn++) { + bool wasDown = slot->buttonDownPrev[btn]; + if (slot->buttonDown[btn] && !wasDown) slot->buttonPressed[btn] = true; + if (!slot->buttonDown[btn] && wasDown) slot->buttonReleased[btn] = true; + } +} + +bool SwitchInput_handleEvents(struct Runner* runner) { + if (!initialized) { + padConfigureInput(SWITCH_NPAD_COUNT, HidNpadStyleSet_NpadStandard); + padInitializeDefault(&pads[0]); + for (int i = 1; SWITCH_NPAD_COUNT > i; i++) { + padInitialize(&pads[i], HidNpadIdType_No1 + i); + } + initialized = true; + } + + if (!appletMainLoop()) return true; + + int connectedCount = 0; + for (int i = 0; SWITCH_NPAD_COUNT > i; i++) { + padUpdate(&pads[i]); + u64 cur = pads[i].buttons_cur; + bool connected = padIsConnected(&pads[i]); + + char guid[32]; + snprintf(guid, sizeof(guid), "switch-nx-%d", i + 1); + fillGamepadSlot(&runner->gamepads->slots[i], &pads[i], cur, connected, i, guid); + + if (connected) connectedCount++; + } + + runner->gamepads->connectedCount = connectedCount; + + return false; +} diff --git a/src/switch/switch_input.h b/src/switch/switch_input.h new file mode 100644 index 000000000..12d54baf8 --- /dev/null +++ b/src/switch/switch_input.h @@ -0,0 +1,10 @@ +#ifndef _BS_SWITCH_INPUT_H_ +#define _BS_SWITCH_INPUT_H_ + +#include + +struct Runner; + +bool SwitchInput_handleEvents(struct Runner* runner); + +#endif From bd906bb73c1607faed9f2baa7276e24fc46e7c96 Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Tue, 25 Aug 2026 17:30:19 +0100 Subject: [PATCH 16/19] nintendo facebutton layout --- src/switch/switch_input.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/switch/switch_input.c b/src/switch/switch_input.c index 2fb8a58eb..ece5f969e 100644 --- a/src/switch/switch_input.c +++ b/src/switch/switch_input.c @@ -11,10 +11,10 @@ static PadState pads[SWITCH_NPAD_COUNT]; static bool initialized = false; static void mapLibnxToGml(GamepadSlot* slot, PadState* pad, u64 cur) { - if (cur & HidNpadButton_B) slot->buttonDown[0] = true; - if (cur & HidNpadButton_A) slot->buttonDown[1] = true; - if (cur & HidNpadButton_X) slot->buttonDown[2] = true; - if (cur & HidNpadButton_Y) slot->buttonDown[3] = true; + if (cur & HidNpadButton_A) slot->buttonDown[0] = true; + if (cur & HidNpadButton_B) slot->buttonDown[1] = true; + if (cur & HidNpadButton_Y) slot->buttonDown[2] = true; + if (cur & HidNpadButton_X) slot->buttonDown[3] = true; if (cur & HidNpadButton_L) slot->buttonDown[4] = true; if (cur & HidNpadButton_R) slot->buttonDown[5] = true; slot->buttonValue[6] = (cur & HidNpadButton_ZL) ? 1.0f : 0.0f; @@ -49,9 +49,7 @@ static void fillGamepadSlot(GamepadSlot* slot, PadState* pad, u64 cur, bool conn strncpy(slot->description, "Nintendo Switch Controller", sizeof(slot->description) - 1); strncpy(slot->guid, guid, sizeof(slot->guid) - 1); - if (connected) { - mapLibnxToGml(slot, pad, cur); - } + if (connected) mapLibnxToGml(slot, pad, cur); for (int btn = 0; GP_BUTTON_COUNT > btn; btn++) { bool wasDown = slot->buttonDownPrev[btn]; From 6f608285b9604d792fa58e1b1ae190967c5ffc42 Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Tue, 25 Aug 2026 17:31:18 +0100 Subject: [PATCH 17/19] remove stray romfs exit --- src/switch/main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/switch/main.c b/src/switch/main.c index 874ff9fdc..0d00505a3 100644 --- a/src/switch/main.c +++ b/src/switch/main.c @@ -40,6 +40,5 @@ int main(int argc, char* argv[]) { int ret = loop(args, argv[0]); freeCommandLineArgs(&args); - romfsExit(); return ret; } From abe0f738d63bcbfa3ae61c39443e01bc764374d5 Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Tue, 25 Aug 2026 17:33:06 +0100 Subject: [PATCH 18/19] add switch to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b41e0b987..3f8a543bc 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ Of course, there are exceptions that break game compatibility altogether: * PlayStation 2 * PlayStation 3 * PlayStation Vita +* Nintendo Switch * ...and maybe more in the future! Additionally, any platform with reasonably complete C and POSIX conformance should work, the following have been tested. From addbc4ba4d5f7f3310c6ed04eb93a8b452bc62b2 Mon Sep 17 00:00:00 2001 From: Un1q32 Date: Tue, 25 Aug 2026 22:10:08 -0400 Subject: [PATCH 19/19] change file location --- src/switch/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/switch/main.c b/src/switch/main.c index 0d00505a3..07dca27f1 100644 --- a/src/switch/main.c +++ b/src/switch/main.c @@ -35,8 +35,8 @@ int main(int argc, char* argv[]) { #else args.renderer = SOFTWARE; #endif - args.dataWinPath = "sdmc:/data/butterscotch/data.win"; - args.saveFolder = "sdmc:/data/butterscotch"; + args.dataWinPath = "sdmc:/switch/butterscotch/data.win"; + args.saveFolder = "sdmc:/switch/butterscotch"; int ret = loop(args, argv[0]); freeCommandLineArgs(&args);