Nintendo Switch support

This commit is contained in:
Adrian Graber 2021-07-13 01:11:42 +02:00
parent 523b23339c
commit 6665b16ba2
33 changed files with 481 additions and 19 deletions

29
.github/workflows/build-switch.yml vendored Normal file
View file

@ -0,0 +1,29 @@
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 -DREVC_AUDIO=OAL -DLIBRW_PLATFORM=GL3 -DLIBRW_GL3_GFXLIB=GLFW -DREVC_WITH_OPUS=False -DREVC_VENDORED_LIBRW=True -DREVC_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

View file

@ -26,6 +26,24 @@
"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__",
"LIBRW",
"RW_GL3",
"AUDIO_OAL"
]
}
],
"version": 4

View file

@ -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",
@ -16,6 +21,7 @@
"src/render",
"src/rw",
"src/save",
"src/save/glfw",
"src/skel",
"src/text",
"src/vehicles",

View file

@ -1,15 +1,27 @@
cmake_minimum_required(VERSION 3.8)
cmake_minimum_required(VERSION 3.14)
set(EXECUTABLE reVC)
set(PROJECT REVC)
project(${EXECUTABLE} C CXX)
set(${PROJECT}_AUTHOR "${PROJECT} Team")
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REFSPEC GIT_SHA1 "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR")
message(STATUS "Building ${CMAKE_PROJECT_NAME} GIT SHA1: ${GIT_SHA1}")
if(NINTENDO_SWITCH)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/nx")
include(NXFunctions)
endif()
if(NOT COMMAND reVC_platform_target)
function(reVC_platform_target)
endfunction()
endif()
if(WIN32)
set(${PROJECT}_AUDIOS "OAL" "MSS")
else()
@ -66,6 +78,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)")

View file

@ -1,4 +1,4 @@
<img src="https://github.com/GTAmodding/re3/blob/miami/logo.png?raw=true" alt="reVC logo" width="200">
<img src="https://github.com/GTAmodding/re3/blob/miami/res/images/logo_1024.png?raw=true" alt="reVC logo" width="200">
[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2FGTAmodding%2Fre3%2Fbadge%3Fref%3Dmiami&style=flat)](https://actions-badge.atrox.dev/GTAmodding/re3/goto?ref=miami)
<a href="https://discord.gg/RFNbjsUMGg"><img src="https://img.shields.io/badge/discord-join-7289DA.svg?logo=discord&longCache=true&style=flat" /></a>

View file

@ -0,0 +1,38 @@
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()
set(CMAKE_EXECUTABLE_SUFFIX ".elf")
function(reVC_platform_target TARGET)
cmake_parse_arguments(RPT "INSTALL" "" "" ${ARGN})
get_target_property(TARGET_TYPE "${TARGET}" TYPE)
if(TARGET_TYPE STREQUAL "EXECUTABLE")
nx_generate_nacp(${TARGET}.nacp
NAME "${TARGET}"
AUTHOR "${${PROJECT}_AUTHOR}"
VERSION "1.0.0-${GIT_SHA1}"
)
nx_create_nro(${TARGET}
NACP ${TARGET}.nacp
ICON "${PROJECT_SOURCE_DIR}/res/images/logo_256.jpg"
)
if(${PROJECT}_INSTALL AND RPT_INSTALL)
get_target_property(TARGET_OUTPUT_NAME ${TARGET} OUTPUT_NAME)
if(NOT TARGET_OUTPUT_NAME)
set(TARGET_OUTPUT_NAME "${TARGET}")
endif()
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${TARGET_OUTPUT_NAME}.nro"
DESTINATION "."
)
endif()
endif()
endfunction()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View file

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

BIN
res/images/logo_256.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View file

