From 25a1cb8ce725286575d60fbe64193f882c22db71 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 5 Feb 2023 02:09:32 +0100 Subject: [PATCH] Nintendo Switch support (again) --- common/backends.h | 1 + common/defaults.h | 11 +- common/port.h | 9 +- engine/common/host.c | 2 +- engine/common/imagelib/img_png.c | 3 + engine/common/sys_con.c | 5 + engine/common/system.c | 21 +++- engine/common/whereami.c | 2 +- engine/platform/nswitch/icon.jpg | Bin 0 -> 7846 bytes engine/platform/nswitch/sys_nswitch.c | 140 +++++++++++++++++++++ engine/platform/nswitch/xash3d-fwgs.nacp | Bin 0 -> 16384 bytes engine/platform/platform.h | 5 + engine/platform/posix/lib_posix.c | 1 - engine/platform/posix/sys_posix.c | 2 +- engine/platform/sdl/sys_sdl.c | 6 + engine/server/sv_game.c | 2 +- engine/wscript | 63 +++++++--- public/build.c | 2 + public/build.h | 5 +- public/buildenums.h | 3 + scripts/waifulib/compiler_optimizations.py | 4 + scripts/waifulib/nswitch.py | 64 ++++++++++ scripts/waifulib/xcompile.py | 100 ++++++++++++++- wscript | 24 +++- 24 files changed, 442 insertions(+), 33 deletions(-) create mode 100644 engine/platform/nswitch/icon.jpg create mode 100644 engine/platform/nswitch/sys_nswitch.c create mode 100644 engine/platform/nswitch/xash3d-fwgs.nacp create mode 100644 scripts/waifulib/nswitch.py diff --git a/common/backends.h b/common/backends.h index be3cdaa6..77bcced8 100644 --- a/common/backends.h +++ b/common/backends.h @@ -47,6 +47,7 @@ GNU General Public License for more details. #define MSGBOX_SDL 1 #define MSGBOX_ANDROID 2 #define MSGBOX_WIN32 3 +#define MSGBOX_NSWITCH 4 // library loading (XASH_LIB) diff --git a/common/defaults.h b/common/defaults.h index e992ef4d..2144b3be 100644 --- a/common/defaults.h +++ b/common/defaults.h @@ -47,7 +47,9 @@ SETUP BACKENDS DEFINITIONS #endif // XASH_TIMER #ifndef XASH_MESSAGEBOX - #define XASH_MESSAGEBOX MSGBOX_SDL + #if !XASH_NSWITCH // SDL2 messageboxes not available + #define XASH_MESSAGEBOX MSGBOX_SDL + #endif #endif // XASH_MESSAGEBOX #endif #elif XASH_ANDROID @@ -105,6 +107,8 @@ SETUP BACKENDS DEFINITIONS #ifndef XASH_MESSAGEBOX #if XASH_WIN32 #define XASH_MESSAGEBOX MSGBOX_WIN32 + #elif XASH_NSWITCH + #define XASH_MESSAGEBOX MSGBOX_NSWITCH #else // !XASH_WIN32 #define XASH_MESSAGEBOX MSGBOX_STDERR #endif // !XASH_WIN32 @@ -177,4 +181,9 @@ Default build-depended cvar and constant values #define DEFAULT_FULLSCREEN 1 #endif // DEFAULT_FULLSCREEN +#if XASH_NSWITCH + #define DEFAULT_MODE_WIDTH 1280 + #define DEFAULT_MODE_HEIGHT 720 +#endif // XASH_NSWITCH + #endif // DEFAULTS_H diff --git a/common/port.h b/common/port.h index 05a732da..bf55e171 100644 --- a/common/port.h +++ b/common/port.h @@ -39,8 +39,13 @@ GNU General Public License for more details. #if XASH_POSIX #include - #include - #define HAVE_DUP + #ifdef XASH_NSWITCH + #define SOLDER_LIBDL_COMPAT + #include + #else + #include + #define HAVE_DUP + #endif #define O_BINARY 0 #define O_TEXT 0 #define _mkdir( x ) mkdir( x, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ) diff --git a/engine/common/host.c b/engine/common/host.c index c0515eae..e558b285 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -1013,7 +1013,7 @@ 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_SDL == 2 +#elif (XASH_SDL == 2) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2 char *szBasePath; if( !( szBasePath = SDL_GetBasePath() ) ) diff --git a/engine/common/imagelib/img_png.c b/engine/common/imagelib/img_png.c index 8056ac7c..2a4c742d 100644 --- a/engine/common/imagelib/img_png.c +++ b/engine/common/imagelib/img_png.c @@ -20,6 +20,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 #elif !XASH_WIN32 #include #endif diff --git a/engine/common/sys_con.c b/engine/common/sys_con.c index b0a241a6..6a0c3dd2 100644 --- a/engine/common/sys_con.c +++ b/engine/common/sys_con.c @@ -264,6 +264,11 @@ static void Sys_PrintStdout( const char *logtime, const char *msg ) void IOS_Log( const char * ); IOS_Log( buf ); #endif // TARGET_OS_IOS + +#if XASH_NSWITCH && NSWITCH_DEBUG + // just spew it to stderr normally in debug mode + fprintf( stderr, "%s %s", logtime, buf ); +#endif // XASH_NSWITCH && NSWITCH_DEBUG #elif !XASH_WIN32 // Wcon does the job Sys_PrintLogfile( STDOUT_FILENO, logtime, msg, XASH_COLORIZE_CONSOLE ); Sys_FlushStdout(); diff --git a/engine/common/system.c b/engine/common/system.c index 6df8ffe6..d7d08165 100644 --- a/engine/common/system.c +++ b/engine/common/system.c @@ -26,7 +26,6 @@ GNU General Public License for more details. #if XASH_POSIX #include #include -#include #if !XASH_ANDROID #include @@ -37,6 +36,10 @@ GNU General Public License for more details. #include #endif +#if XASH_NSWITCH +#include +#endif + #include "menu_int.h" // _UPDATE_PAGE macro #include "library.h" @@ -126,7 +129,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 ); @@ -566,6 +569,19 @@ it explicitly doesn't use internal allocation or string copy utils */ qboolean Sys_NewInstance( const char *gamedir ) { +#if XASH_NSWITCH + char newargs[4096]; + const char *exe = host.argv[0]; // arg 0 is always the full NRO path + + // TODO: carry over the old args (assuming you can even pass any) + Q_snprintf( newargs, sizeof( newargs ), "%s -game %s", exe, gamedir ); + // just restart the entire thing + printf( "envSetNextLoad exe: `%s`\n", exe ); + printf( "envSetNextLoad argv:\n`%s`\n", newargs ); + Host_Shutdown( ); + envSetNextLoad( exe, newargs ); + exit( 0 ); +#else int i = 0; qboolean replacedArg = false; size_t exelen; @@ -613,6 +629,7 @@ qboolean Sys_NewInstance( const char *gamedir ) free( newargs[i] ); free( newargs ); free( exe ); +#endif return false; } diff --git a/engine/common/whereami.c b/engine/common/whereami.c index e7958363..0a0fb570 100644 --- a/engine/common/whereami.c +++ b/engine/common/whereami.c @@ -795,7 +795,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) return length; } -#elif defined(__sgi) +#elif defined(__sgi) || defined(__SWITCH__) /* * These functions are stubbed for now to get the code compiling. diff --git a/engine/platform/nswitch/icon.jpg b/engine/platform/nswitch/icon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3bb62ec231e41f118705343c492fb1355859bc85 GIT binary patch literal 7846 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 literal 0 HcmV?d00001 diff --git a/engine/platform/nswitch/sys_nswitch.c b/engine/platform/nswitch/sys_nswitch.c new file mode 100644 index 00000000..8165f211 --- /dev/null +++ b/engine/platform/nswitch/sys_nswitch.c @@ -0,0 +1,140 @@ +/* +switch.c - switch backend +Copyright (C) 2021-2023 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 +#include +#include +#include +#include +#include +#include +#include +#include + +static int nxlink_sock = -1; + +/* HACKHACK: force-export stuff required by the dynamic libs */ + +// libunwind stuff for C++ exceptions, required by filesystem_stdio +extern void *_Unwind_GetIPInfo; +extern void *_Unwind_Resume_or_Rethrow; +extern void *_Unwind_GetRegionStart; +extern void *_Unwind_Resume; +extern void *_Unwind_DeleteException; +extern void *_Unwind_RaiseException; +extern void *_Unwind_SetIP; +extern void *_Unwind_GetTextRelBase; +extern void *_Unwind_GetLanguageSpecificData; +extern void *_Unwind_SetGR; +extern void *_Unwind_GetDataRelBase; + +// these are macros in our libc, so we need to wrap them +static int tolower_fn(int c) { return tolower(c); } +static int toupper_fn(int c) { return toupper(c); } +static int isalnum_fn(int c) { return isalnum(c); } +static int isalpha_fn(int c) { return isalpha(c); } + +static const solder_export_t aux_exports[] = +{ + SOLDER_EXPORT("tolower", tolower_fn), + SOLDER_EXPORT("toupper", toupper_fn), + SOLDER_EXPORT("isalnum", isalnum_fn), + SOLDER_EXPORT("isalpha", isalpha_fn), + SOLDER_EXPORT_SYMBOL(mkdir), + SOLDER_EXPORT_SYMBOL(remove), + SOLDER_EXPORT_SYMBOL(rename), + SOLDER_EXPORT_SYMBOL(fsync), + SOLDER_EXPORT_SYMBOL(strchrnul), + SOLDER_EXPORT_SYMBOL(stpcpy), + SOLDER_EXPORT_SYMBOL(_Unwind_GetIPInfo), + SOLDER_EXPORT_SYMBOL(_Unwind_Resume_or_Rethrow), + SOLDER_EXPORT_SYMBOL(_Unwind_GetRegionStart), + SOLDER_EXPORT_SYMBOL(_Unwind_Resume), + SOLDER_EXPORT_SYMBOL(_Unwind_DeleteException), + SOLDER_EXPORT_SYMBOL(_Unwind_RaiseException), + SOLDER_EXPORT_SYMBOL(_Unwind_SetIP), + SOLDER_EXPORT_SYMBOL(_Unwind_GetTextRelBase), + SOLDER_EXPORT_SYMBOL(_Unwind_GetLanguageSpecificData), + SOLDER_EXPORT_SYMBOL(_Unwind_SetGR), + SOLDER_EXPORT_SYMBOL(_Unwind_GetDataRelBase), +}; + +const solder_export_t *__solder_aux_exports = aux_exports; +const size_t __solder_num_aux_exports = sizeof(aux_exports) / sizeof(*aux_exports); + +/* end of export crap */ + +void Platform_ShellExecute( const char *path, const char *parms ) +{ + Con_Reportf( S_WARN "Tried to shell execute ;%s; -- not supported\n", path ); +} + +#if XASH_MESSAGEBOX == MSGBOX_NSWITCH +void Platform_MessageBox( const char *title, const char *message, qboolean unused ) +{ + // TODO: maybe figure out how to show an actual messagebox or an on-screen console + // without murdering the renderer + // assume this is a fatal error + FILE *f = fopen( "fatal.log", "w" ); + if ( f ) + { + fprintf( f, "%s:\n%s\n", title, message ); + fclose( f ); + } + // dump to nxlink as well + fprintf( stderr, "%s:\n%s\n", title, message ); +} +#endif // XASH_MESSAGEBOX == MSGBOX_NSWITCH + +// this gets executed before main(), do not delete +void userAppInit( void ) +{ + socketInitializeDefault( ); +#ifdef NSWITCH_DEBUG + nxlink_sock = nxlinkStdio( ); +#endif + if ( solder_init( 0 ) < 0 ) + { + fprintf( stderr, "solder_init() failed: %s\n", solder_dlerror() ); + fflush( stderr ); + exit( 1 ); + } +} + +// this gets executed on exit(), do not delete +void userAppExit( void ) +{ + solder_quit( ); + if ( nxlink_sock >= 0 ) + { + close( nxlink_sock ); + nxlink_sock = -1; + } + socketExit( ); +} + +void NSwitch_Init( void ) +{ + printf( "NSwitch_Init\n" ); +} + +void NSwitch_Shutdown( void ) +{ + printf( "NSwitch_Shutdown\n" ); + // force deinit everything SDL-related to avoid issues with changing games + if ( SDL_WasInit( 0 ) ) + SDL_Quit( ); +} diff --git a/engine/platform/nswitch/xash3d-fwgs.nacp b/engine/platform/nswitch/xash3d-fwgs.nacp new file mode 100644 index 0000000000000000000000000000000000000000..7f8c9c53e02eb0fdbd46b5f7b34c51c45b978e40 GIT binary patch literal 16384 zcmeIyI|{-;6op|QohH5ItU!EhL6QYnByB1a5SwV>ZnKk7i9rseOd*_q8o46|@9&3Y z)z-&T$cp?tB$G?j3 zn(&W*FY&r9{_(FOye9nP-%Gr1i+}v92(JnM`1ca8+u|SpD#B~RKmNVM>$dLxwFVOf zC_n)UP=Epypa2CZU|(R~7l`Yj#P{MoCNZvJ@;PZ5N6v10*bko?f9;n2{bu~_iEkIb fuRigUc^m~OKmiI+fC3bt00k&O0SZvye+#?-u-uLr literal 0 HcmV?d00001 diff --git a/engine/platform/platform.h b/engine/platform/platform.h index 0aaee2b5..ccf53067 100644 --- a/engine/platform/platform.h +++ b/engine/platform/platform.h @@ -51,6 +51,11 @@ void Platform_UpdateStatusLine( void ); static inline void Platform_UpdateStatusLine( void ) { } #endif +#if XASH_NSWITCH +void NSwitch_Init( void ); +void NSwitch_Shutdown( void ); +#endif + /* ============================================================================== diff --git a/engine/platform/posix/lib_posix.c b/engine/platform/posix/lib_posix.c index 746b73e7..ad97130e 100644 --- a/engine/platform/posix/lib_posix.c +++ b/engine/platform/posix/lib_posix.c @@ -15,7 +15,6 @@ GNU General Public License for more details. #define _GNU_SOURCE #include "platform/platform.h" #if XASH_LIB == LIB_POSIX -#include #ifdef XASH_IRIX #include "platform/irix/dladdr.h" #endif diff --git a/engine/platform/posix/sys_posix.c b/engine/platform/posix/sys_posix.c index c5371f98..3872f8da 100644 --- a/engine/platform/posix/sys_posix.c +++ b/engine/platform/posix/sys_posix.c @@ -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]; diff --git a/engine/platform/sdl/sys_sdl.c b/engine/platform/sdl/sys_sdl.c index 0194c291..8c6fc13f 100644 --- a/engine/platform/sdl/sys_sdl.c +++ b/engine/platform/sdl/sys_sdl.c @@ -68,6 +68,9 @@ void Platform_Init( void ) #ifdef XASH_WIN32 Wcon_CreateConsole(); // system console used by dedicated server or show fatal errors #endif +#ifdef XASH_NSWITCH + NSwitch_Init(); +#endif SDLash_InitCursors(); } @@ -79,4 +82,7 @@ void Platform_Shutdown( void ) #ifdef XASH_WIN32 Wcon_DestroyConsole(); #endif +#ifdef XASH_NSWITCH + NSwitch_Shutdown(); +#endif } diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index d3d953dc..c2d84e01 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -3100,7 +3100,7 @@ void SV_SetStringArrayMode( qboolean dynamic ) #endif } -#if XASH_64BIT && !XASH_WIN32 && !XASH_APPLE +#if XASH_64BIT && !XASH_WIN32 && !XASH_APPLE && !XASH_NSWITCH #define USE_MMAP #include #endif diff --git a/engine/wscript b/engine/wscript index 8195d772..1639147e 100644 --- a/engine/wscript +++ b/engine/wscript @@ -48,6 +48,14 @@ def configure(conf): conf.options.NO_ASYNC_RESOLVE = True if not conf.check_cc( fragment='int main(){ int i = socket();}', lib = 'wattcpwl', mandatory=False ): conf.define('XASH_NO_NETWORK',1) + elif conf.env.DEST_OS == 'nswitch': + conf.load('sdl2') + if not conf.env.HAVE_SDL2: + conf.fatal('SDL2 not availiable! Install switch-sdl2!') + conf.define('XASH_SDL', 2) + # 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) @@ -123,7 +131,7 @@ def build(bld): if bld.env.DEST_OS == 'win32': libs += ['USER32', 'SHELL32', 'GDI32', 'ADVAPI32', 'DBGHELP', 'PSAPI', 'WS2_32' ] source += bld.path.ant_glob(['platform/win32/*.c']) - elif bld.env.DEST_OS != 'dos': #posix + elif bld.env.DEST_OS != 'dos' and bld.env.DEST_OS != 'nswitch': #posix libs += [ 'M', 'RT', 'PTHREAD', 'ASOUND'] if not bld.env.STATIC: libs += ['DL'] @@ -162,6 +170,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/posix/*.c']) + source += bld.path.ant_glob(['platform/nswitch/*.c']) + # add client files if not bld.env.DEDICATED: source += bld.path.ant_glob([ @@ -172,22 +185,34 @@ def build(bld): includes = ['server', 'client', 'client/vgui' ] - if bld.env.SINGLE_BINARY: - install_path = bld.env.BINDIR - program = 'cxxprogram' if is_cxx_link else 'cprogram' - if bld.env.STATIC: - program += '_static' - features = ['c', program] + # Switch has custom parameters + if bld.env.DEST_OS == 'nswitch': + bld(source = source, + target = 'xash', + features = 'c cxxprogram', + includes = includes, + use = libs, + install_path = None, + nro_install_path = bld.env.BINDIR, + nacp = 'platform/nswitch/xash3d-fwgs.nacp', + icon = 'platform/nswitch/icon.jpg') else: - install_path = bld.env.LIBDIR - features = ['c', 'cxxshlib' if is_cxx_link else 'cshlib'] - - bld(source = source, - target = 'xash', - features = features, - includes = includes, - use = libs, - install_path = install_path, - subsystem = bld.env.MSVC_SUBSYSTEM, - rpath = '$ORIGIN' - ) + if bld.env.SINGLE_BINARY: + install_path = bld.env.BINDIR + program = 'cxxprogram' if is_cxx_link else 'cprogram' + if bld.env.STATIC: + program += '_static' + features = ['c', program] + else: + install_path = bld.env.LIBDIR + features = ['c', 'cxxshlib' if is_cxx_link else 'cshlib'] + + bld(source = source, + target = 'xash', + features = features, + includes = includes, + use = libs, + install_path = install_path, + subsystem = bld.env.MSVC_SUBSYSTEM, + rpath = '$ORIGIN' + ) diff --git a/public/build.c b/public/build.c index 758ef738..08827800 100644 --- a/public/build.c +++ b/public/build.c @@ -109,6 +109,8 @@ const char *Q_PlatformStringByID( const int platform ) return "serenity"; case PLATFORM_IRIX: return "irix"; + case PLATFORM_NSWITCH: + return "nswitch"; } assert( 0 ); diff --git a/public/build.h b/public/build.h index b2ff2c2d..8a4db711 100644 --- a/public/build.h +++ b/public/build.h @@ -82,6 +82,7 @@ Then you can use another oneliner to query all variables: #undef XASH_SERENITY #undef XASH_WIN32 #undef XASH_X86 +#undef XASH_NSWITCH //================================================================ // @@ -119,12 +120,14 @@ Then you can use another oneliner to query all variables: #if TARGET_OS_IOS #define XASH_IOS 1 #endif // TARGET_OS_IOS + #elif defined __SWITCH__ + #define XASH_NSWITCH 1 #else #error #endif #endif -#if XASH_ANDROID || defined XASH_IOS +#if XASH_ANDROID || defined XASH_IOS || defined XASH_NSWITCH #define XASH_MOBILE_PLATFORM 1 #endif diff --git a/public/buildenums.h b/public/buildenums.h index 872975ad..ed7a0c58 100644 --- a/public/buildenums.h +++ b/public/buildenums.h @@ -39,6 +39,7 @@ GNU General Public License for more details. #define PLATFORM_HAIKU 10 #define PLATFORM_SERENITY 11 #define PLATFORM_IRIX 12 +#define PLATFORM_NSWITCH 13 #if XASH_WIN32 #define XASH_PLATFORM PLATFORM_WIN32 @@ -64,6 +65,8 @@ GNU General Public License for more details. #define XASH_PLATFORM PLATFORM_SERENITY #elif XASH_IRIX #define XASH_PLATFORM PLATFORM_IRIX +#elif XASH_NSWITCH + #define XASH_PLATFORM PLATFORM_NSWITCH #else #error #endif diff --git a/scripts/waifulib/compiler_optimizations.py b/scripts/waifulib/compiler_optimizations.py index a0fd9b87..110b0762 100644 --- a/scripts/waifulib/compiler_optimizations.py +++ b/scripts/waifulib/compiler_optimizations.py @@ -169,4 +169,8 @@ def get_optimization_flags(conf): if conf.options.POLLY: cflags += conf.get_flags_by_compiler(POLLY_CFLAGS, conf.env.COMPILER_CC) + if conf.env.DEST_OS == 'nswitch' and conf.options.BUILD_TYPE == 'debug': + # enable remote debugger + cflags.append('-DNSWITCH_DEBUG') + return cflags, linkflags diff --git a/scripts/waifulib/nswitch.py b/scripts/waifulib/nswitch.py new file mode 100644 index 00000000..63391768 --- /dev/null +++ b/scripts/waifulib/nswitch.py @@ -0,0 +1,64 @@ +# encoding: utf-8 +# nswitch.py -- switch NRO task +# Copyright (C) 2018 a1batross +# 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. + +from waflib.Tools import ccroot +from waflib import * + +def configure(conf): + conf.find_program('elf2nro') + + v = conf.env + + v.ELF2NRO_NACP_F = ['--nacp='] + v.ELF2NRO_ICON_F = ['--icon='] + +class elf2nro(Task.Task): + color = 'RED' + run_str = '${ELF2NRO} ${ELFFILE} ${TGT} ${ELF2NRO_NACP_F?NACP}${NACP} ${ELF2NRO_ICON_F?ICON}${ICON}' + + def keyword(self): + if Logs.colors_lst['USE']: # red/blue switch colors :) + return '%sConverting to NRO' % Logs.colors_lst['CYAN'] + return 'Converting to NRO' + +@TaskGen.feature('cxxprogram') +@TaskGen.after_method('apply_link') +def apply_nro(self): + elffile = self.link_task.outputs[0] + + nodes = [elffile] + + def add_source_file(ctx, nodes, f): + if f: + if isinstance(f, str): + node = ctx.path.make_node(f) + elif isinstance(f, Node.Node): + node = f + + nodes += [node] + return node + return None + + nacpfile = add_source_file(self, nodes, getattr(self, 'nacp', None)) + iconfile = add_source_file(self, nodes, getattr(self, 'icon', None)) + self.env.ELFFILE = str(elffile) + if nacpfile: self.env.NACP = str(nacpfile) + if iconfile: self.env.ICON = str(iconfile) + + tsk = self.nro_task = self.create_task('elf2nro', nodes) + self.nro_task.set_outputs(nodes[0].change_ext('.nro')) + + inst_to = getattr(self, 'nro_install_path', None) + if inst_to: + self.add_install_files(install_to=inst_to, + install_from=tsk.outputs[:], chmod=Utils.O755, task=tsk) diff --git a/scripts/waifulib/xcompile.py b/scripts/waifulib/xcompile.py index 981a081d..f2fa4091 100644 --- a/scripts/waifulib/xcompile.py +++ b/scripts/waifulib/xcompile.py @@ -30,6 +30,8 @@ ANDROID_NDK_API_MIN = { 10: 3, 19: 16, 20: 16, 23: 16, 25: 19 } # minimal API le 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,87 @@ 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(NSWITCH_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 gen_toolchain_prefix(self): + return 'aarch64-none-elf-' + + def gen_gcc_toolchain_path(self): + return os.path.join(self.dka64_dir, 'bin', self.gen_toolchain_prefix()) + + def cc(self): + return self.gen_gcc_toolchain_path() + 'gcc' + + def cxx(self): + return self.gen_gcc_toolchain_path() + 'g++' + + def strip(self): + return self.gen_gcc_toolchain_path() + 'strip' + + def pkgconfig(self): + # counter-intuitively, this motherfucker is in $DEVKITPRO/portlibs/switch/bin + return os.path.join(self.portlibs_dir, 'bin', self.gen_toolchain_prefix() + '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] + # the game wants GNU extensions + if cxx: + cflags += ['-std=gnu++17', '-D_GNU_SOURCE'] + else: + cflags += ['-std=gnu11', '-D_GNU_SOURCE'] + 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 -rdynamic + linkflags += ['-Wl,--hash-style=sysv', '-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): + # system libraries implicitly require math and C++ standard library + ldflags = ['-lm', '-lstdc++'] + return ldflags + def options(opt): xc = opt.add_option_group('Cross compile options') xc.add_option('--android', action='store', dest='ANDROID_OPTS', default=None, @@ -356,6 +439,8 @@ def options(opt): help='enable building for Motorola MAGX [default: %default]') xc.add_option('--enable-msvc-wine', action='store_true', dest='MSVC_WINE', default=False, help='enable building with MSVC using Wine [default: %default]') + xc.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: @@ -408,10 +493,23 @@ def configure(conf): conf.env.DEST_OS = 'win32' conf.env.DEST_CPU = conf.env.MSVC_TARGETS[0] conf.env.COMPILER_CXX = conf.env.COMPILER_CC = 'msvc' + 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.DEST_OS = 'nswitch' conf.env.MAGX = conf.options.MAGX conf.env.MSVC_WINE = conf.options.MSVC_WINE - 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 diff --git a/wscript b/wscript index 4931ad6a..be23b686 100644 --- a/wscript +++ b/wscript @@ -132,6 +132,9 @@ def configure(conf): # Load compilers early conf.load('xshlib xcompile compiler_c compiler_cxx') + if conf.options.NSWITCH: + conf.load('nswitch') + # HACKHACK: override msvc DEST_CPU value by something that we understand if conf.env.DEST_CPU == 'amd64': conf.env.DEST_CPU = 'x86_64' @@ -170,6 +173,12 @@ def configure(conf): enforce_pic = False elif conf.env.DEST_OS == 'dos': conf.options.SINGLE_BINARY = True + 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 if conf.env.STATIC_LINKING: enforce_pic = False # PIC may break full static builds @@ -233,6 +242,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: @@ -282,7 +299,10 @@ def configure(conf): conf.define('ALLOCA_H', 'malloc.h') if conf.env.DEST_OS != 'win32': - conf.check_cc(lib='dl', mandatory=False) + if conf.env.DEST_OS == 'nswitch': + conf.check_cfg(package='solder', args='--cflags --libs', uselib_store='SOLDER') + else: + conf.check_cc(lib='dl', mandatory=False) if not conf.env.LIB_M: # HACK: already added in xcompile! conf.check_cc(lib='m') @@ -354,7 +374,7 @@ int main(int argc, char **argv) { strchrnul(argv[1], 'x'); return 0; }''' conf.env.LIBDIR = conf.env.BINDIR = conf.env.LIBDIR + '/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 != 'android': conf.env.PREFIX = '/' conf.env.SHAREDIR = conf.env.LIBDIR = conf.env.BINDIR = conf.env.PREFIX