mirror of
https://github.com/halpz/re3.git
synced 2025-07-23 15:59:45 +00:00
Nintendo Switch support
This commit is contained in:
@ -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
|
||||
|
@ -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
|
||||
|
@ -821,7 +821,9 @@ PadHandler(RsEvent event, void *param)
|
||||
RwBool
|
||||
AttachInputDevices(void)
|
||||
{
|
||||
#ifndef IGNORE_MOUSE_KEYBOARD
|
||||
RsInputDeviceAttach(rsKEYBOARD, KeyboardHandler);
|
||||
#endif
|
||||
|
||||
RsInputDeviceAttach(rsPAD, PadHandler);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user