From 60765b65d8e3ed9ba89dece5512c83957900392c Mon Sep 17 00:00:00 2001
From: AAGaming <aagaming@riseup.net>
Date: Fri, 31 May 2024 21:08:42 -0400
Subject: [PATCH] it builds now

---
 .envrc                                        |  4 +-
 .gitignore                                    |  1 +
 CMakeLists.txt                                | 61 ++++++++++++++++++-
 cmake/Modules/switch.cmake                    | 59 ++++++++++++++++++
 flake.nix                                     | 14 +++--
 src/CMakeLists.txt                            |  6 ++
 src/doomdef.h                                 |  4 +-
 src/doomtype.h                                | 13 ++--
 src/io/streams.cpp                            |  4 +-
 src/sdl/i_main.cpp                            | 32 ++++++++++
 src/stun.cpp                                  |  2 +-
 .../include/tracy/common/TracySystem.cpp      |  6 +-
 12 files changed, 189 insertions(+), 17 deletions(-)
 create mode 100644 cmake/Modules/switch.cmake

diff --git a/.envrc b/.envrc
index 3550a30f2d..78a4a1c1e5 100644
--- a/.envrc
+++ b/.envrc
@@ -1 +1,3 @@
-use flake
+if [ -z "$IN_NIX_SHELL" ]; then
+  use flake
+fi
diff --git a/.gitignore b/.gitignore
index c19183fd08..7c4d1b691f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,4 +23,5 @@ Win32_LIB_ASM_Release
 /bin
 /build
 /CMakeUserPresets.json
+/CMakeCache.txt
 /.direnv
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1f852c981d..d86a3f24f7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -76,6 +76,7 @@ option(SRB2_CONFIG_SKIP_COMPTIME "Skip regenerating comptime. To speed up iterat
 option(SRB2_CONFIG_PROFILEMODE "Compile for profiling (GCC only)." OFF)
 option(SRB2_CONFIG_TRACY "Compile with Tracy profiling enabled" OFF)
 option(SRB2_CONFIG_ASAN "Compile with AddressSanitizer (libasan)." OFF)
+option(SWITCH "Build for the Nintendo Switch." OFF)
 set(SRB2_CONFIG_ASSET_DIRECTORY "" CACHE PATH "Path to directory that contains all asset files for the installer. If set, assets will be part of installation and cpack.")
 
 # Enable CCache
@@ -96,8 +97,53 @@ endif()
 
 add_subdirectory(thirdparty)
 
-find_package(ZLIB REQUIRED)
-find_package(PNG REQUIRED)
+if(SWITCH)
+	set(DEVKITPRO $ENV{DEVKITPRO})
+	include_directories(
+        ${DEVKITPRO}/portlibs/switch/include/SDL2
+        ${DEVKITPRO}/libnx/include
+        ${DEVKITPRO}/portlibs/switch/include
+    )
+	list(APPEND CMAKE_PREFIX_PATH ${DEVKITPRO}/portlibs/switch/lib/cmake)
+	set(PKG_CONFIG_EXECUTABLE ${DEVKITPRO}/portlibs/switch/bin/aarch64-none-elf-pkg-config)
+
+	find_package(PkgConfig REQUIRED)
+
+	pkg_search_module(ZLIB REQUIRED zlib)
+	find_path(ZLIB_INCLUDE_DIR zlib.h HINTS ${ZLIB_INCLUDEDIR} ${ZLIB_INCLUDE_DIRS})
+	find_library(ZLIB_LIBRARY NAMES z HINTS ${ZLIB_LIBDIR} ${ZLIB_LIBRARY_DIRS})
+    add_library(ZLIB::ZLIB STATIC IMPORTED GLOBAL)
+    set_target_properties(ZLIB::ZLIB PROPERTIES
+            IMPORTED_LOCATION "${ZLIB_LIBRARY}"
+            INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIR}")
+
+	pkg_search_module(PNG REQUIRED libpng)
+	find_path(PNG_INCLUDE_DIR png.h HINTS ${PNG_INCLUDEDIR} ${PNG_INCLUDE_DIRS})
+	find_library(PNG_LIBRARY NAMES png HINTS ${PNG_LIBDIR} ${PNG_LIBRARY_DIRS})
+	add_library(PNG::PNG STATIC IMPORTED GLOBAL)
+    set_target_properties(PNG::PNG PROPERTIES
+            IMPORTED_LOCATION "${PNG_LIBRARY}"
+            INTERFACE_INCLUDE_DIRECTORIES "${PNG_INCLUDE_DIR}")
+
+	# TODO USE A PRESET!!!!!!!!!!!
+	add_definitions(-D__SWITCH__)
+	set(SRB2_CONFIG_ENABLE_DISCORDRPC OFF)
+	set(SRB2_CONFIG_ENABLE_STUN OFF)
+
+	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_NXLINK=1 -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE -g -O2 -ffunction-sections -fno-rtti")
+	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_NXLINK=1 -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -g -O2 -ffunction-sections -fPIE")
+	set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --verbose -Wl,-z,notext -L${DEVKITPRO}/libnx/lib -L${DEVKITPRO}/portlibs/switch/lib -g -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE -specs=${DEVKITPRO}/libnx/switch.specs -lnx -lm")
+	set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} --verbose -Wl,-z,notext -L${DEVKITPRO}/libnx/lib -L${DEVKITPRO}/portlibs/switch/lib -g -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE -specs=${DEVKITPRO}/libnx/switch.specs -lnx -lm")
+	set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --verbose -Wl,-z,notext -L${DEVKITPRO}/libnx/lib -L${DEVKITPRO}/portlibs/switch/lib -g -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE -specs=${DEVKITPRO}/libnx/switch.specs -lnx -lm")
+	set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -g -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE")
+	# set(CMAKE_STATIC_LINKER_FLAGS ${CMAKE_STATIC_LINKER_FLAGS} -g -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE)
+	include(switch)
+else()
+	find_package(ZLIB REQUIRED)
+	find_package(PNG REQUIRED)
+endif()
+
+
 find_package(SDL2 CONFIG REQUIRED)
 find_package(CURL REQUIRED)
 # Use the one in thirdparty/fmt to guarantee a minimum version