@ -54,9 +54,13 @@ target_compile_definitions(${EXECUTABLE} PRIVATE USE_OUR_VERSIONING)
if(${PROJECT}_AUDIO STREQUAL "OAL")
find_package(OpenAL REQUIRED)
target_include_directories(${EXECUTABLE} PRIVATE ${OPENAL_INCLUDE_DIR})
target_link_libraries(${EXECUTABLE} PRIVATE ${OPENAL_LIBRARY})
target_compile_definitions(${EXECUTABLE} PRIVATE ${OPENAL_DEFINITIONS})
if(TARGET OpenAL::OpenAL)
target_link_libraries(${EXECUTABLE} PRIVATE OpenAL::OpenAL)
else()
target_include_directories(${EXECUTABLE} PRIVATE ${OPENAL_INCLUDE_DIR})
target_link_libraries(${EXECUTABLE} PRIVATE ${OPENAL_LIBRARY})
target_compile_definitions(${EXECUTABLE} PRIVATE ${OPENAL_DEFINITIONS})
endif()
target_compile_definitions(${EXECUTABLE} PRIVATE AUDIO_OAL)
elseif(${PROJECT}_AUDIO STREQUAL "MSS")
find_package(MilesSDK REQUIRED)
@ -120,13 +124,24 @@ 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()
if(NOT (WIN32 OR APPLE OR NINTENDO_SWITCH))
find_package(X11 REQUIRED)
target_link_libraries(${EXECUTABLE} PRIVATE X11::X11)
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 +155,5 @@ if(${PROJECT}_INSTALL)
install(FILES $<TARGET_PDB_FILE:${EXECUTABLE}> DESTINATION "." OPTIONAL)
endif()
endif()
reVC_platform_target(${EXECUTABLE} INSTALL)

View file

@ -2673,6 +2673,14 @@ const char *PlayStationButtons[][MAX_CONTROLLERACTIONS] =
#undef PS2_CROSS
#undef PS2_SQUARE
const char *NintendoSwitchButtons_noIcons[][MAX_CONTROLLERACTIONS] =
CONTROLLER_BUTTONS("Y", "A", "B", "X", "L", "ZL", "LS", "R", "ZR", "RS", "BACK", "right stick up", "right stick down", "right stick left", "right stick right");
#ifdef BUTTON_ICONS
const char *NintendoSwitchButtons[][MAX_CONTROLLERACTIONS] =
CONTROLLER_BUTTONS("~T~", "~O~", "~X~", "~Q~", "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "BACK", "~H~", "~L~", "~(~", "~)~");
#endif
#undef UP
#undef DOWN
#undef LEFT
@ -2698,6 +2706,9 @@ void CControllerConfigManager::GetWideStringOfCommandKeys(uint16 action, wchar *
case CMenuManager::CONTROLLER_DUALSHOCK4:
Buttons = CFont::ButtonsSlot != -1 ? PlayStationButtons : PlayStationButtons_noIcons;
break;
case CMenuManager::CONTROLLER_NINTENDO_SWITCH:
Buttons = CFont::ButtonsSlot != -1 ? NintendoSwitchButtons : NintendoSwitchButtons_noIcons;
break;
default:
#endif
Buttons = CFont::ButtonsSlot != -1 ? XboxButtons : XboxButtons_noIcons;
@ -2713,6 +2724,9 @@ void CControllerConfigManager::GetWideStringOfCommandKeys(uint16 action, wchar *
case CMenuManager::CONTROLLER_DUALSHOCK4:
Buttons = PlayStationButtons_noIcons;
break;
case CMenuManager::CONTROLLER_NINTENDO_SWITCH:
Buttons = NintendoSwitchButtons_noIcons;
break;
default:
Buttons = XboxButtons_noIcons;
break;

View file

@ -539,8 +539,12 @@ CMenuManager::CMenuManager()
#endif
#ifdef GAMEPAD_MENU
#ifdef __SWITCH__
m_PrefsControllerType = CONTROLLER_NINTENDO_SWITCH;
#else
m_PrefsControllerType = CONTROLLER_XBOXONE;
#endif
#endif
}
void
@ -566,7 +570,11 @@ CMenuManager::Initialise(void)
m_nCurrOption = 0;
m_nOptionHighlightTransitionBlend = 0;
CentreMousePointer();
#ifdef GTA_HANDHELD
m_bShowMouse = false;
#else
m_bShowMouse = true;
#endif
m_fMapSize = MENU_Y(162.0f); // Y because of HOR+
m_fMapCenterX = MENU_X_LEFT_ALIGNED(320.0f);
m_fMapCenterY = MENU_Y(225.0f);
@ -5872,6 +5880,7 @@ const char* controllerTypesPaths[] = {
"MODELS/FRONTEND_DS4.TXD",
"MODELS/FRONTEND_X360.TXD",
"MODELS/FRONTEND_XONE.TXD",
"MODELS/FRONTEND_NSW.TXD",
};
void
@ -5982,6 +5991,18 @@ CMenuManager::PrintController(void)
TEXT_L2R2_Y += 5.0f;
TEXT_SELECT_X += 3.0f;
break;
case CONTROLLER_NINTENDO_SWITCH:
TEXT_L1_Y += 5.0f;
TEXT_L1_Y_VEH = TEXT_L1_Y;
TEXT_R1_Y += 5.0f;
TEXT_TRIANGLE_Y += 3.0f;
TEXT_CIRCLE_Y += 3.0f;
TEXT_CROSS_Y += 3.0f;
TEXT_LSTICK_Y -= 23.0f;
TEXT_DPAD_Y += 25.0;
TEXT_RSTICK_Y += 1.0f;
TEXT_R3_Y += 1.0f;
break;
};
if (m_DisplayControllerOnFoot) {
@ -6278,6 +6299,7 @@ CMenuManager::PrintController(void)
{
case CONTROLLER_XBOXONE:
case CONTROLLER_XBOX360:
case CONTROLLER_NINTENDO_SWITCH:
CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));
switch (m_PrefsLanguage)
{
@ -6358,6 +6380,7 @@ CMenuManager::PrintController(void)
{
case CONTROLLER_XBOXONE:
case CONTROLLER_XBOX360:
case CONTROLLER_NINTENDO_SWITCH:
CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));
switch (m_PrefsLanguage)
{
@ -6441,6 +6464,7 @@ CMenuManager::PrintController(void)
{
case CONTROLLER_XBOXONE:
case CONTROLLER_XBOX360:
case CONTROLLER_NINTENDO_SWITCH:
CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));
switch (m_PrefsLanguage)
{
@ -6525,6 +6549,7 @@ CMenuManager::PrintController(void)
{
case CONTROLLER_XBOXONE:
case CONTROLLER_XBOX360:
case CONTROLLER_NINTENDO_SWITCH:
CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));
CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_SMT"));
break;
@ -6567,6 +6592,9 @@ CMenuManager::LoadController(int8 type)
case CONTROLLER_DUALSHOCK4:
CFont::LoadButtons("MODELS/PS3BTNS.TXD");
break;
case CONTROLLER_NINTENDO_SWITCH:
CFont::LoadButtons("MODELS/NSWBTNS.TXD");
break;
default:
CFont::LoadButtons("MODELS/X360BTNS.TXD");
break;

View file

@ -685,6 +685,7 @@ public:
CONTROLLER_DUALSHOCK4,
CONTROLLER_XBOX360,
CONTROLLER_XBOXONE,
CONTROLLER_NINTENDO_SWITCH,
};
int8 m_PrefsControllerType;

