diff --git a/.github/workflows/libretro-switch.yml b/.github/workflows/libretro-switch.yml deleted file mode 100644 index f6112512e..000000000 --- a/.github/workflows/libretro-switch.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Libretro - Nintendo Switch CI - -on: [push, pull_request] - -jobs: - build: - runs-on: ubuntu-latest - container: devkitpro/devkita64:latest - - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - submodules: recursive - - - name: CMake - run: | - cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=$DEVKITPRO/cmake/Switch.cmake -DLIBRETRO=ON - cmake --build build --config Release --target combined --parallel 2 diff --git a/.github/workflows/switch.yml b/.github/workflows/switch.yml new file mode 100644 index 000000000..0039ac9ee --- /dev/null +++ b/.github/workflows/switch.yml @@ -0,0 +1,33 @@ +name: Nintendo Switch CI + +on: [push, pull_request] + +jobs: + build: + name: ${{ matrix.config.name }} + runs-on: ubuntu-latest + container: devkitpro/devkita64:latest + + strategy: + matrix: + config: + - {name: standalone} + - {name: libretro, cmakeArgs: -DLIBRETRO=ON} + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + submodules: recursive + + - name: CMake + run: | + cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=$DEVKITPRO/cmake/Switch.cmake ${{ matrix.config.cmakeArgs }} + cmake --build build --config Release --parallel 2 + + - uses: actions/upload-artifact@v2 + with: + name: flycast-switch-${{ matrix.config.name }} + path: build/artifact + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index e094dcb6e..620fbb3f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,17 +52,24 @@ endif() string(TIMESTAMP BUILD_TIMESTAMP UTC) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/core/version.h.in" "${CMAKE_CURRENT_SOURCE_DIR}/core/version.h" @ONLY) -if(LIBRETRO) - if (NINTENDO_SWITCH) - add_library(${PROJECT_NAME} STATIC core/emulator.cpp) - set(USE_VULKAN OFF) - set(USE_GLES OFF) - set(USE_GLES2 OFF) - enable_language(ASM) - target_compile_definitions(${PROJECT_NAME} PRIVATE HAVE_LIBNX) - else() - add_library(${PROJECT_NAME} SHARED core/emulator.cpp) - endif() +if(NINTENDO_SWITCH) + set(USE_VULKAN OFF) + set(USE_GLES OFF) + set(USE_GLES2 OFF) + enable_language(ASM) + + if(LIBRETRO) + add_library(${PROJECT_NAME} STATIC core/emulator.cpp) + target_compile_definitions(${PROJECT_NAME} PRIVATE LIBRETRO HAVE_LIBNX HAVE_OPENGL HAVE_OIT) + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "flycast_libretro_libnx") + set(CMAKE_STATIC_LIBRARY_PREFIX "") + else() + add_executable(${PROJECT_NAME} core/emulator.cpp) + target_compile_definitions(${PROJECT_NAME} PRIVATE EGL_NO_PLATFORM_SPECIFIC_TYPES) + endif() + +elseif(LIBRETRO) + add_library(${PROJECT_NAME} SHARED core/emulator.cpp) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "flycast_libretro") set(CMAKE_SHARED_LIBRARY_PREFIX "") @@ -118,9 +125,9 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE target_include_directories(${PROJECT_NAME} PRIVATE core core/deps core/deps/stb core/khronos) if(LIBRETRO) target_include_directories(${PROJECT_NAME} PRIVATE shell/libretro) - if(NINTENDO_SWITCH) - target_include_directories(${PROJECT_NAME} PRIVATE shell/switch "${DEVKITPRO}/portlibs/switch/include") - endif() +endif() +if(NINTENDO_SWITCH) + target_include_directories(${PROJECT_NAME} PRIVATE shell/switch "${DEVKITPRO}/portlibs/switch/include") endif() find_package(OpenMP) @@ -191,6 +198,8 @@ if(NOT LIBRETRO) target_sources(${PROJECT_NAME} PRIVATE core/sdl/sdl.cpp core/sdl/sdl.h core/sdl/sdl_gamepad.h core/sdl/sdl_keyboard.h) if(APPLE) target_include_directories(${PROJECT_NAME} PRIVATE "${SDL2_INCLUDE_DIRS}/..") + elseif(NINTENDO_SWITCH) + target_include_directories(${PROJECT_NAME} PRIVATE "${DEVKITPRO}/portlibs/switch/include/SDL2") else() target_include_directories(${PROJECT_NAME} PRIVATE ${SDL2_INCLUDE_DIRS}) endif() @@ -787,7 +796,7 @@ if(NOT APPLE AND NOT LIBRETRO) core/wsi/gl32funcs.c core/wsi/gl32funcs.h) endif() -if(NOT NINTENDO_SWITCH) +if(NOT (NINTENDO_SWITCH AND LIBRETRO)) target_sources(${PROJECT_NAME} PRIVATE core/wsi/gl4funcs.cpp) endif() @@ -1082,7 +1091,7 @@ if(NOT LIBRETRO) find_library(AUDIO_TOOLBOX_LIBRARY AudioToolbox) target_link_libraries(${PROJECT_NAME} PRIVATE ${AUDIO_UNIT_LIBRARY} ${FOUNDATION_LIBRARY} ${AUDIO_TOOLBOX_LIBRARY}) - elseif(UNIX) + elseif(UNIX OR NINTENDO_SWITCH) if(NOT BUILD_TESTING) target_sources(${PROJECT_NAME} PRIVATE core/linux-dist/main.cpp) @@ -1116,15 +1125,27 @@ if(BUILD_TESTING) endif() if(NINTENDO_SWITCH) - add_custom_target(combined - COMMAND ${CMAKE_AR} -x $ - COMMAND ${CMAKE_AR} -x $ - COMMAND ${CMAKE_AR} -x $ - COMMAND ${CMAKE_AR} -rs libflycast_libretro.a *.obj - COMMAND mv libflycast_libretro.a flycast_libretro_libnx.a - COMMAND rm *.obj - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - DEPENDS xxHash::xxhash chdr-static zip) - add_dependencies(combined ${PROJECT_NAME}) + if(LIBRETRO) + add_custom_target(combined ALL + COMMAND ${CMAKE_AR} -x $ + COMMAND ${CMAKE_AR} -x $ + COMMAND ${CMAKE_AR} -x $ + COMMAND ${CMAKE_AR} -rs flycast_libretro_libnx.a *.obj + COMMAND rm *.obj + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS xxHash::xxhash chdr-static zip) + add_dependencies(combined ${PROJECT_NAME}) + else() + add_custom_command(OUTPUT flycast.nacp + COMMAND ${DEVKITPRO}/tools/bin/nacptool --create Flycast "flyinghead, M4xw" ${GIT_VERSION} ${CMAKE_BINARY_DIR}/flycast.nacp + COMMENT "Generating NACP info") + + add_custom_command(OUTPUT flycast.nro + COMMAND mkdir -p ${CMAKE_BINARY_DIR}/artifact + COMMAND ${DEVKITPRO}/tools/bin/elf2nro ${CMAKE_BINARY_DIR}/flycast ${CMAKE_BINARY_DIR}/artifact/flycast.nro --icon=${CMAKE_SOURCE_DIR}/shell/linux/flycast.png --nacp=${CMAKE_BINARY_DIR}/flycast.nacp + DEPENDS flycast.nacp ${CMAKE_BINARY_DIR}/flycast + COMMENT "Generating NRO") + add_custom_target(nro ALL DEPENDS flycast.nacp flycast.nro) + endif() endif() diff --git a/core/khronos/GL4/gl3w.c b/core/khronos/GL4/gl3w.c index eb85f8cba..661dc1c8f 100644 --- a/core/khronos/GL4/gl3w.c +++ b/core/khronos/GL4/gl3w.c @@ -88,8 +88,10 @@ static GL3WglProc get_proc(const char *proc) *(void **)(&res) = dlsym(libgl, proc); return res; } -#elif defined(__ANDROID__) +#elif defined(__ANDROID__) || defined(__SWITCH__) +#ifdef __ANDROID__ #include +#endif #include static int open_libgl(void) diff --git a/core/linux-dist/main.cpp b/core/linux-dist/main.cpp index b956005a4..25af8566d 100644 --- a/core/linux-dist/main.cpp +++ b/core/linux-dist/main.cpp @@ -1,6 +1,6 @@ #include "types.h" -#if defined(__unix__) +#if defined(__unix__) || defined(__SWITCH__) #include "hw/sh4/dyna/blockmanager.h" #include "log/LogManager.h" #include "emulator.h" @@ -11,6 +11,13 @@ #include #include +#if defined(__SWITCH__) +// name conflict +#define Event SwitchEvent +#include +#undef Event +#endif + #if defined(SUPPORT_DISPMANX) #include "dispmanx.h" #endif @@ -123,6 +130,7 @@ void common_linux_setup(); // If no folder exists, $HOME/.config/flycast is created and used. std::string find_user_config_dir() { +#ifndef __SWITCH__ struct stat info; std::string xdg_home; if (nowide::getenv("HOME") != NULL) @@ -160,7 +168,7 @@ std::string find_user_config_dir() return fullpath; } - +#endif // Unable to detect config dir, use the current folder return "."; } @@ -173,6 +181,7 @@ std::string find_user_config_dir() // If no folder exists, $HOME/.local/share/flycast is created and used. std::string find_user_data_dir() { +#ifndef __SWITCH__ struct stat info; std::string xdg_home; if (nowide::getenv("HOME") != NULL) @@ -210,7 +219,7 @@ std::string find_user_data_dir() return fullpath; } - +#endif // Unable to detect data dir, use the current folder return "."; } @@ -247,6 +256,7 @@ std::vector find_system_config_dirs() { std::vector dirs; +#ifndef __SWITCH__ std::string xdg_home; if (nowide::getenv("HOME") != NULL) { @@ -275,6 +285,7 @@ std::vector find_system_config_dirs() dirs.push_back("/etc/flycast/"); // This isn't part of the XDG spec, but much more common than /etc/xdg/ dirs.push_back("/etc/xdg/flycast/"); } +#endif dirs.push_back("./"); return dirs; @@ -300,6 +311,7 @@ std::vector find_system_data_dirs() { std::vector dirs; +#ifndef __SWITCH__ std::string xdg_home; if (nowide::getenv("HOME") != NULL) { @@ -337,6 +349,7 @@ std::vector find_system_data_dirs() std::string path = (std::string)nowide::getenv("FLYCAST_BIOS_PATH"); addDirectoriesFromPath(dirs, path, "/"); } +#endif dirs.push_back("./"); dirs.push_back("data/"); @@ -345,6 +358,15 @@ std::vector find_system_data_dirs() int main(int argc, char* argv[]) { +#if defined(__SWITCH__) + socketInitializeDefault(); + nxlinkStdio(); + + hidInitializeTouchScreen(); + hidInitializeMouse(); + hidInitializeKeyboard(); +#endif // __SWITCH__ + LogManager::Init(); // Set directories @@ -365,7 +387,9 @@ int main(int argc, char* argv[]) } #endif +#if defined(__unix__) common_linux_setup(); +#endif if (reicast_init(argc, argv)) die("Flycast initialization failed\n"); @@ -388,9 +412,12 @@ int main(int argc, char* argv[]) return 0; } -#endif +#if defined(__unix__) void os_DebugBreak() { raise(SIGTRAP); } +#endif + +#endif // __unix__ || __SWITCH__ diff --git a/core/log/ConsoleListenerNix.cpp b/core/log/ConsoleListenerNix.cpp index 4aa67c048..0fdf88cd3 100644 --- a/core/log/ConsoleListenerNix.cpp +++ b/core/log/ConsoleListenerNix.cpp @@ -16,6 +16,8 @@ ConsoleListener::ConsoleListener() { #ifdef LOG_TO_PTY m_use_color = 1; +#elif defined(__SWITCH__) + m_use_color = 0; #else m_use_color = !!isatty(fileno(stderr)); #endif diff --git a/core/network/net_platform.h b/core/network/net_platform.h index f151a1047..e63c6b6ae 100644 --- a/core/network/net_platform.h +++ b/core/network/net_platform.h @@ -24,7 +24,10 @@ #include #include #ifdef __SWITCH__ +// name conflict +#define Event SwitchEvent #include +#undef Event #ifndef INADDR_NONE #define INADDR_NONE 0xffffffff #endif diff --git a/core/nullDC.cpp b/core/nullDC.cpp index 692fa7be3..a37c63512 100644 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -52,6 +52,8 @@ int reicast_init(int argc, char* argv[]) os_SetupInput(); // Needed to avoid crash calling dc_is_running() in gui + if (!_nvmem_enabled()) + dc_init(); Get_Sh4Interpreter(&sh4_cpu); sh4_cpu.Init(); debugger::init(); diff --git a/core/wsi/gl_context.h b/core/wsi/gl_context.h index 2244138ea..6988adc12 100644 --- a/core/wsi/gl_context.h +++ b/core/wsi/gl_context.h @@ -55,7 +55,7 @@ private: #include "sdl.h" -#elif defined(GLES) || defined(__ANDROID__) +#elif defined(GLES) || defined(__ANDROID__) || defined(__SWITCH__) #include "egl.h"