@@ -193,3 +239,14 @@ list(APPEND EXE_NAME_PARTS ${SRB2_SDL2_EXE_SUFFIX})
 
 list(JOIN EXE_NAME_PARTS "_" EXE_NAME)
 set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME ${EXE_NAME})
+
+if (SWITCH)
+	add_nro_target(ringracers
+	SRB2SDL2
+	"Dr. Robotnik's Ring Racers"
+	"Kart Krew and AAGaming"
+	"${SAFE_REVISION}"
+	"../docs/logo.png"
+	"../res"
+	)
+endif()
diff --git a/cmake/Modules/switch.cmake b/cmake/Modules/switch.cmake
new file mode 100644
index 0000000000..970e0e4f93
--- /dev/null
+++ b/cmake/Modules/switch.cmake
@@ -0,0 +1,59 @@
+# https://github.com/streetpea/chiaki4deck/blob/62247411dda3fdc44d5950234ae8b8b01dc5dc71/cmake/switch.cmake#L22
+
+
+# Find DEVKITPRO
+set(DEVKITPRO "$ENV{DEVKITPRO}" CACHE PATH "Path to DevKitPro")
+if(NOT DEVKITPRO)
+	message(FATAL_ERROR "Please set DEVKITPRO env before calling cmake. https://devkitpro.org/wiki/Getting_Started")
+endif()
+
+# troubleshoot
+message(STATUS "CMAKE_FIND_ROOT_PATH = ${CMAKE_FIND_ROOT_PATH}")
+message(STATUS "PKG_CONFIG_EXECUTABLE = ${PKG_CONFIG_EXECUTABLE}")
+message(STATUS "CMAKE_EXE_LINKER_FLAGS = ${CMAKE_EXE_LINKER_FLAGS}")
+get_property(include_directories DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
+message(STATUS "INCLUDE_DIRECTORIES = ${include_directories}")
+message(STATUS "CMAKE_C_COMPILER = ${CMAKE_C_COMPILER}")
+message(STATUS "CMAKE_CXX_COMPILER = ${CMAKE_CXX_COMPILER}")
+
+find_program(ELF2NRO elf2nro ${DEVKITPRO}/tools/bin)
+if (ELF2NRO)
+	message(STATUS "elf2nro: ${ELF2NRO} - found")
+else()
+	message(WARNING "elf2nro - not found")
+endif()
+
+find_program(NACPTOOL nacptool ${DEVKITPRO}/tools/bin)
+if (NACPTOOL)
+	message(STATUS "nacptool: ${NACPTOOL} - found")
+else()
+	message(WARNING "nacptool - not found")
+endif()
+
+function(__add_nacp target APP_TITLE APP_AUTHOR APP_VERSION)
+	set(__NACP_COMMAND ${NACPTOOL} --create ${APP_TITLE} ${APP_AUTHOR} ${APP_VERSION} ${CMAKE_CURRENT_BINARY_DIR}/${target})
+
+	add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target}
+		COMMAND ${__NACP_COMMAND}
+		WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
+		VERBATIM
+		)
+endfunction()
+
+function(add_nro_target output_name target title author version icon romfs)
+	if(NOT ${output_name}.nacp)
+		__add_nacp(${output_name}.nacp ${title} ${author} ${version})
+	endif()
+	add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${output_name}.nro
+		COMMAND ${ELF2NRO} $<TARGET_FILE:${target}>
+		${CMAKE_CURRENT_BINARY_DIR}/${output_name}.nro
+		--icon=${icon}
+		--nacp=${CMAKE_CURRENT_BINARY_DIR}/${output_name}.nacp
+		--romfsdir=${romfs}
+		DEPENDS ${target} ${CMAKE_CURRENT_BINARY_DIR}/${output_name}.nacp
+		VERBATIM
+		)
+	add_custom_target(${output_name}_nro ALL SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${output_name}.nro)
+endfunction()
+
+set(CMAKE_USE_SYSTEM_ENVIRONMENT_PATH OFF)
diff --git a/flake.nix b/flake.nix
index c0d09521dc..535fd64e96 100644
--- a/flake.nix
+++ b/flake.nix
@@ -22,17 +22,23 @@
       };
     in {
 
-      devShells.default = pkgs.mkShell {
+      devShells.default = (pkgs.buildFHSUserEnv {
+        name = "ringracers-dev";
         # devkitNix packages also provide relevant tools you may want available
         # in your PATH.
-        buildInputs = [pkgs.devkitNix.devkitA64];
+        targetPkgs = pkgs: with pkgs; [
+          pkgs.devkitNix.devkitA64
+          cmake
+          pkg-config
+          ncurses
+        ];
 
         # Each package provides a shell hook that sets all necessary
         # environmental variables. This part is necessary, otherwise your build
         # system won't know where to find devkitPro. By setting these
         # variables we allow devkitPro's example Makefiles to work out of the box.
-        inherit (pkgs.devkitNix.devkitA64) shellHook;
-      };
+        profile = pkgs.devkitNix.devkitA64.shellHook;
+      }).env;
 
       packages.default = pkgs.stdenv.mkDerivation {
         name = "ringracers";
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index af64bb0bcc..feab12bcdd 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -237,6 +237,12 @@ add_subdirectory(blua)
 if (UNIX)
 	target_compile_definitions(SRB2SDL2 PRIVATE -DUNIXCOMMON)
 endif()
+if (SWITCH)
+	message("building for switch")
+	target_compile_definitions(SRB2SDL2 PRIVATE -D__SWITCH__ -D_GNU_SOURCE)
+	# target_compile_options(SRB2SDL2 PUBLIC -fPIE -ffunction-sections)
+	target_link_libraries(SRB2SDL2 PRIVATE -lz -lpng)
+endif()
 
 if(CMAKE_COMPILER_IS_GNUCC)
 	find_program(OBJCOPY objcopy)
diff --git a/src/doomdef.h b/src/doomdef.h
index 69faba1a00..f6a596d256 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -76,7 +76,7 @@ extern "C" {
 //#define PARANOIA // do some tests that never fail but maybe
 // turn this on by make etc.. DEBUGMODE = 1 or use the Debug profile in the VC++ projects
 //#endif
-#if defined (_WIN32) || (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) || defined (macintosh)
+#if defined (_WIN32) || (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) || defined (macintosh) || defined (__SWITCH__)
 #define LOGMESSAGES // write message in log.txt
 #endif
 
@@ -88,7 +88,7 @@ extern char logfilename[1024];
 /* A mod name to further distinguish versions. */
 #define SRB2APPLICATION "RingRacers"
 
-//#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3
+#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3
 #ifdef DEVELOP
 #define PARANOIA // On by default for DEVELOP builds
 #define VERSIONSTRING "Development EXE"
diff --git a/src/doomtype.h b/src/doomtype.h
index 2d35585518..9d1dcc203e 100644
--- a/src/doomtype.h
+++ b/src/doomtype.h
@@ -82,7 +82,9 @@ typedef long ssize_t;
 #endif
 
 /* Strings and some misc platform specific stuff */
-
+#ifdef __SWITCH__
+#include <strings.h>
+#endif
 #ifdef _MSC_VER
 	// Microsoft VisualC++
 #if (_MSC_VER <= 1800) // MSVC 2013 and back
@@ -104,7 +106,7 @@ typedef long ssize_t;
 	#define strncasecmp             strnicmp
 	#define strcasecmp              strcmpi
 #endif
-#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)
+#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) || defined (__SWITCH__)
 	#undef stricmp
 	#define stricmp(x,y) strcasecmp(x,y)
 	#undef strnicmp
@@ -117,7 +119,7 @@ char *nongnu_strcasestr(const char *in, const char *what);
 #endif
 #define stristr strcasestr
 
-#if defined (PC_DOS) || defined (_WIN32) || defined (__HAIKU__)
+#if defined (PC_DOS) || defined (_WIN32) || defined (__HAIKU__) || defined (__SWITCH__)
 #define HAVE_DOSSTR_FUNCS
 #endif
 
@@ -163,8 +165,11 @@ typedef int32_t boolean;
 #endif
 
 #ifndef __cplusplus
-#ifndef _WIN32
+#if !defined (_WIN32) && !defined (__SWITCH__)
 enum {false = 0, true = 1};
+#elif defined (__SWITCH__)
+#define false 0
+#define true 1
 #else
 #define false FALSE
 #define true TRUE
diff --git a/src/io/streams.cpp b/src/io/streams.cpp
index 6b291f2e6e..cf32bf9b20 100644
--- a/src/io/streams.cpp
+++ b/src/io/streams.cpp
@@ -172,7 +172,7 @@ static int portable_fseek64(FILE* file, int64_t offset, int origin)
 {
 #ifdef _MSC_VER
 	return _fseeki64(file, offset, origin);
-#elif __APPLE__ || defined(__FreeBSD__)
+#elif __APPLE__ || defined(__FreeBSD__) || defined(__SWITCH__)
 	return fseeko(file, offset, origin);
 #else
 	return fseeko64(file, offset, origin);
@@ -183,7 +183,7 @@ static int64_t portable_ftell64(FILE* file)
 {
 #ifdef _MSC_VER
 	return _ftelli64(file);
-#elif __APPLE__ || defined(__FreeBSD__)
+#elif __APPLE__ || defined(__FreeBSD__) || defined(__SWITCH__)
 	return ftello(file);
 #else
 	return ftello64(file);
diff --git a/src/sdl/i_main.cpp b/src/sdl/i_main.cpp
index ebddecac9f..0af396a383 100644
--- a/src/sdl/i_main.cpp
+++ b/src/sdl/i_main.cpp
@@ -240,9 +240,11 @@ static void walk_exception_stack(std::string& accum, const std::exception& ex, b
 	else
 		accum.append("Uncaught exception: ");
 
+	#ifndef __SWITCH__
 	accum.append("(");
 	accum.append(typeid(ex).name());
 	accum.append(") ");
+	#endif
 	accum.append(ex.what());
 
 	try {
@@ -254,6 +256,36 @@ static void walk_exception_stack(std::string& accum, const std::exception& ex, b
 	}
 }
 
+#ifdef __SWITCH__
+#include <switch.h>
+#include <sys/socket.h>
+#ifdef ENABLE_NXLINK
+#define TRACE(fmt,...) ((void)0)
+static int s_nxlinkSock = -1;
+
+static void initNxLink()
+{
+    if (R_FAILED(socketInitializeDefault()))
+        return;
+
+    s_nxlinkSock = nxlinkStdio();
+    if (s_nxlinkSock >= 0)
+        TRACE("printf output now goes to nxlink server");
+    else
+        socketExit();
+}
+
+static void deinitNxLink()
+{
+    if (s_nxlinkSock >= 0)
+    {
+        close(s_nxlinkSock);
+        socketExit();
+        s_nxlinkSock = -1;
+    }
+}
+#endif
+#endif
 
 /**	\brief	The main function
 
diff --git a/src/stun.cpp b/src/stun.cpp
index ee981dd2ee..5c7a05ddcf 100644
--- a/src/stun.cpp
+++ b/src/stun.cpp
@@ -20,7 +20,7 @@
 #define _CRT_RAND_S
 #elif defined (__APPLE__)
 #include <CommonCrypto/CommonRandom.h>
-#else
+#elif ! defined (__SWITCH__) // No you don't.
 #error "Need CSPRNG."
 #endif
 
diff --git a/thirdparty/tracy/include/tracy/common/TracySystem.cpp b/thirdparty/tracy/include/tracy/common/TracySystem.cpp
index 9a477aa310..d7f782a4ed 100644
--- a/thirdparty/tracy/include/tracy/common/TracySystem.cpp
+++ b/thirdparty/tracy/include/tracy/common/TracySystem.cpp
@@ -81,6 +81,10 @@ TRACY_API uint32_t GetThreadHandleImpl()
 #elif defined __EMSCRIPTEN__
     // Not supported, but let it compile.
     return 0;
+// TODO BROKEN LOL WTF
+#elif defined __SWITCH__
+    // Not supported, but let it compile.
+    return 0;
 #else
     // To add support for a platform, retrieve and return the kernel thread identifier here.
     //
@@ -88,7 +92,7 @@ TRACY_API uint32_t GetThreadHandleImpl()
     // thread identifier. It is a pointer to a library-allocated data structure instead.
     // Such pointers will be reused heavily, making the pthread_t non-unique. Additionally
     // a 64-bit pointer cannot be reliably truncated to 32 bits.
-    #error "Unsupported platform!"
+    // #error "Unsupported platform!"
 #endif
 
 }
-- 
GitLab