switch: make it work again

with dynamic libs this time
This commit is contained in:
fgsfds 2021-05-22 06:25:20 +03:00 committed by Alibek Omarov
parent 654bac83a5
commit d4bf5e104e
15 changed files with 251 additions and 10 deletions

View File

@ -39,7 +39,12 @@ GNU General Public License for more details.
#if XASH_POSIX
#include <unistd.h>
#include <dlfcn.h>
#ifdef XASH_NSWITCH
#define SOLDER_LIBDL_COMPAT
#include <solder.h>
#else
#include <dlfcn.h>
#endif
#define PATH_SPLITTER "/"
#define HAVE_DUP

View File

@ -95,6 +95,8 @@ const char *Q_buildos( void )
osname = "DOS4GW";
#elif XASH_HAIKU
osname = "haiku";
#elif XASH_NSWITCH
osname = "nswitch";
#else
#error "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug"
#endif

View File

@ -990,6 +990,10 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
#if TARGET_OS_IOS
const char *IOS_GetDocsDir();
Q_strncpy( host.rootdir, IOS_GetDocsDir(), sizeof(host.rootdir) );
#elif XASH_NSWITCH
// we can't NOT be in the same directory as the NRO
host.rootdir[0] = '.';
host.rootdir[1] = '\0';
#elif XASH_SDL == 2
char *szBasePath;

View File

@ -21,6 +21,9 @@ GNU General Public License for more details.
#if defined(XASH_NO_NETWORK)
#include "platform/stub/net_stub.h"
#elif XASH_NSWITCH
// our ntohl is here
#include <arpa/inet.h>
#elif !XASH_WIN32
#include <netinet/in.h>
#endif

View File

