mirror of
https://github.com/YGGverse/xash3d-fwgs.git
synced 2025-01-17 18:40:02 +00:00
Merge remote-tracking branch 'fgsfds/switch_newer'
This commit is contained in:
commit
2aeee59a31
3
.github/workflows/c-cpp.yml
vendored
3
.github/workflows/c-cpp.yml
vendored
@ -34,6 +34,9 @@ jobs:
|
|||||||
# targetos: motomagx
|
# targetos: motomagx
|
||||||
# targetarch: armv6
|
# targetarch: armv6
|
||||||
|
|
||||||
|
- os: ubuntu-20.04
|
||||||
|
targetos: nswitch
|
||||||
|
targetarch: arm64
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
targetos: win32
|
targetos: win32
|
||||||
targetarch: amd64
|
targetarch: amd64
|
||||||
|
@ -47,6 +47,7 @@ GNU General Public License for more details.
|
|||||||
#define MSGBOX_SDL 1
|
#define MSGBOX_SDL 1
|
||||||
#define MSGBOX_ANDROID 2
|
#define MSGBOX_ANDROID 2
|
||||||
#define MSGBOX_WIN32 3
|
#define MSGBOX_WIN32 3
|
||||||
|
#define MSGBOX_NSWITCH 4
|
||||||
|
|
||||||
|
|
||||||
// library loading (XASH_LIB)
|
// library loading (XASH_LIB)
|
||||||
|
@ -47,7 +47,9 @@ SETUP BACKENDS DEFINITIONS
|
|||||||
#endif // XASH_TIMER
|
#endif // XASH_TIMER
|
||||||
|
|
||||||
#ifndef XASH_MESSAGEBOX
|
#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 // XASH_MESSAGEBOX
|
||||||
#endif
|
#endif
|
||||||
#elif XASH_ANDROID
|
#elif XASH_ANDROID
|
||||||
@ -105,6 +107,8 @@ SETUP BACKENDS DEFINITIONS
|
|||||||
#ifndef XASH_MESSAGEBOX
|
#ifndef XASH_MESSAGEBOX
|
||||||
#if XASH_WIN32
|
#if XASH_WIN32
|
||||||
#define XASH_MESSAGEBOX MSGBOX_WIN32
|
#define XASH_MESSAGEBOX MSGBOX_WIN32
|
||||||
|
#elif XASH_NSWITCH
|
||||||
|
#define XASH_MESSAGEBOX MSGBOX_NSWITCH
|
||||||
#else // !XASH_WIN32
|
#else // !XASH_WIN32
|
||||||
#define XASH_MESSAGEBOX MSGBOX_STDERR
|
#define XASH_MESSAGEBOX MSGBOX_STDERR
|
||||||
#endif // !XASH_WIN32
|
#endif // !XASH_WIN32
|
||||||
@ -177,4 +181,9 @@ Default build-depended cvar and constant values
|
|||||||
#define DEFAULT_FULLSCREEN 1
|
#define DEFAULT_FULLSCREEN 1
|
||||||
#endif // DEFAULT_FULLSCREEN
|
#endif // DEFAULT_FULLSCREEN
|
||||||
|
|
||||||
|
#if XASH_NSWITCH
|
||||||
|
#define DEFAULT_MODE_WIDTH 1280
|
||||||
|
#define DEFAULT_MODE_HEIGHT 720
|
||||||
|
#endif // XASH_NSWITCH
|
||||||
|
|
||||||
#endif // DEFAULTS_H
|
#endif // DEFAULTS_H
|
||||||
|
@ -39,10 +39,15 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
#if XASH_POSIX
|
#if XASH_POSIX
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <dlfcn.h>
|
#if XASH_NSWITCH
|
||||||
#define HAVE_DUP
|
#define SOLDER_LIBDL_COMPAT
|
||||||
#define O_BINARY 0
|
#include <solder.h>
|
||||||
#define O_TEXT 0
|
#else
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#define HAVE_DUP
|
||||||
|
#define O_BINARY 0
|
||||||
|
#endif
|
||||||
|
#define O_TEXT 0
|
||||||
#define _mkdir( x ) mkdir( x, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH )
|
#define _mkdir( x ) mkdir( x, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1230,7 +1230,7 @@ void Field_KeyDownEvent( field_t *edit, int key )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( key == K_BACKSPACE || key == K_B_BUTTON )
|
if( key == K_BACKSPACE || key == K_X_BUTTON )
|
||||||
{
|
{
|
||||||
if( edit->cursor > 0 )
|
if( edit->cursor > 0 )
|
||||||
{
|
{
|
||||||
@ -1575,7 +1575,7 @@ void Key_Console( int key )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// command completion
|
// command completion
|
||||||
if( key == K_TAB || key == K_X_BUTTON )
|
if( key == K_TAB || key == K_L2_BUTTON )
|
||||||
{
|
{
|
||||||
Con_CompleteCommand( &con.input );
|
Con_CompleteCommand( &con.input );
|
||||||
Con_Bottom();
|
Con_Bottom();
|
||||||
@ -1638,6 +1638,24 @@ void Key_Console( int key )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if XASH_NSWITCH
|
||||||
|
// enable the OSK with button press
|
||||||
|
if( key == K_Y_BUTTON )
|
||||||
|
{
|
||||||
|
Key_EnableTextInput( true, true );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// exit the console by pressing MINUS
|
||||||
|
if( key == K_BACK_BUTTON )
|
||||||
|
{
|
||||||
|
if( cls.state == ca_active && !cl.background )
|
||||||
|
Key_SetKeyDest( key_game );
|
||||||
|
else UI_SetActiveMenu( true );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// pass to the normal editline routine
|
// pass to the normal editline routine
|
||||||
Field_KeyDownEvent( &con.input, key );
|
Field_KeyDownEvent( &con.input, key );
|
||||||
}
|
}
|
||||||
@ -1653,14 +1671,14 @@ void Key_Message( int key )
|
|||||||
{
|
{
|
||||||
char buffer[MAX_SYSPATH];
|
char buffer[MAX_SYSPATH];
|
||||||
|
|
||||||
if( key == K_ESCAPE )
|
if( key == K_ESCAPE || key == K_BACK_BUTTON )
|
||||||
{
|
{
|
||||||
Key_SetKeyDest( key_game );
|
Key_SetKeyDest( key_game );
|
||||||
Con_ClearField( &con.chat );
|
Con_ClearField( &con.chat );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( key == K_ENTER || key == K_KP_ENTER )
|
if( key == K_ENTER || key == K_KP_ENTER || key == K_A_BUTTON )
|
||||||
{
|
{
|
||||||
if( con.chat.buffer[0] && cls.state == ca_active )
|
if( con.chat.buffer[0] && cls.state == ca_active )
|
||||||
{
|
{
|
||||||
|
@ -841,7 +841,9 @@ void GAME_EXPORT Key_SetKeyDest( int key_dest )
|
|||||||
cls.key_dest = key_menu;
|
cls.key_dest = key_menu;
|
||||||
break;
|
break;
|
||||||
case key_console:
|
case key_console:
|
||||||
|
#if !XASH_NSWITCH // if we don't disable this, pops up the keyboard during load
|
||||||
Key_EnableTextInput( true, false );
|
Key_EnableTextInput( true, false );
|
||||||
|
#endif
|
||||||
cls.key_dest = key_console;
|
cls.key_dest = key_console;
|
||||||
break;
|
break;
|
||||||
case key_message:
|
case key_message:
|
||||||
|
@ -895,8 +895,11 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
|
|||||||
host.mempool = Mem_AllocPool( "Zone Engine" );
|
host.mempool = Mem_AllocPool( "Zone Engine" );
|
||||||
|
|
||||||
// HACKHACK: Quake console is always allowed
|
// HACKHACK: Quake console is always allowed
|
||||||
|
// HACKHACK: console is also always allowed on the Switch since we can't really pass command line
|
||||||
// TODO: determine if we are running QWrap more reliable
|
// TODO: determine if we are running QWrap more reliable
|
||||||
if( Sys_CheckParm( "-console" ) || !Q_stricmp( SI.exeName, "quake" ))
|
#if !XASH_NSWITCH
|
||||||
|
if( Sys_CheckParm( "-console" ) || !Q_stricmp( SI.exeName, "quake" ) )
|
||||||
|
#endif
|
||||||
host.allow_console = true;
|
host.allow_console = true;
|
||||||
|
|
||||||
if( Sys_CheckParm( "-dev" ))
|
if( Sys_CheckParm( "-dev" ))
|
||||||
@ -1013,7 +1016,7 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
|
|||||||
#if TARGET_OS_IOS
|
#if TARGET_OS_IOS
|
||||||
const char *IOS_GetDocsDir();
|
const char *IOS_GetDocsDir();
|
||||||
Q_strncpy( host.rootdir, IOS_GetDocsDir(), sizeof(host.rootdir) );
|
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;
|
char *szBasePath;
|
||||||
|
|
||||||
if( !( szBasePath = SDL_GetBasePath() ) )
|
if( !( szBasePath = SDL_GetBasePath() ) )
|
||||||
|
@ -20,6 +20,9 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
#if defined(XASH_NO_NETWORK)
|
#if defined(XASH_NO_NETWORK)
|
||||||
#include "platform/stub/net_stub.h"
|
#include "platform/stub/net_stub.h"
|
||||||
|
#elif XASH_NSWITCH
|
||||||
|
// our ntohl is here
|
||||||
|
#include <arpa/inet.h>
|
||||||
#elif !XASH_WIN32
|
#elif !XASH_WIN32
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -264,6 +264,11 @@ static void Sys_PrintStdout( const char *logtime, const char *msg )
|
|||||||
void IOS_Log( const char * );
|
void IOS_Log( const char * );
|
||||||
IOS_Log( buf );
|
IOS_Log( buf );
|
||||||
#endif // TARGET_OS_IOS
|
#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
|
#elif !XASH_WIN32 // Wcon does the job
|
||||||
Sys_PrintLogfile( STDOUT_FILENO, logtime, msg, XASH_COLORIZE_CONSOLE );
|
Sys_PrintLogfile( STDOUT_FILENO, logtime, msg, XASH_COLORIZE_CONSOLE );
|
||||||
Sys_FlushStdout();
|
Sys_FlushStdout();
|
||||||
|
@ -26,7 +26,6 @@ GNU General Public License for more details.
|
|||||||
#if XASH_POSIX
|
#if XASH_POSIX
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <dlfcn.h>
|
|
||||||
|
|
||||||
#if !XASH_ANDROID
|
#if !XASH_ANDROID
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
@ -37,6 +36,10 @@ GNU General Public License for more details.
|
|||||||
#include <process.h>
|
#include <process.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if XASH_NSWITCH
|
||||||
|
#include <switch.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "menu_int.h" // _UPDATE_PAGE macro
|
#include "menu_int.h" // _UPDATE_PAGE macro
|
||||||
|
|
||||||
#include "library.h"
|
#include "library.h"
|
||||||
@ -126,7 +129,7 @@ const char *Sys_GetCurrentUser( void )
|
|||||||
|
|
||||||
if( GetUserName( s_userName, &size ))
|
if( GetUserName( s_userName, &size ))
|
||||||
return s_userName;
|
return s_userName;
|
||||||
#elif XASH_POSIX && !XASH_ANDROID
|
#elif XASH_POSIX && !XASH_ANDROID && !XASH_NSWITCH
|
||||||
uid_t uid = geteuid();
|
uid_t uid = geteuid();
|
||||||
struct passwd *pw = getpwuid( uid );
|
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 )
|
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;
|
int i = 0;
|
||||||
qboolean replacedArg = false;
|
qboolean replacedArg = false;
|
||||||
size_t exelen;
|
size_t exelen;
|
||||||
@ -613,6 +629,7 @@ qboolean Sys_NewInstance( const char *gamedir )
|
|||||||
free( newargs[i] );
|
free( newargs[i] );
|
||||||
free( newargs );
|
free( newargs );
|
||||||
free( exe );
|
free( exe );
|
||||||
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -795,7 +795,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(__sgi)
|
#elif defined(__sgi) || defined(__SWITCH__)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These functions are stubbed for now to get the code compiling.
|
* These functions are stubbed for now to get the code compiling.
|
||||||
|
BIN
engine/platform/nswitch/icon.jpg
Normal file
BIN
engine/platform/nswitch/icon.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.7 KiB |
125
engine/platform/nswitch/sys_nswitch.c
Normal file
125
engine/platform/nswitch/sys_nswitch.c
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <switch.h>
|
||||||
|
#include <solder.h>
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
static int nxlink_sock = -1;
|
||||||
|
|
||||||
|
/* HACKHACK: force-export stuff required by the dynamic libs */
|
||||||
|
|
||||||
|
// this is required by some std::filesystem crap in libstdc++
|
||||||
|
// we don't have it defined in our libc
|
||||||
|
long pathconf( const char *path, int name ) { return -1; }
|
||||||
|
|
||||||
|
// part of libunwind; required by any dynamic lib that uses C++ exceptions
|
||||||
|
extern void *_Unwind_Resume;
|
||||||
|
|
||||||
|
// 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( pathconf ),
|
||||||
|
SOLDER_EXPORT_SYMBOL( fsync ),
|
||||||
|
SOLDER_EXPORT_SYMBOL( strchrnul ),
|
||||||
|
SOLDER_EXPORT_SYMBOL( stpcpy ),
|
||||||
|
SOLDER_EXPORT_SYMBOL( _Unwind_Resume ),
|
||||||
|
};
|
||||||
|
|
||||||
|
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( );
|
||||||
|
}
|
BIN
engine/platform/nswitch/xash3d-fwgs.nacp
Normal file
BIN
engine/platform/nswitch/xash3d-fwgs.nacp
Normal file
Binary file not shown.
@ -51,6 +51,11 @@ void Platform_UpdateStatusLine( void );
|
|||||||
static inline void Platform_UpdateStatusLine( void ) { }
|
static inline void Platform_UpdateStatusLine( void ) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if XASH_NSWITCH
|
||||||
|
void NSwitch_Init( void );
|
||||||
|
void NSwitch_Shutdown( void );
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ GNU General Public License for more details.
|
|||||||
#endif
|
#endif
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
#if XASH_LIB == LIB_POSIX
|
#if XASH_LIB == LIB_POSIX
|
||||||
#include <dlfcn.h>
|
|
||||||
#ifdef XASH_IRIX
|
#ifdef XASH_IRIX
|
||||||
#include "platform/irix/dladdr.h"
|
#include "platform/irix/dladdr.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -67,7 +67,7 @@ static qboolean Sys_FindExecutable( const char *baseName, char *buf, size_t size
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !XASH_ANDROID
|
#if !XASH_ANDROID && !XASH_NSWITCH
|
||||||
void Platform_ShellExecute( const char *path, const char *parms )
|
void Platform_ShellExecute( const char *path, const char *parms )
|
||||||
{
|
{
|
||||||
char xdgOpen[128];
|
char xdgOpen[128];
|
||||||
|
@ -68,6 +68,9 @@ void Platform_Init( void )
|
|||||||
#ifdef XASH_WIN32
|
#ifdef XASH_WIN32
|
||||||
Wcon_CreateConsole(); // system console used by dedicated server or show fatal errors
|
Wcon_CreateConsole(); // system console used by dedicated server or show fatal errors
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef XASH_NSWITCH
|
||||||
|
NSwitch_Init();
|
||||||
|
#endif
|
||||||
|
|
||||||
SDLash_InitCursors();
|
SDLash_InitCursors();
|
||||||
}
|
}
|
||||||
@ -79,4 +82,7 @@ void Platform_Shutdown( void )
|
|||||||
#ifdef XASH_WIN32
|
#ifdef XASH_WIN32
|
||||||
Wcon_DestroyConsole();
|
Wcon_DestroyConsole();
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef XASH_NSWITCH
|
||||||
|
NSwitch_Shutdown();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -3100,7 +3100,7 @@ void SV_SetStringArrayMode( qboolean dynamic )
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if XASH_64BIT && !XASH_WIN32 && !XASH_APPLE
|
#if XASH_64BIT && !XASH_WIN32 && !XASH_APPLE && !XASH_NSWITCH
|
||||||
#define USE_MMAP
|
#define USE_MMAP
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -983,6 +983,8 @@ void SV_Init( void )
|
|||||||
Cvar_RegisterVariable( &sv_enttools_enable );
|
Cvar_RegisterVariable( &sv_enttools_enable );
|
||||||
Cvar_RegisterVariable( &sv_enttools_maxfire );
|
Cvar_RegisterVariable( &sv_enttools_maxfire );
|
||||||
|
|
||||||
|
Cvar_RegisterVariable( &sv_autosave );
|
||||||
|
|
||||||
sv_allow_joystick = Cvar_Get( "sv_allow_joystick", "1", FCVAR_ARCHIVE, "allow connect with joystick enabled" );
|
sv_allow_joystick = Cvar_Get( "sv_allow_joystick", "1", FCVAR_ARCHIVE, "allow connect with joystick enabled" );
|
||||||
sv_allow_mouse = Cvar_Get( "sv_allow_mouse", "1", FCVAR_ARCHIVE, "allow connect with mouse" );
|
sv_allow_mouse = Cvar_Get( "sv_allow_mouse", "1", FCVAR_ARCHIVE, "allow connect with mouse" );
|
||||||
sv_allow_touch = Cvar_Get( "sv_allow_touch", "1", FCVAR_ARCHIVE, "allow connect with touch controls" );
|
sv_allow_touch = Cvar_Get( "sv_allow_touch", "1", FCVAR_ARCHIVE, "allow connect with touch controls" );
|
||||||
|
@ -48,6 +48,18 @@ def configure(conf):
|
|||||||
conf.options.NO_ASYNC_RESOLVE = True
|
conf.options.NO_ASYNC_RESOLVE = True
|
||||||
if not conf.check_cc( fragment='int main(){ int i = socket();}', lib = 'wattcpwl', mandatory=False ):
|
if not conf.check_cc( fragment='int main(){ int i = socket();}', lib = 'wattcpwl', mandatory=False ):
|
||||||
conf.define('XASH_NO_NETWORK',1)
|
conf.define('XASH_NO_NETWORK',1)
|
||||||
|
elif conf.env.DEST_OS == 'nswitch':
|
||||||
|
# re-enable undefined reference errors
|
||||||
|
conf.env.CXXFLAGS += ['-Wl,--no-undefined']
|
||||||
|
conf.env.CFLAGS += ['-Wl,--no-undefined']
|
||||||
|
# allow the SDL2 sanity check to complete properly by linking in libstdc++ and lm normally
|
||||||
|
conf.env.LDFLAGS += ['-lstdc++', '-lm']
|
||||||
|
conf.load('sdl2')
|
||||||
|
if not conf.env.HAVE_SDL2:
|
||||||
|
conf.fatal('SDL2 not availiable! Install switch-sdl2!')
|
||||||
|
conf.define('XASH_SDL', 2)
|
||||||
|
conf.env.LDFLAGS.remove('-lstdc++')
|
||||||
|
conf.env.LDFLAGS.remove('-lm')
|
||||||
elif conf.options.FBDEV_SW:
|
elif conf.options.FBDEV_SW:
|
||||||
# unused, XASH_LINUX without XASH_SDL gives fbdev & alsa support
|
# unused, XASH_LINUX without XASH_SDL gives fbdev & alsa support
|
||||||
# conf.define('XASH_FBDEV', 1)
|
# conf.define('XASH_FBDEV', 1)
|
||||||
@ -123,7 +135,7 @@ def build(bld):
|
|||||||
if bld.env.DEST_OS == 'win32':
|
if bld.env.DEST_OS == 'win32':
|
||||||
libs += ['USER32', 'SHELL32', 'GDI32', 'ADVAPI32', 'DBGHELP', 'PSAPI', 'WS2_32' ]
|
libs += ['USER32', 'SHELL32', 'GDI32', 'ADVAPI32', 'DBGHELP', 'PSAPI', 'WS2_32' ]
|
||||||
source += bld.path.ant_glob(['platform/win32/*.c'])
|
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']
|
libs += [ 'M', 'RT', 'PTHREAD', 'ASOUND']
|
||||||
if not bld.env.STATIC:
|
if not bld.env.STATIC:
|
||||||
libs += ['DL']
|
libs += ['DL']
|
||||||
@ -162,6 +174,11 @@ def build(bld):
|
|||||||
libs += ['LOG']
|
libs += ['LOG']
|
||||||
source += bld.path.ant_glob(['platform/android/*.cpp', 'platform/android/*.c', 'platform/linux/*.c'])
|
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
|
# add client files
|
||||||
if not bld.env.DEDICATED:
|
if not bld.env.DEDICATED:
|
||||||
source += bld.path.ant_glob([
|
source += bld.path.ant_glob([
|
||||||
@ -172,22 +189,38 @@ def build(bld):
|
|||||||
|
|
||||||
includes = ['server', 'client', 'client/vgui' ]
|
includes = ['server', 'client', 'client/vgui' ]
|
||||||
|
|
||||||
if bld.env.SINGLE_BINARY:
|
# Switch has custom parameters
|
||||||
install_path = bld.env.BINDIR
|
if bld.env.DEST_OS == 'nswitch':
|
||||||
program = 'cxxprogram' if is_cxx_link else 'cprogram'
|
# HACK: link in the entirety of libstdc++ so that dynamic libs could use all of it without manual exporting
|
||||||
if bld.env.STATIC:
|
# we can't do this right away because std::filesystem will complain about not having pathconf(),
|
||||||
program += '_static'
|
# which we have defined in sys_nswitch.c
|
||||||
features = ['c', program]
|
bld.env.LDFLAGS += ['-Wl,--whole-archive', '-lstdc++', '-Wl,--no-whole-archive', '-lm']
|
||||||
|
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:
|
else:
|
||||||
install_path = bld.env.LIBDIR
|
if bld.env.SINGLE_BINARY:
|
||||||
features = ['c', 'cxxshlib' if is_cxx_link else 'cshlib']
|
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,
|
bld(source = source,
|
||||||
target = 'xash',
|
target = 'xash',
|
||||||
features = features,
|
features = features,
|
||||||
includes = includes,
|
includes = includes,
|
||||||
use = libs,
|
use = libs,
|
||||||
install_path = install_path,
|
install_path = install_path,
|
||||||
subsystem = bld.env.MSVC_SUBSYSTEM,
|
subsystem = bld.env.MSVC_SUBSYSTEM,
|
||||||
rpath = '$ORIGIN'
|
rpath = '$ORIGIN'
|
||||||
)
|
)
|
||||||
|
@ -109,6 +109,8 @@ const char *Q_PlatformStringByID( const int platform )
|
|||||||
return "serenity";
|
return "serenity";
|
||||||
case PLATFORM_IRIX:
|
case PLATFORM_IRIX:
|
||||||
return "irix";
|
return "irix";
|
||||||
|
case PLATFORM_NSWITCH:
|
||||||
|
return "nswitch";
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( 0 );
|
assert( 0 );
|
||||||
|
@ -82,6 +82,7 @@ Then you can use another oneliner to query all variables:
|
|||||||
#undef XASH_SERENITY
|
#undef XASH_SERENITY
|
||||||
#undef XASH_WIN32
|
#undef XASH_WIN32
|
||||||
#undef XASH_X86
|
#undef XASH_X86
|
||||||
|
#undef XASH_NSWITCH
|
||||||
|
|
||||||
//================================================================
|
//================================================================
|
||||||
//
|
//
|
||||||
@ -119,12 +120,14 @@ Then you can use another oneliner to query all variables:
|
|||||||
#if TARGET_OS_IOS
|
#if TARGET_OS_IOS
|
||||||
#define XASH_IOS 1
|
#define XASH_IOS 1
|
||||||
#endif // TARGET_OS_IOS
|
#endif // TARGET_OS_IOS
|
||||||
|
#elif defined __SWITCH__
|
||||||
|
#define XASH_NSWITCH 1
|
||||||
#else
|
#else
|
||||||
#error
|
#error
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if XASH_ANDROID || defined XASH_IOS
|
#if XASH_ANDROID || defined XASH_IOS || defined XASH_NSWITCH
|
||||||
#define XASH_MOBILE_PLATFORM 1
|
#define XASH_MOBILE_PLATFORM 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ GNU General Public License for more details.
|
|||||||
#define PLATFORM_HAIKU 10
|
#define PLATFORM_HAIKU 10
|
||||||
#define PLATFORM_SERENITY 11
|
#define PLATFORM_SERENITY 11
|
||||||
#define PLATFORM_IRIX 12
|
#define PLATFORM_IRIX 12
|
||||||
|
#define PLATFORM_NSWITCH 13
|
||||||
|
|
||||||
#if XASH_WIN32
|
#if XASH_WIN32
|
||||||
#define XASH_PLATFORM PLATFORM_WIN32
|
#define XASH_PLATFORM PLATFORM_WIN32
|
||||||
@ -64,6 +65,8 @@ GNU General Public License for more details.
|
|||||||
#define XASH_PLATFORM PLATFORM_SERENITY
|
#define XASH_PLATFORM PLATFORM_SERENITY
|
||||||
#elif XASH_IRIX
|
#elif XASH_IRIX
|
||||||
#define XASH_PLATFORM PLATFORM_IRIX
|
#define XASH_PLATFORM PLATFORM_IRIX
|
||||||
|
#elif XASH_NSWITCH
|
||||||
|
#define XASH_PLATFORM PLATFORM_NSWITCH
|
||||||
#else
|
#else
|
||||||
#error
|
#error
|
||||||
#endif
|
#endif
|
||||||
|
20
scripts/gha/build_nswitch.sh
Normal file
20
scripts/gha/build_nswitch.sh
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
. scripts/lib.sh
|
||||||
|
|
||||||
|
cd "$BUILDDIR" || die
|
||||||
|
|
||||||
|
rm -rf artifacts build pkgtemp
|
||||||
|
|
||||||
|
mkdir -p pkgtemp/xash3d/{valve,gearbox,bshift}/{dlls,cl_dlls} || die
|
||||||
|
mkdir -p artifacts/ || die
|
||||||
|
|
||||||
|
echo "Running build script in Docker container..."
|
||||||
|
|
||||||
|
docker run --name xash-build --rm -v `pwd`:`pwd` -w `pwd` devkitpro/devkita64:latest bash ./scripts/gha/build_nswitch_docker.sh || die
|
||||||
|
|
||||||
|
echo "Packaging artifacts..."
|
||||||
|
|
||||||
|
pushd pkgtemp
|
||||||
|
7z a -t7z ../artifacts/xash3d-fwgs-nswitch.7z -m0=lzma2 -mx=9 -mfb=64 -md=32m -ms=on -r xash3d/
|
||||||
|
popd
|
64
scripts/gha/build_nswitch_docker.sh
Normal file
64
scripts/gha/build_nswitch_docker.sh
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
. scripts/lib.sh
|
||||||
|
|
||||||
|
# args: branch name, gamedir name
|
||||||
|
build_hlsdk()
|
||||||
|
{
|
||||||
|
echo "Building HLSDK: $1 branch..."
|
||||||
|
git checkout switch-$1
|
||||||
|
./waf configure -T release --nswitch || die_configure
|
||||||
|
./waf build || die
|
||||||
|
cp build/dlls/$1_nswitch_arm64.so ../pkgtemp/xash3d/$2/dlls/
|
||||||
|
cp build/cl_dll/client_nswitch_arm64.so ../pkgtemp/xash3d/$2/cl_dlls/
|
||||||
|
./waf clean
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Setting up environment..."
|
||||||
|
|
||||||
|
# we can't actually download dkp-toolchain-vars even from here, so
|
||||||
|
export PORTLIBS_ROOT=${DEVKITPRO}/portlibs
|
||||||
|
export PATH=${DEVKITPRO}/tools/bin:${DEVKITPRO}/devkitA64/bin:$PATH
|
||||||
|
export TOOL_PREFIX=aarch64-none-elf-
|
||||||
|
export CC=${TOOL_PREFIX}gcc
|
||||||
|
export CXX=${TOOL_PREFIX}g++
|
||||||
|
export AR=${TOOL_PREFIX}gcc-ar
|
||||||
|
export RANLIB=${TOOL_PREFIX}gcc-ranlib
|
||||||
|
export PORTLIBS_PREFIX=${DEVKITPRO}/portlibs/switch
|
||||||
|
export PATH=$PORTLIBS_PREFIX/bin:$PATH
|
||||||
|
export ARCH="-march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIC -ftls-model=local-exec"
|
||||||
|
export CFLAGS="${ARCH} -O2 -ffunction-sections -fdata-sections"
|
||||||
|
export CXXFLAGS="${CFLAGS}"
|
||||||
|
export CPPFLAGS="-D__SWITCH__ -I${PORTLIBS_PREFIX}/include -isystem ${DEVKITPRO}/libnx/include"
|
||||||
|
export LDFLAGS="${ARCH} -L${PORTLIBS_PREFIX}/lib -L${DEVKITPRO}/libnx/lib"
|
||||||
|
export LIBS="-lnx"
|
||||||
|
|
||||||
|
# forgive me father, for I have sinned
|
||||||
|
ln -s /usr/bin/python3 /usr/bin/python
|
||||||
|
|
||||||
|
echo "Building libsolder..."
|
||||||
|
|
||||||
|
make -C libsolder install || die
|
||||||
|
|
||||||
|
echo "Building engine..."
|
||||||
|
|
||||||
|
./waf configure -T release --nswitch || die_configure
|
||||||
|
./waf build || die
|
||||||
|
|
||||||
|
echo "Building HLSDK..."
|
||||||
|
|
||||||
|
# TODO: replace with hlsdk-portable when PRs are merged
|
||||||
|
pushd hlsdk-xash3d
|
||||||
|
build_hlsdk hl valve
|
||||||
|
build_hlsdk opfor gearbox
|
||||||
|
build_hlsdk bshift bshift
|
||||||
|
popd
|
||||||
|
|
||||||
|
echo "Copying artifacts..."
|
||||||
|
|
||||||
|
cp build/engine/xash.nro pkgtemp/xash3d/xash3d.nro
|
||||||
|
cp build/filesystem/filesystem_stdio.so pkgtemp/xash3d/
|
||||||
|
cp build/ref/gl/libref_gl.so pkgtemp/xash3d/
|
||||||
|
cp build/ref/soft/libref_soft.so pkgtemp/xash3d/
|
||||||
|
cp build/3rdparty/mainui/libmenu.so pkgtemp/xash3d/
|
||||||
|
cp build/3rdparty/extras/extras.pk3 pkgtemp/xash3d/valve/
|
18
scripts/gha/deps_nswitch.sh
Normal file
18
scripts/gha/deps_nswitch.sh
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cd $GITHUB_WORKSPACE
|
||||||
|
|
||||||
|
echo "Downloading devkitA64 docker container..."
|
||||||
|
|
||||||
|
docker pull devkitpro/devkita64:latest || exit 1
|
||||||
|
|
||||||
|
echo "Downloading libsolder..."
|
||||||
|
|
||||||
|
rm -rf libsolder
|
||||||
|
git clone https://github.com/fgsfdsfgs/libsolder.git || exit 1
|
||||||
|
|
||||||
|
echo "Downloading HLSDK..."
|
||||||
|
|
||||||
|
# TODO: change to FWGS/hlsdk-portable.git when changes are merged in
|
||||||
|
rm -rf hlsdk-xash3d hlsdk-portable
|
||||||
|
git clone --recursive https://github.com/fgsfdsfgs/hlsdk-xash3d.git || exit 1
|
@ -169,4 +169,8 @@ def get_optimization_flags(conf):
|
|||||||
if conf.options.POLLY:
|
if conf.options.POLLY:
|
||||||
cflags += conf.get_flags_by_compiler(POLLY_CFLAGS, conf.env.COMPILER_CC)
|
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
|
return cflags, linkflags
|
||||||
|
64
scripts/waifulib/nswitch.py
Normal file
64
scripts/waifulib/nswitch.py
Normal file
@ -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)
|
@ -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_STPCPY_API_MIN = 21 # stpcpy() introduced in SDK 21
|
||||||
ANDROID_64BIT_API_MIN = 21 # minimal API level that supports 64-bit targets
|
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
|
# This class does support ONLY r10e and r19c/r20 NDK
|
||||||
class Android:
|
class Android:
|
||||||
ctx = None # waf context
|
ctx = None # waf context
|
||||||
@ -348,6 +350,88 @@ class Android:
|
|||||||
ldflags += ['-march=armv5te']
|
ldflags += ['-march=armv5te']
|
||||||
return ldflags
|
return ldflags
|
||||||
|
|
||||||
|
class NintendoSwitch:
|
||||||
|
ctx = None # waf context
|
||||||
|
arch = "arm64"
|
||||||
|
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):
|
||||||
|
# NOTE: shared libraries should be built without standard libs, so that they could import their contents from the NRO,
|
||||||
|
# but executables, including the SDL2 sanity check, will generally require libstdc++ and libm, which we will add manually
|
||||||
|
ldflags = [] # ['-lm', '-lstdc++']
|
||||||
|
return ldflags
|
||||||
|
|
||||||
def options(opt):
|
def options(opt):
|
||||||
xc = opt.add_option_group('Cross compile options')
|
xc = opt.add_option_group('Cross compile options')
|
||||||
xc.add_option('--android', action='store', dest='ANDROID_OPTS', default=None,
|
xc.add_option('--android', action='store', dest='ANDROID_OPTS', default=None,
|
||||||
@ -356,6 +440,8 @@ def options(opt):
|
|||||||
help='enable building for Motorola MAGX [default: %default]')
|
help='enable building for Motorola MAGX [default: %default]')
|
||||||
xc.add_option('--enable-msvc-wine', action='store_true', dest='MSVC_WINE', default=False,
|
xc.add_option('--enable-msvc-wine', action='store_true', dest='MSVC_WINE', default=False,
|
||||||
help='enable building with MSVC using Wine [default: %default]')
|
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):
|
def configure(conf):
|
||||||
if conf.options.ANDROID_OPTS:
|
if conf.options.ANDROID_OPTS:
|
||||||
@ -408,10 +494,23 @@ def configure(conf):
|
|||||||
conf.env.DEST_OS = 'win32'
|
conf.env.DEST_OS = 'win32'
|
||||||
conf.env.DEST_CPU = conf.env.MSVC_TARGETS[0]
|
conf.env.DEST_CPU = conf.env.MSVC_TARGETS[0]
|
||||||
conf.env.COMPILER_CXX = conf.env.COMPILER_CC = 'msvc'
|
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.MAGX = conf.options.MAGX
|
||||||
conf.env.MSVC_WINE = conf.options.MSVC_WINE
|
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:
|
for k in c_config.MACRO_TO_DESTOS:
|
||||||
MACRO_TO_DESTOS[k] = c_config.MACRO_TO_DESTOS[k] # ordering is important
|
MACRO_TO_DESTOS[k] = c_config.MACRO_TO_DESTOS[k] # ordering is important
|
||||||
c_config.MACRO_TO_DESTOS = MACRO_TO_DESTOS
|
c_config.MACRO_TO_DESTOS = MACRO_TO_DESTOS
|
||||||
|
26
wscript
26
wscript
@ -132,6 +132,9 @@ def configure(conf):
|
|||||||
# Load compilers early
|
# Load compilers early
|
||||||
conf.load('xshlib xcompile compiler_c compiler_cxx')
|
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
|
# HACKHACK: override msvc DEST_CPU value by something that we understand
|
||||||
if conf.env.DEST_CPU == 'amd64':
|
if conf.env.DEST_CPU == 'amd64':
|
||||||
conf.env.DEST_CPU = 'x86_64'
|
conf.env.DEST_CPU = 'x86_64'
|
||||||
@ -170,6 +173,12 @@ def configure(conf):
|
|||||||
enforce_pic = False
|
enforce_pic = False
|
||||||
elif conf.env.DEST_OS == 'dos':
|
elif conf.env.DEST_OS == 'dos':
|
||||||
conf.options.SINGLE_BINARY = True
|
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:
|
if conf.env.STATIC_LINKING:
|
||||||
enforce_pic = False # PIC may break full static builds
|
enforce_pic = False # PIC may break full static builds
|
||||||
@ -236,6 +245,14 @@ def configure(conf):
|
|||||||
|
|
||||||
cflags, linkflags = conf.get_optimization_flags()
|
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 them for the engine executable
|
||||||
|
# additionally, shared libs are linked without standard libs, we'll add those back in the engine wscript
|
||||||
|
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
|
# And here C++ flags starts to be treated separately
|
||||||
cxxflags = list(cflags)
|
cxxflags = list(cflags)
|
||||||
if conf.env.COMPILER_CC != 'msvc' and not conf.options.DISABLE_WERROR:
|
if conf.env.COMPILER_CC != 'msvc' and not conf.options.DISABLE_WERROR:
|
||||||
@ -285,7 +302,12 @@ def configure(conf):
|
|||||||
conf.define('ALLOCA_H', 'malloc.h')
|
conf.define('ALLOCA_H', 'malloc.h')
|
||||||
|
|
||||||
if conf.env.DEST_OS != 'win32':
|
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', mandatory=True)
|
||||||
|
if conf.env.HAVE_SOLDER and conf.env.LIB_SOLDER and conf.options.BUILD_TYPE == 'debug':
|
||||||
|
conf.env.LIB_SOLDER[0] += 'd' # load libsolderd in debug mode
|
||||||
|
else:
|
||||||
|
conf.check_cc(lib='dl', mandatory=False)
|
||||||
|
|
||||||
if not conf.env.LIB_M: # HACK: already added in xcompile!
|
if not conf.env.LIB_M: # HACK: already added in xcompile!
|
||||||
conf.check_cc(lib='m')
|
conf.check_cc(lib='m')
|
||||||
@ -357,7 +379,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.LIBDIR = conf.env.BINDIR = conf.env.LIBDIR + '/xash3d'
|
||||||
conf.env.SHAREDIR = '${PREFIX}/share/xash3d'
|
conf.env.SHAREDIR = '${PREFIX}/share/xash3d'
|
||||||
else:
|
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.PREFIX = '/'
|
||||||
|
|
||||||
conf.env.SHAREDIR = conf.env.LIBDIR = conf.env.BINDIR = conf.env.PREFIX
|
conf.env.SHAREDIR = conf.env.LIBDIR = conf.env.BINDIR = conf.env.PREFIX
|
||||||
|
Loading…
x
Reference in New Issue
Block a user