summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build-switch.yml28
-rw-r--r--.vscode/c_cpp_properties.json19
-rw-r--r--.vscode/settings.json10
-rw-r--r--CMakeLists.txt6
-rw-r--r--cmake/nx/NXFunctions.cmake7
-rw-r--r--logo_switch.jpgbin0 -> 18096 bytes
-rw-r--r--src/CMakeLists.txt40
-rw-r--r--src/core/common.h4
-rw-r--r--src/core/config.h9
-rw-r--r--src/core/re3.cpp2
-rw-r--r--src/skel/crossplatform.cpp146
-rw-r--r--src/skel/events.cpp2
-rw-r--r--src/skel/glfw/glfw.cpp12
13 files changed, 273 insertions, 12 deletions
diff --git a/.github/workflows/build-switch.yml b/.github/workflows/build-switch.yml
new file mode 100644
index 00000000..46e1d501
--- /dev/null
+++ b/.github/workflows/build-switch.yml
@@ -0,0 +1,28 @@
+name: re3 cmake devkitA64 (Nintendo Switch)
+on:
+ pull_request:
+ push:
+ release:
+ types: published
+jobs:
+ build-nintendo-switch:
+ runs-on: ubuntu-latest
+ container: devkitpro/devkita64:latest
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ submodules: 'true'
+ - name: "Build files"
+ run: |
+ /opt/devkitpro/portlibs/switch/bin/aarch64-none-elf-cmake -S. -Bbuild -DRE3_AUDIO=OAL -DLIBRW_PLATFORM=GL3 -DLIBRW_GL3_GFXLIB=GLFW -DRE3_WITH_OPUS=False -DRE3_VENDORED_LIBRW=True -DRE3_INSTALL=True
+ cmake --build build --parallel
+ - name: "Create binary package (cpack)"
+ working-directory: ./build
+ run: |
+ cpack
+ - name: "Archive binary package (github artifacts)"
+ uses: actions/upload-artifact@v2
+ with:
+ name: "switch-gl3"
+ path: build/*.zip
+ if-no-files-found: error
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index 327d8cc7..a214042a 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -26,6 +26,25 @@
"compilerArgs": ["-ggdb"],
"cStandard": "gnu11",
"cppStandard": "gnu++14"
+ },
+ {
+ "name": "devkitPro aarch64 (Nintendo Switch)",
+ "compilerPath": "${env:DEVKITPRO}/devkitA64/bin/aarch64-none-elf-g++",
+ "includePath": [
+ "${default}",
+ "${env:DEVKITPRO}/portlibs/switch/include",
+ "${env:DEVKITPRO}/libnx/include"
+ ],
+ "intelliSenseMode": "gcc-arm64",
+ "cStandard": "gnu11",
+ "cppStandard": "gnu++11",
+ "defines": [
+ "__SWITCH__",
+ "GTA_SWITCH",
+ "LIBRW",
+ "RW_GL3",
+ "AUDIO_OAL"
+ ]
}
],
"version": 4
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 10cb5627..ee8362c1 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -2,8 +2,13 @@
"C_Cpp.default.cStandard": "gnu11",
"C_Cpp.default.cppStandard": "gnu++14",
"C_Cpp.default.includePath": [
+ "src",
"src/animation",
"src/audio",
+ "src/audio/eax",
+ "src/audio/oal",
+ "src/buildings",
+ "src/collision",
"src/control",
"src/core",
"src/entities",
@@ -15,8 +20,9 @@
"src/peds",
"src/render",
"src/rw",
- "src/save",
- "src/skel",
+ "src/save/",
+ "src/skel/",
+ "src/skel/glfw",
"src/text",
"src/vehicles",
"src/weapons",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5396d3b4..b687124a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,6 +12,10 @@ message(STATUS "Building ${CMAKE_PROJECT_NAME} GIT SHA1: ${GIT_SHA1}")
if(WIN32)
set(${PROJECT}_AUDIOS "OAL" "MSS")
+elseif(NINTENDO_SWITCH)
+ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/nx")
+ include(NXFunctions)
+ set(${PROJECT}_AUDIOS "OAL")
else()
set(${PROJECT}_AUDIOS "OAL")
endif()
@@ -66,6 +70,8 @@ if(${PROJECT}_INSTALL)
set(os "-apple")
elseif(UNIX)
set(os "-linux")
+ elseif(NINTENDO_SWITCH)
+ set(os "-switch")
else()
set(compiler "-UNK")
message(WARNING "Unknown os. Created cpack package will be wrong. (override using cpack -P)")
diff --git a/cmake/nx/NXFunctions.cmake b/cmake/nx/NXFunctions.cmake
new file mode 100644
index 00000000..8fa23fae
--- /dev/null
+++ b/cmake/nx/NXFunctions.cmake
@@ -0,0 +1,7 @@
+if(NOT COMMAND nx_generate_nacp)
+ message(FATAL_ERROR "The `nx_generate_nacp` cmake command is not available. Please use an appropriate Nintendo Switch toolchain.")
+endif()
+
+if(NOT COMMAND nx_create_nro)
+ message(FATAL_ERROR "The `nx_create_nro` cmake command is not available. Please use an appropriate Nintendo Switch toolchain.")
+endif()
diff --git a/logo_switch.jpg b/logo_switch.jpg
new file mode 100644
index 00000000..595d2c3b
--- /dev/null
+++ b/logo_switch.jpg
Binary files differ
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 28090d7e..67dfb325 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -120,13 +120,19 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
)
endif()
+if(NINTENDO_SWITCH)
+ set(${PROJECT}_C_CXX_EXTENSIONS ON)
+else()
+ set(${PROJECT}_C_CXX_EXTENSIONS OFF)
+endif()
+
set_target_properties(${EXECUTABLE}
PROPERTIES
C_STANDARD 11
- C_EXTENSIONS OFF
+ C_EXTENSIONS ${${PROJECT}_C_CXX_EXTENSIONS}
C_STANDARD_REQUIRED ON
CXX_STANDARD 11
- CXX_EXTENSIONS OFF
+ CXX_EXTENSIONS ${${PROJECT}_C_CXX_EXTENSIONS}
CXX_STANDARD_REQUIRED ON
)
@@ -140,3 +146,33 @@ if(${PROJECT}_INSTALL)
install(FILES $<TARGET_PDB_FILE:${EXECUTABLE}> DESTINATION "." OPTIONAL)
endif()
endif()
+
+# Build Nintendo Switch binaries
+if(NINTENDO_SWITCH)
+ target_compile_definitions(${EXECUTABLE} PRIVATE
+ GTA_SWITCH
+ )
+
+ # Needed for OpenAL-Soft
+ target_link_libraries(${EXECUTABLE} PRIVATE
+ openal # HACK - something broke with latest cmake
+ SDL2
+ )
+
+ nx_generate_nacp (${EXECUTABLE}.nacp
+ NAME "${EXECUTABLE}"
+ AUTHOR "${EXECUTABLE} Team"
+ VERSION "1.0.0-${GIT_SHA1}"
+ )
+
+ nx_create_nro(${EXECUTABLE}
+ NACP ${EXECUTABLE}.nacp
+ ICON "${PROJECT_SOURCE_DIR}/logo_switch.jpg"
+ )
+
+ if(${PROJECT}_INSTALL)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}.nro"
+ DESTINATION "."
+ )
+ endif()
+endif()
diff --git a/src/core/common.h b/src/core/common.h
index da162762..99aafc5a 100644
--- a/src/core/common.h
+++ b/src/core/common.h
@@ -11,6 +11,10 @@
#define __STDC_LIMIT_MACROS // so we get UINT32_MAX etc
#endif
+#ifdef GTA_SWITCH
+#include <switch.h>
+#endif
+
#include <stdint.h>
#include <string.h>
#include <math.h>
diff --git a/src/core/config.h b/src/core/config.h
index 885f98b8..edb5fb5a 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -319,7 +319,7 @@ enum Config {
#if !defined(RW_GL3) && defined(_WIN32)
#define XINPUT
#endif
-#if defined XINPUT || (defined RW_GL3 && !defined LIBRW_SDL2 && !defined __SWITCH__)
+#if defined XINPUT || (defined RW_GL3 && !defined LIBRW_SDL2 && !defined GTA_SWITCH)
#define DETECT_JOYSTICK_MENU // Then we'll expect user to enter Controller->Detect joysticks if his joystick isn't detected at the start.
#endif
#define DETECT_PAD_INPUT_SWITCH // Adds automatic switch of pad related stuff between controller and kb/m
@@ -439,7 +439,7 @@ enum Config {
#endif
// Streaming
-#if !defined(_WIN32) && !defined(__SWITCH__)
+#if !defined(_WIN32) && !defined(GTA_SWITCH)
//#define ONE_THREAD_PER_CHANNEL // Don't use if you're not on SSD/Flash - also not utilized too much right now(see commented LoadAllRequestedModels in Streaming.cpp)
#define FLUSHABLE_STREAMING // Make it possible to interrupt reading when processing file isn't needed anymore.
#endif
@@ -461,4 +461,9 @@ enum Config {
#undef PEDS_REPORT_CRIMES_ON_PHONE
#endif
+#ifdef GTA_SWITCH
+ #define IGNORE_MOUSE_KEYBOARD // ignore mouse & keyboard input
+ #define USE_UNNAMED_SEM // named semaphores are unsupported on the switch
+#endif
+
#endif // VANILLA_DEFINES
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index b7d89363..40be153a 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -45,9 +45,7 @@
#include "Population.h"
#include "IniFile.h"
-#ifdef DETECT_JOYSTICK_MENU
#include "crossplatform.h"
-#endif
#ifndef _WIN32
#include "assert.h"
diff --git a/src/skel/crossplatform.cpp b/src/skel/crossplatform.cpp
index 577983b6..758125e9 100644
--- a/src/skel/crossplatform.cpp
+++ b/src/skel/crossplatform.cpp
@@ -198,6 +198,20 @@ char* casepath(char const* path, bool checkPathFirst)
size_t rl = 0;
DIR* d;
+ char* c;
+
+ #if defined(GTA_SWITCH) || defined(GTA_VITA)
+ if( (c = strstr(p, ":/")) != NULL) // scheme used by some environments, eg. switch, vita
+ {
+ size_t deviceNameOffset = c - p + 3;
+ char* deviceNamePath = (char*)alloca(deviceNameOffset + 1);
+ strlcpy(deviceNamePath, p, deviceNameOffset);
+ deviceNamePath[deviceNameOffset] = 0;
+ d = opendir(deviceNamePath);
+ p = c + 1;
+ }
+ else
+ #endif
if (p[0] == '/' || p[0] == '\\')
{
d = opendir("/");
@@ -212,7 +226,7 @@ char* casepath(char const* path, bool checkPathFirst)
bool cantProceed = false; // just convert slashes in what's left in string, don't correct case of letters(because we can't)
bool mayBeTrailingSlash = false;
- char* c;
+
while (c = strsep(&p, "/\\"))
{
// May be trailing slash(allow), slash at the start(avoid), or multiple slashes(avoid)
@@ -279,3 +293,133 @@ char* casepath(char const* path, bool checkPathFirst)
return out;
}
#endif
+
+#ifdef GTA_SWITCH
+/* Taken from glibc */
+char *realpath(const char *name, char *resolved)
+{
+ char *rpath, *dest = NULL;
+ const char *start, *end, *rpath_limit;
+ long int path_max;
+
+ /* As per Single Unix Specification V2 we must return an error if
+ either parameter is a null pointer. We extend this to allow
+ the RESOLVED parameter to be NULL in case the we are expected to
+ allocate the room for the return value. */
+ if (!name)
+ return NULL;
+
+ /* As per Single Unix Specification V2 we must return an error if
+ the name argument points to an empty string. */
+ if (name[0] == '\0')
+ return NULL;
+
+#ifdef PATH_MAX
+ path_max = PATH_MAX;
+#else
+ path_max = pathconf(name, _PC_PATH_MAX);
+ if (path_max <= 0)
+ path_max = 1024;
+#endif
+
+ if (!resolved)
+ {
+ rpath = (char*)malloc(path_max);
+ if (!rpath)
+ return NULL;
+ }
+ else
+ rpath = resolved;
+ rpath_limit = rpath + path_max;
+
+ if (name[0] != '/')
+ {
+ if (!getcwd(rpath, path_max))
+ {
+ rpath[0] = '\0';
+ goto error;
+ }
+ dest = (char*)memchr(rpath, '\0', path_max);
+ }
+ else
+ {
+ rpath[0] = '/';
+ dest = rpath + 1;
+ }
+
+ for (start = end = name; *start; start = end)
+ {
+ /* Skip sequence of multiple path-separators. */
+ while (*start == '/')
+ ++start;
+
+ /* Find end of path component. */
+ for (end = start; *end && *end != '/'; ++end)
+ /* Nothing. */;
+
+ if (end - start == 0)
+ break;
+ else if (end - start == 1 && start[0] == '.')
+ /* nothing */;
+ else if (end - start == 2 && start[0] == '.' && start[1] == '.')
+ {
+ /* Back up to previous component, ignore if at root already. */
+ if (dest > rpath + 1)
+ while ((--dest)[-1] != '/')
+ ;
+ }
+ else
+ {
+ size_t new_size;
+
+ if (dest[-1] != '/')
+ *dest++ = '/';
+
+ if (dest + (end - start) >= rpath_limit)
+ {
+ ptrdiff_t dest_offset = dest - rpath;
+ char *new_rpath;
+
+ if (resolved)
+ {
+ if (dest > rpath + 1)
+ dest--;
+ *dest = '\0';
+ goto error;
+ }
+ new_size = rpath_limit - rpath;
+ if (end - start + 1 > path_max)
+ new_size += end - start + 1;
+ else
+ new_size += path_max;
+ new_rpath = (char *)realloc(rpath, new_size);
+ if (!new_rpath)
+ goto error;
+ rpath = new_rpath;
+ rpath_limit = rpath + new_size;
+
+ dest = rpath + dest_offset;
+ }
+
+ dest = (char*)memcpy(dest, start, end - start);
+ *dest = '\0';
+ }
+ }
+ if (dest > rpath + 1 && dest[-1] == '/')
+ --dest;
+ *dest = '\0';
+
+ return rpath;
+
+error:
+ if (!resolved)
+ free(rpath);
+ return NULL;
+}
+
+ssize_t readlink (const char * __path, char * __buf, size_t __buflen)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
diff --git a/src/skel/events.cpp b/src/skel/events.cpp
index 3e1e95b3..87447819 100644
--- a/src/skel/events.cpp
+++ b/src/skel/events.cpp
@@ -821,7 +821,9 @@ PadHandler(RsEvent event, void *param)
RwBool
AttachInputDevices(void)
{
+#ifndef IGNORE_MOUSE_KEYBOARD
RsInputDeviceAttach(rsKEYBOARD, KeyboardHandler);
+#endif
RsInputDeviceAttach(rsPAD, PadHandler);
diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp
index 8d3fc7d7..c7f92d34 100644
--- a/src/skel/glfw/glfw.cpp
+++ b/src/skel/glfw/glfw.cpp
@@ -12,12 +12,14 @@ DWORD _dwOperatingSystemVersion;
#include "resource.h"
#else
long _dwOperatingSystemVersion;
+#ifndef GTA_SWITCH
#ifndef __APPLE__
#include <sys/sysinfo.h>
#else
#include <mach/mach_host.h>
#include <sys/sysctl.h>
#endif
+#endif
#include <errno.h>
#include <locale.h>
#include <signal.h>
@@ -51,7 +53,7 @@ long _dwOperatingSystemVersion;
#include "MemoryMgr.h"
// We found out that GLFW's keyboard input handling is still pretty delayed/not stable, so now we fetch input from X11 directly on Linux.
-#if !defined _WIN32 && !defined __APPLE__ && !defined __SWITCH__ // && !defined WAYLAND
+#if !defined _WIN32 && !defined __APPLE__ && !defined GTA_SWITCH // && !defined WAYLAND
#define GET_KEYBOARD_INPUT_FROM_X11
#endif
@@ -485,12 +487,14 @@ psInitialize(void)
debug("Physical memory size %llu\n", _dwMemAvailPhys);
debug("Available physical memory %llu\n", size);
#else
+#ifndef GTA_SWITCH
struct sysinfo systemInfo;
sysinfo(&systemInfo);
_dwMemAvailPhys = systemInfo.freeram;
debug("Physical memory size %u\n", systemInfo.totalram);
debug("Available physical memory %u\n", systemInfo.freeram);
#endif
+#endif
TheText.Unload();
@@ -949,13 +953,15 @@ void psPostRWinit(void)
RwVideoMode vm;
RwEngineGetVideoModeInfo(&vm, GcurSelVM);
+ glfwSetFramebufferSizeCallback(PSGLOBAL(window), resizeCB);
+#ifndef IGNORE_MOUSE_KEYBOARD
#ifndef GET_KEYBOARD_INPUT_FROM_X11
glfwSetKeyCallback(PSGLOBAL(window), keypressCB);
#endif
- glfwSetFramebufferSizeCallback(PSGLOBAL(window), resizeCB);
glfwSetScrollCallback(PSGLOBAL(window), scrollCB);
glfwSetCursorPosCallback(PSGLOBAL(window), cursorCB);
glfwSetCursorEnterCallback(PSGLOBAL(window), cursorEnterCB);
+#endif
glfwSetWindowIconifyCallback(PSGLOBAL(window), windowIconifyCB);
glfwSetWindowFocusCallback(PSGLOBAL(window), windowFocusCB);
glfwSetJoystickCallback(joysChangeCB);
@@ -1791,7 +1797,7 @@ main(int argc, char *argv[])
InitMemoryMgr();
#endif
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(GTA_SWITCH)
struct sigaction act;
act.sa_sigaction = terminateHandler;
act.sa_flags = SA_SIGINFO;