View file

@ -34,7 +34,7 @@
#ifdef CUSTOM_FRONTEND_OPTIONS
#ifdef IMPROVED_VIDEOMODE
#if defined(IMPROVED_VIDEOMODE) && !defined(GTA_HANDHELD)
#define VIDEOMODE_SELECTOR MENUACTION_CFO_SELECT, "FEM_SCF", { new CCFOSelect((int8*)&FrontEndMenuManager.m_nPrefsWindowed, "VideoMode", "Windowed", screenModes, 2, true, ScreenModeAfterChange, true) }, 0, 0, MENUALIGN_LEFT,
#else
#define VIDEOMODE_SELECTOR
@ -354,7 +354,7 @@ void DetectJoystickGoBack() {
#endif
#ifdef GAMEPAD_MENU
const char* controllerTypes[] = { "FEC_DS2", "FEC_DS3", "FEC_DS4", "FEC_360", "FEC_ONE" };
const char* controllerTypes[] = { "FEC_DS2", "FEC_DS3", "FEC_DS4", "FEC_360", "FEC_ONE", "FEC_NSW" };
void ControllerTypeAfterChange(int8 before, int8 after)
{
FrontEndMenuManager.LoadController(after);
@ -604,7 +604,11 @@ CMenuScreenCustom aScreens[] = {
// MENUPAGE_OPTIONS = 27
{ "FET_OPT", MENUPAGE_NONE, nil, nil,
#ifdef GTA_HANDHELD
MENUACTION_CHANGEMENU, "FEO_CON", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS}, 320, 132, MENUALIGN_CENTER,
#else
MENUACTION_CHANGEMENU, "FEO_CON", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC}, 320, 132, MENUALIGN_CENTER,
#endif
MENUACTION_LOADRADIO, "FEO_AUD", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 0, 0, MENUALIGN_CENTER,
MENUACTION_CHANGEMENU, "FEO_DIS", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_CENTER,
#ifdef GRAPHICS_MENU_OPTIONS
@ -660,7 +664,11 @@ CMenuScreenCustom aScreens[] = {
{ "", 0, nil, nil, },
#ifdef GAMEPAD_MENU
#ifdef GTA_HANDHELD
{ "FET_AGS", MENUPAGE_OPTIONS, new CCustomScreenLayout({40, 78, 25, true, true}), nil,
#else
{ "FET_AGS", MENUPAGE_CONTROLLER_PC, new CCustomScreenLayout({40, 78, 25, true, true}), nil,
#endif
MENUACTION_CTRLCONFIG, "FEC_CCF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, 40, 76, MENUALIGN_LEFT,
MENUACTION_CTRLDISPLAY, "FEC_CDP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, 0, 0, MENUALIGN_LEFT,
INVERT_PAD_SELECTOR
@ -726,7 +734,9 @@ CMenuScreenCustom aScreens[] = {
// MENUPAGE_GRAPHICS_SETTINGS
{ "FET_GFX", MENUPAGE_OPTIONS, new CCustomScreenLayout({40, 78, 25, true, true}), GraphicsGoBack,
#ifndef GTA_HANDHELD
MENUACTION_SCREENRES, "FED_RES", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, 0, 0, MENUALIGN_LEFT,
#endif
MENUACTION_WIDESCREEN, "FED_WIS", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, 0, 0, MENUALIGN_LEFT,
VIDEOMODE_SELECTOR
#ifdef LEGACY_MENU_OPTIONS

View file

@ -11,6 +11,11 @@
#define __STDC_LIMIT_MACROS // so we get UINT32_MAX etc
#endif
#ifdef __SWITCH__
#include <switch.h>
#endif
#include <stdint.h>
#include <string.h>
#include <math.h>

View file

@ -165,6 +165,11 @@ enum Config {
#define GTA_VERSION GTAVC_PC_11
// Enable configuration for handheld console ports
#if defined(__SWITCH__) || defined(PSP2)
#define GTA_HANDHELD
#endif
// TODO(MIAMI): someone ought to find and check out uses of these defines:
//#define GTA3_STEAM_PATCH
//#define GTAVC_JP_PATCH
@ -176,7 +181,9 @@ enum Config {
# define VU_COLLISION
# define PS2_MENU
#elif defined GTA_PC
# define PC_PLAYER_CONTROLS // mouse player/cam mode
# ifndef GTA_HANDHELD
# define PC_PLAYER_CONTROLS // mouse player/cam mode
# endif
# define GTA_REPLAY
# define GTA_SCENE_EDIT
# define PC_MENU
@ -325,7 +332,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_HANDHELD)
#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
@ -347,7 +354,7 @@ enum Config {
//# define PS2_MENU_USEALLPAGEICONS
#else
# define MAP_ENHANCEMENTS // Adding waypoint and better mouse support
# ifdef XINPUT
# if defined(XINPUT) || defined(GTA_HANDHELD)
# define GAMEPAD_MENU // Add gamepad menu
# endif
# define TRIANGLE_BACK_BUTTON
@ -456,4 +463,12 @@ static_assert(false, "SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually
#undef USE_CUTSCENE_SHADOW_FOR_PED
#endif
#ifdef GTA_HANDHELD
#define IGNORE_MOUSE_KEYBOARD // ignore mouse & keyboard input
#endif
#ifdef __SWITCH__
#define USE_UNNAMED_SEM // named semaphores are unsupported on the switch
#endif
#endif // VANILLA_DEFINES

View file

@ -45,9 +45,7 @@
#include "MBlur.h"
#include "ControllerConfig.h"
#ifdef DETECT_JOYSTICK_MENU
#include "crossplatform.h"
#endif
#ifndef _WIN32
#include "assert.h"

View file

@ -198,6 +198,20 @@ char* casepath(char const* path, bool checkPathFirst)
size_t rl = 0;
DIR* d;
char* c;
#if defined(__SWITCH__) || defined(PSP2)
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)
@ -293,3 +307,133 @@ char *_strdate(char *buf) {
return strdate(buf);
}
#endif
#ifdef __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

View file

@ -161,3 +161,28 @@ bool FindNextFile(HANDLE, WIN32_FIND_DATA*);
void FileTimeToSystemTime(time_t*, SYSTEMTIME*);
void GetDateFormat(int, int, SYSTEMTIME*, int, char*, int);
#endif
#ifdef __SWITCH__
// tweak glfw values for switch to match expected pc bindings
#ifdef GLFW_GAMEPAD_BUTTON_A
#undef GLFW_GAMEPAD_BUTTON_A
#endif
#define GLFW_GAMEPAD_BUTTON_A 1
#ifdef GLFW_GAMEPAD_BUTTON_B
#undef GLFW_GAMEPAD_BUTTON_B
#endif
#define GLFW_GAMEPAD_BUTTON_B 0
#ifdef GLFW_GAMEPAD_BUTTON_X
#undef GLFW_GAMEPAD_BUTTON_X
#endif
#define GLFW_GAMEPAD_BUTTON_X 3
#ifdef GLFW_GAMEPAD_BUTTON_Y
#undef GLFW_GAMEPAD_BUTTON_Y
#endif
#define GLFW_GAMEPAD_BUTTON_Y 2
#endif

View file

@ -821,7 +821,9 @@ PadHandler(RsEvent event, void *param)
RwBool
AttachInputDevices(void)
{
#ifndef IGNORE_MOUSE_KEYBOARD
RsInputDeviceAttach(rsKEYBOARD, KeyboardHandler);
#endif
RsInputDeviceAttach(rsPAD, PadHandler);

View file

@ -12,12 +12,14 @@ DWORD _dwOperatingSystemVersion;
#include "resource.h"
#else
long _dwOperatingSystemVersion;
#ifndef __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_HANDHELD // && !defined WAYLAND
#define GET_KEYBOARD_INPUT_FROM_X11
#endif
@ -328,6 +330,78 @@ psNativeTextureSupport(void)
#define CMDSTR LPSTR
#endif
/*
*****************************************************************************
*/
#ifdef __SWITCH__
static HidVibrationValue SwitchVibrationValues[2];
static HidVibrationDeviceHandle SwitchVibrationDeviceHandles[2][2];
static HidVibrationDeviceHandle SwitchVibrationDeviceGC;
static PadState SwitchPad;
static Result HidInitializationResult[2];
static Result HidInitializationGCResult;
static void _psInitializeVibration()
{
HidInitializationResult[0] = hidInitializeVibrationDevices(SwitchVibrationDeviceHandles[0], 2, HidNpadIdType_Handheld, HidNpadStyleTag_NpadHandheld);
if(R_FAILED(HidInitializationResult[0])) {
printf("Failed to initialize VibrationDevice for Handheld Mode\n");
}
HidInitializationResult[1] = hidInitializeVibrationDevices(SwitchVibrationDeviceHandles[1], 2, HidNpadIdType_No1, HidNpadStyleSet_NpadFullCtrl);
if(R_FAILED(HidInitializationResult[1])) {
printf("Failed to initialize VibrationDevice for Detached Mode\n");
}
HidInitializationGCResult = hidInitializeVibrationDevices(&SwitchVibrationDeviceGC, 1, HidNpadIdType_No1, HidNpadStyleTag_NpadGc);
if(R_FAILED(HidInitializationResult[1])) {
printf("Failed to initialize VibrationDevice for GC Mode\n");
}
SwitchVibrationValues[0].freq_low = 160.0f;
SwitchVibrationValues[0].freq_high = 320.0f;
padConfigureInput(1, HidNpadStyleSet_NpadFullCtrl);
padInitializeDefault(&SwitchPad);
}
static void _psHandleVibration()
{
padUpdate(&SwitchPad);
uint8 target_device = padIsHandheld(&SwitchPad) ? 0 : 1;
if(R_SUCCEEDED(HidInitializationResult[target_device])) {
CPad* pad = CPad::GetPad(0);
// value conversion based on SDL2 switch port
SwitchVibrationValues[0].amp_high = SwitchVibrationValues[0].amp_low = pad->ShakeFreq == 0 ? 0.0f : 320.0f;
SwitchVibrationValues[0].freq_low = pad->ShakeFreq == 0.0 ? 160.0f : (float)pad->ShakeFreq * 1.26f;
SwitchVibrationValues[0].freq_high = pad->ShakeFreq == 0.0 ? 320.0f : (float)pad->ShakeFreq * 1.26f;
if (pad->ShakeDur < CTimer::GetTimeStepInMilliseconds())
pad->ShakeDur = 0;
else
pad->ShakeDur -= CTimer::GetTimeStepInMilliseconds();
if (pad->ShakeDur == 0) pad->ShakeFreq = 0;
if(target_device == 1 && R_SUCCEEDED(HidInitializationGCResult)) {
// gamecube rumble
hidSendVibrationGcErmCommand(SwitchVibrationDeviceGC, pad->ShakeFreq > 0 ? HidVibrationGcErmCommand_Start : HidVibrationGcErmCommand_Stop);
}
memcpy(&SwitchVibrationValues[1], &SwitchVibrationValues[0], sizeof(HidVibrationValue));
hidSendVibrationValues(SwitchVibrationDeviceHandles[target_device], SwitchVibrationValues, 2);
}
}
#else
static void _psInitializeVibration() {}
static void _psHandleVibration() {}
#endif
/*
*****************************************************************************
*/
@ -407,6 +481,8 @@ psInitialize(void)
InitialiseLanguage();
#endif
_psInitializeVibration();
gGameState = GS_START_UP;
TRACE("gGameState = GS_START_UP");
@ -480,6 +556,9 @@ psInitialize(void)
_dwMemAvailPhys = (uint64_t)(vm_stat.free_count * page_size);
debug("Physical memory size %llu\n", _dwMemAvailPhys);
debug("Available physical memory %llu\n", size);
#elif defined (__SWITCH__)
svcGetInfo(&_dwMemAvailPhys, InfoType_UsedMemorySize, CUR_PROCESS_HANDLE, 0);
debug("Physical memory size %llu\n", _dwMemAvailPhys);
#else
#ifndef __APPLE__
struct sysinfo systemInfo;
@ -982,13 +1061,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);
@ -1824,7 +1905,7 @@ main(int argc, char *argv[])
InitMemoryMgr();
#endif
#ifndef _WIN32
#if !defined(_WIN32) && !defined(__SWITCH__)
struct sigaction act;
act.sa_sigaction = terminateHandler;
act.sa_flags = SA_SIGINFO;
@ -2486,7 +2567,9 @@ void CapturePad(RwInt32 padID)
if ( Abs(rightStickPos.y) > 0.3f )
pad->PCTempJoyState.RightStickY = (int32)(rightStickPos.y * 128.0f);
}
_psHandleVibration();
return;
}

View file

@ -14414,6 +14414,9 @@ XBOX 360 CONTROLLER
[FEC_ONE]
XBOX ONE CONTROLLER
[FEC_NSW]
NINTENDO SWITCH CONTROLLER
[FEC_TYP]
GAMEPAD TYPE

View file

@ -14703,6 +14703,9 @@ XBOX 360 CONTROLLER
[FEC_ONE]
XBOX ONE CONTROLLER
[FEC_NSW]
NINTENDO SWITCH CONTROLLER
[FEC_TYP]
GAMEPAD TYPE

View file

@ -14703,6 +14703,9 @@ XBOX 360 CONTROLLER
[FEC_ONE]
XBOX ONE CONTROLLER
[FEC_NSW]
NINTENDO SWITCH CONTROLLER
[FEC_TYP]
GAMEPAD-TYP

View file

@ -14712,6 +14712,9 @@ XBOX 360 CONTROLLER
[FEC_ONE]
XBOX ONE CONTROLLER
[FEC_NSW]
NINTENDO SWITCH CONTROLLER
[FEC_TYP]
GAMEPAD TYPE

View file

@ -14398,6 +14398,9 @@ MANDO DE XBOX 360
[FEC_ONE]
MANDO DE XBOX ONE
[FEC_NSW]
MANDO DE NINTENDO SWITCH
[FEC_TYP]
TIPO DE MANDO