Skip to content

Commit

Permalink
Add Nintendo Switch initial support
Browse files Browse the repository at this point in the history
  • Loading branch information
AGraber committed Jul 12, 2021
1 parent f500268 commit 28f2663
Show file tree
Hide file tree
Showing 13 changed files with 273 additions and 12 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/build-switch.yml
Original file line number Diff line number Diff line change
@@ -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
19 changes: 19 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 8 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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)")
Expand Down
7 changes: 7 additions & 0 deletions cmake/nx/NXFunctions.cmake
Original file line number Diff line number Diff line change
@@ -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()
Binary file added logo_switch.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 38 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
)

Expand All @@ -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()
4 changes: 4 additions & 0 deletions src/core/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
9 changes: 7 additions & 2 deletions src/core/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
2 changes: 0 additions & 2 deletions src/core/re3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@
#include "Population.h"
#include "IniFile.h"

#ifdef DETECT_JOYSTICK_MENU
#include "crossplatform.h"
#endif

#ifndef _WIN32
#include "assert.h"
Expand Down
146 changes: 145 additions & 1 deletion src/skel/crossplatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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("/");
Expand All @@ -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)
Expand Down Expand Up @@ -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
2 changes: 2 additions & 0 deletions src/skel/events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,9 @@ PadHandler(RsEvent event, void *param)
RwBool
AttachInputDevices(void)
{
#ifndef IGNORE_MOUSE_KEYBOARD
RsInputDeviceAttach(rsKEYBOARD, KeyboardHandler);
#endif

RsInputDeviceAttach(rsPAD, PadHandler);

Expand Down
Loading

0 comments on commit 28f2663

Please sign in to comment.