@ -25,7 +25,12 @@ GNU General Public License for more details.
#if XASH_POSIX
#include <unistd.h>
#include <signal.h>
#if XASH_NSWITCH
#define SOLDER_LIBDL_COMPAT
#include <solder.h>
#else
#include <dlfcn.h>
#endif
#if !XASH_ANDROID
#include <pwd.h>
@ -126,7 +131,7 @@ const char *Sys_GetCurrentUser( void )
if( GetUserName( s_userName, &size ))
return s_userName;
#elif XASH_POSIX && !XASH_ANDROID
#elif XASH_POSIX && !XASH_ANDROID && !XASH_NSWITCH
uid_t uid = geteuid();
struct passwd *pw = getpwuid( uid );
@ -405,6 +410,9 @@ void Sys_Error( const char *error, ... )
{
va_list argptr;
char text[MAX_PRINT_MSG];
#if XASH_NSWITCH
FILE *fout;
#endif
DEBUG_BREAK;
@ -429,6 +437,16 @@ void Sys_Error( const char *error, ... )
#endif
}
#if XASH_NSWITCH
fprintf( stderr, "Fatal error: %s\n", text );
fout = fopen( "fatal.log", "w" );
if (fout)
{
fprintf( fout, "Fatal error: %s\n", text );
fclose( fout );
}
#endif
if( host_developer.value )
{
#if XASH_WIN32

View File

@ -0,0 +1,61 @@
/*
switch.c - switch backend
Copyright (C) 2021 fgsfds
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "platform/platform.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <switch.h>
#include <solder.h>
static int nxlink_sock = -1;
// HACKHACK: force these lads to link in
const solder_export_t solder_extra_exports[] =
{
SOLDER_EXPORT_SYMBOL(vsprintf),
SOLDER_EXPORT_SYMBOL(isalpha),
SOLDER_EXPORT_SYMBOL(isalnum),
SOLDER_EXPORT_SYMBOL(tolower),
SOLDER_EXPORT_SYMBOL(toupper),
};
void Platform_ShellExecute( const char *path, const char *parms )
{
Con_Reportf( S_WARN "Tried to shell execute `%s` -- not supported\n", path );
}
void NSwitch_Init( void )
{
socketInitializeDefault();
nxlink_sock = nxlinkStdio();
if ( solder_init(0) < 0 )
{
fprintf( stderr, "solder_init() failed: %s\n", solder_dlerror() );
fflush( stderr );
exit(1);
}
printf("NSwitch_Init\n");
}
void NSwitch_Shutdown( void )
{
printf("NSwitch_Shutdown\n");
solder_quit();
if (nxlink_sock >= 0)
close(nxlink_sock);
socketExit();
}

View File

@ -45,6 +45,11 @@ const char *Android_LoadID( void );
void Android_SaveID( const char *id );
#endif
#if XASH_NSWITCH
void NSwitch_Init( void );
void NSwitch_Shutdown( void );
#endif
/*
==============================================================================

View File

@ -67,7 +67,7 @@ static qboolean Sys_FindExecutable( const char *baseName, char *buf, size_t size
return false;
}
#if !XASH_ANDROID
#if !XASH_ANDROID && !XASH_NSWITCH
void Platform_ShellExecute( const char *path, const char *parms )
{
char xdgOpen[128];
@ -145,7 +145,7 @@ void Posix_Daemonize( void )
}
#if !XASH_SDL && !XASH_ANDROID
#if !XASH_SDL && !XASH_ANDROID && !XASH_NSWITCH
void Platform_Init( void )
{

View File

@ -61,12 +61,15 @@ void Platform_Init( void )
SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
SDL_StopTextInput();
#endif // XASH_SDL == 2
#if XASH_POSIX
#if XASH_POSIX && !XASH_NSWITCH
Posix_Daemonize();
#endif
#ifdef XASH_WIN32
Wcon_CreateConsole(); // system console used by dedicated server or show fatal errors
#endif
#ifdef XASH_NSWITCH
NSwitch_Init();
#endif
}
void Platform_Shutdown( void )
@ -74,4 +77,7 @@ void Platform_Shutdown( void )
#ifdef XASH_WIN32
Wcon_DestroyConsole();
#endif
#ifdef XASH_NSWITCH
NSwitch_Shutdown();
#endif
}

View File

@ -3071,7 +3071,7 @@ void SV_SetStringArrayMode( qboolean dynamic )
}
#ifdef XASH_64BIT
#if !XASH_WIN32
#if !XASH_WIN32 && !XASH_NSWITCH
#define USE_MMAP
#include <sys/mman.h>
#endif

View File

@ -51,6 +51,19 @@ def configure(conf):
elif conf.env.DEST_OS == 'android': # Android doesn't need SDL2
for i in ['log']:
conf.check_cc(lib = i)
if conf.env.DEST_OS == 'nswitch':
# our pkg-config script for SDL2 tactically forgets to add -lstdc++ to LDFLAGS
conf.options.SDL2_SANITY_CHECK = False
conf.load('sdl2')
if not conf.env.HAVE_SDL2:
conf.fatal('SDL2 not availiable! Install switch-sdl2!')
conf.define('XASH_SDL', 2)
# find our dynamic linker
# conf.check_cfg(package='solder', args='--cflags --libs', uselib_store='SOLDER')
conf.env.append_unique('LDFLAGS', '-lsolderd')
# disallow undefined symbols
conf.env.append_unique('CXXFLAGS', '-Wl,--no-undefined')
conf.env.append_unique('CFLAGS', '-Wl,--no-undefined')
elif conf.options.FBDEV_SW:
# unused, XASH_LINUX without XASH_SDL gives fbdev & alsa support
# conf.define('XASH_FBDEV', 1)
@ -159,6 +172,11 @@ def build(bld):
libs += ['LOG']
source += bld.path.ant_glob(['platform/android/*.cpp', 'platform/android/*.c', 'platform/linux/*.c'])
if bld.env.DEST_OS == 'nswitch':
libs += ['SOLDER']
source += bld.path.ant_glob(['platform/nswitch/*.c'])
is_cxx_link = True # switch-mesa requires libstdc++
# add client files
if not bld.env.DEDICATED:
source += bld.path.ant_glob([

View File

@ -20,7 +20,7 @@ GNU General Public License for more details.
#include <stdlib.h>
#include <stdarg.h>
#if defined(__APPLE__) || defined(__unix__) || defined(__HAIKU__)
#if defined(__APPLE__) || defined(__unix__) || defined(__HAIKU__) || defined(__SWITCH__)
#define XASHLIB "libxash." OS_LIB_EXT
#elif _WIN32
#if !__MINGW32__ && _MSC_VER >= 1200

View File

@ -77,6 +77,7 @@ For more information, please refer to <http://unlicense.org/>
#undef XASH_WIN32
#undef XASH_WIN64
#undef XASH_X86
#undef XASH_NSWITCH
//================================================================
//
@ -124,12 +125,16 @@ For more information, please refer to <http://unlicense.org/>
#define XASH_LITTLE_ENDIAN 1
#elif defined __HAIKU__
#define XASH_HAIKU 1
#define XASH_LITTLE_ENDIAN
#elif defined __SWITCH__
#define XASH_NSWITCH 1
#define XASH_LITTLE_ENDIAN
#define XASH_POSIX 1
#else
#error "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug"
#endif
#if defined XASH_ANDROID || defined XASH_IOS
#if defined XASH_ANDROID || defined XASH_IOS || defined XASH_NSWITCH
#define XASH_MOBILE_PLATFORM 1
#endif

View File

@ -30,6 +30,8 @@ ANDROID_NDK_API_MIN = { 10: 3, 19: 16, 20: 16, 23: 16 } # minimal API level ndk
ANDROID_STPCPY_API_MIN = 21 # stpcpy() introduced in SDK 21
ANDROID_64BIT_API_MIN = 21 # minimal API level that supports 64-bit targets
NSWITCH_ENVVARS = ['DEVKITPRO']
# This class does support ONLY r10e and r19c/r20 NDK
class Android:
ctx = None # waf context
@ -348,6 +350,83 @@ class Android:
ldflags += ['-march=armv5te']
return ldflags
class NintendoSwitch:
ctx = None # waf context
arch = "aarch64"
dkp_dir = None
portlibs_dir = None
dka64_dir = None
libnx_dir = None
def __init__(self, ctx):
self.ctx = ctx
for i in NSWITCH_ENVVARS:
self.dkp_dir = os.getenv(i)
if self.dkp_dir != None:
break
else:
ctx.fatal('Set %s environment variable pointing to the DEVKITPRO home!' %
' or '.join(ANDROID_NDK_ENVVARS))
self.dkp_dir = os.path.abspath(self.dkp_dir)
self.dka64_dir = os.path.join(self.dkp_dir, 'devkitA64')
if not os.path.exists(self.dka64_dir):
ctx.fatal('devkitA64 not found in `%s`. Install devkitA64!' % self.dka64_dir)
self.libnx_dir = os.path.join(self.dkp_dir, 'libnx')
if not os.path.exists(self.libnx_dir):
ctx.fatal('libnx not found in `%s`. Install libnx!' % self.libnx_dir)
self.portlibs_dir = os.path.join(self.dkp_dir, 'portlibs', 'switch')
if not os.path.exists(self.portlibs_dir):
ctx.fatal('No Switch libraries found in `%s`!' % self.portlibs_dir)
def cc(self):
return 'aarch64-none-elf-gcc'
def cxx(self):
return 'aarch64-none-elf-g++'
def strip(self):
return 'aarch64-none-elf-strip'
def pkgconfig(self):
return 'aarch64-none-elf-pkg-config'
def cflags(self, cxx = False):
cflags = []
# arch flags
cflags += ['-D__SWITCH__', '-march=armv8-a+crc+crypto', '-mtune=cortex-a57', '-mtp=soft', '-ftls-model=local-exec', '-fPIE']
# help the linker out
cflags += ['-ffunction-sections', '-fdata-sections']
# base include dirs
cflags += ['-isystem "%s/include"' % self.libnx_dir, '-I"%s/include"' % self.portlibs_dir]
if cxx:
# while these are supported, they could fuck up my crappy dynamic linker
cflags += ['-fno-exceptions', '-fno-rtti']
# the game wants GNU extensions
cflags += ['-std=gnu++17', '-D_GNU_SOURCE']
else:
cflags += ['-std=gnu11', '-D_GNU_SOURCE']
# we know we have neon
cflags += ['-DHAVE_EFFICIENT_UNALIGNED_ACCESS', '-DVECTORIZE_SINCOS']
return cflags
# they go before object list
def linkflags(self):
linkflags = ['-fPIE', '-specs=%s/switch.specs' % self.libnx_dir]
# libsolder only supports sysv hashes and we need to build everything with -rdynamoc
linkflags += ['-rdynamic']
# avoid pulling in and exposing mesa's internals, that crashes it for some god forsaken reason
linkflags += ['-Wl,--exclude-libs=libglapi.a', '-Wl,--exclude-libs=libdrm_nouveau.a']
return linkflags
def ldflags(self):
ldflags = []
return ldflags
def options(opt):
android = opt.add_option_group('Android options')
android.add_option('--android', action='store', dest='ANDROID_OPTS', default=None,
@ -357,6 +436,10 @@ def options(opt):
magx.add_option('--enable-magx', action = 'store_true', dest = 'MAGX', default = False,
help = 'enable targetting for MotoMAGX phones [default: %default]')
switch = opt.add_option_group('Nintendo Switch options')
switch.add_option('--nswitch', action='store_true', dest='NSWITCH', default = False,
help ='enable building for Nintendo Switch [default: %default]')
def configure(conf):
if conf.options.ANDROID_OPTS:
values = conf.options.ANDROID_OPTS.split(',')
@ -399,8 +482,25 @@ def configure(conf):
conf.env.LIBPATH_MAGX = [toolchain_path + i for i in ['ezx-z6/lib', 'qt-2.3.8/lib']]
conf.env.LINKFLAGS_MAGX = ['-Wl,-rpath-link=' + i for i in conf.env.LIBPATH_MAGX]
for lib in ['qte-mt', 'ezxappbase', 'ezxpm', 'log_util']:
conf.check_cc(lib=lib, use='MAGX', uselib_store='MAGX')
elif conf.options.NSWITCH:
conf.nswitch = nswitch = NintendoSwitch(conf)
conf.environ['CC'] = nswitch.cc()
conf.environ['CXX'] = nswitch.cxx()
conf.environ['STRIP'] = nswitch.strip()
conf.env.PKGCONFIG = nswitch.pkgconfig()
conf.env.CFLAGS += nswitch.cflags()
conf.env.CXXFLAGS += nswitch.cflags(True)
conf.env.LINKFLAGS += nswitch.linkflags()
conf.env.LDFLAGS += nswitch.ldflags()
conf.env.HAVE_M = True
conf.env.LIB_M = ['m']
conf.env.PREFIX = ''
conf.env.DEST_OS = 'nswitch'
conf.env.MAGX = conf.options.MAGX
MACRO_TO_DESTOS = OrderedDict({ '__ANDROID__' : 'android' })
MACRO_TO_DESTOS = OrderedDict({ '__ANDROID__' : 'android', '__SWITCH__' : 'nswitch' })
for k in c_config.MACRO_TO_DESTOS:
MACRO_TO_DESTOS[k] = c_config.MACRO_TO_DESTOS[k] # ordering is important
c_config.MACRO_TO_DESTOS = MACRO_TO_DESTOS

16
wscript
View File

@ -155,6 +155,12 @@ def configure(conf):
conf.options.NANOGL = True
conf.options.GLWES = True
conf.options.GL = False
elif conf.env.DEST_OS == 'nswitch':
conf.options.NO_VGUI = True
conf.options.GL = True
conf.options.SINGLE_BINARY = True
conf.options.NO_ASYNC_RESOLVE = True
conf.options.USE_STBTT = True
elif conf.env.MAGX:
conf.options.USE_SELECT = True
conf.options.SDL12 = True
@ -227,6 +233,14 @@ def configure(conf):
cflags, linkflags = conf.get_optimization_flags()
# on the Switch, allow undefined symbols by default, which is needed for libsolder to work
# we'll specifically disallow for the engine executable
# additionally, shared libs are linked without libc
if conf.env.DEST_OS == 'nswitch':
linkflags.remove('-Wl,--no-undefined')
conf.env.append_unique('LINKFLAGS_cshlib', ['-nostdlib', '-nostartfiles'])
conf.env.append_unique('LINKFLAGS_cxxshlib', ['-nostdlib', '-nostartfiles'])
# And here C++ flags starts to be treated separately
cxxflags = list(cflags)
if conf.env.COMPILER_CC != 'msvc' and not conf.options.DISABLE_WERROR:
@ -322,7 +336,7 @@ def configure(conf):
conf.env.LIBDIR = conf.env.BINDIR = '${PREFIX}/lib/xash3d'
conf.env.SHAREDIR = '${PREFIX}/share/xash3d'
else:
if sys.platform != 'win32' and not conf.env.DEST_OS == 'android':
if sys.platform != 'win32' and conf.env.DEST_OS not in ['android', 'nswitch']:
conf.env.PREFIX = '/'
conf.env.SHAREDIR = conf.env.LIBDIR = conf.env.BINDIR = conf.env.PREFIX