diff --git a/common/defaults.h b/common/defaults.h index 746b0f4d..bd76b244 100644 --- a/common/defaults.h +++ b/common/defaults.h @@ -165,6 +165,12 @@ Default build-depended cvar and constant values #define DEFAULT_MODE_WIDTH 1280 #define DEFAULT_MODE_HEIGHT 720 #define DEFAULT_ALLOWCONSOLE 1 +#elif XASH_PSVITA + #define DEFAULT_TOUCH_ENABLE "0" + #define DEFAULT_M_IGNORE "1" + #define DEFAULT_MODE_WIDTH 960 + #define DEFAULT_MODE_HEIGHT 544 + #define DEFAULT_ALLOWCONSOLE 1 #elif XASH_MOBILE_PLATFORM #define DEFAULT_TOUCH_ENABLE "1" #define DEFAULT_M_IGNORE "1" diff --git a/common/port.h b/common/port.h index 63419cc6..76189847 100644 --- a/common/port.h +++ b/common/port.h @@ -42,6 +42,10 @@ GNU General Public License for more details. #if XASH_NSWITCH #define SOLDER_LIBDL_COMPAT #include + #elif XASH_PSVITA + #define VRTLD_LIBDL_COMPAT + #include + #define O_BINARY 0 #else #include #define HAVE_DUP diff --git a/engine/client/in_touch.c b/engine/client/in_touch.c index a35a1a67..7131b6c8 100644 --- a/engine/client/in_touch.c +++ b/engine/client/in_touch.c @@ -87,7 +87,7 @@ typedef struct touchbuttonlist_s touch_button_t *last; } touchbuttonlist_t; -struct touch_s +static struct touch_s { qboolean initialized; qboolean config_loaded; diff --git a/engine/common/host.c b/engine/common/host.c index 1d435fb5..54bee1c1 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -1016,6 +1016,12 @@ 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_PSVITA + if ( !PSVita_GetBasePath( host.rootdir, sizeof( host.rootdir ) ) ) + { + Sys_Error( "couldn't find xash3d data directory" ); + host.rootdir[0] = 0; + } #elif (XASH_SDL == 2) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2 char *szBasePath; diff --git a/engine/common/net_ws.c b/engine/common/net_ws.c index bc676d30..cb1ed789 100644 --- a/engine/common/net_ws.c +++ b/engine/common/net_ws.c @@ -25,6 +25,10 @@ GNU General Public License for more details. #else #include "platform/posix/net.h" #endif +#if XASH_PSVITA +#include "platform/psvita/net_psvita.h" +static const struct in6_addr in6addr_any; +#endif #define NET_USE_FRAGMENTS diff --git a/engine/common/sys_con.c b/engine/common/sys_con.c index 53cb27d3..daecebb9 100644 --- a/engine/common/sys_con.c +++ b/engine/common/sys_con.c @@ -265,7 +265,7 @@ static void Sys_PrintStdout( const char *logtime, const char *msg ) IOS_Log( buf ); #endif // TARGET_OS_IOS -#if XASH_NSWITCH && NSWITCH_DEBUG +#if (XASH_NSWITCH && NSWITCH_DEBUG) || XASH_PSVITA // REMOVEME // just spew it to stderr normally in debug mode fprintf( stderr, "%s %s", logtime, buf ); #endif // XASH_NSWITCH && NSWITCH_DEBUG diff --git a/engine/common/system.c b/engine/common/system.c index d7d08165..2eb146d1 100644 --- a/engine/common/system.c +++ b/engine/common/system.c @@ -129,7 +129,7 @@ const char *Sys_GetCurrentUser( void ) if( GetUserName( s_userName, &size )) return s_userName; -#elif XASH_POSIX && !XASH_ANDROID && !XASH_NSWITCH +#elif XASH_POSIX && !XASH_ANDROID && !XASH_NSWITCH && !XASH_PSVITA uid_t uid = geteuid(); struct passwd *pw = getpwuid( uid ); @@ -581,6 +581,9 @@ qboolean Sys_NewInstance( const char *gamedir ) Host_Shutdown( ); envSetNextLoad( exe, newargs ); exit( 0 ); +#elif XASH_PSVITA + fprintf( stderr, "Sys_NewInstance( %s ): not implemented yet\n", gamedir ); + exit( 1 ); #else int i = 0; qboolean replacedArg = false; diff --git a/engine/common/whereami.c b/engine/common/whereami.c index 0a0fb570..b5e8da37 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) || defined(__SWITCH__) +#elif defined(__sgi) || defined(__SWITCH__) || defined(__vita__) /* * These functions are stubbed for now to get the code compiling. diff --git a/engine/platform/linux/vid_fbdev.c b/engine/platform/linux/vid_fbdev.c index bf9d169f..551ca999 100644 --- a/engine/platform/linux/vid_fbdev.c +++ b/engine/platform/linux/vid_fbdev.c @@ -9,7 +9,9 @@ #include #include +#if !XASH_PSVITA #include +#endif #if XASH_ANDROID #include #else diff --git a/engine/platform/platform.h b/engine/platform/platform.h index ccf53067..cd51a95a 100644 --- a/engine/platform/platform.h +++ b/engine/platform/platform.h @@ -56,6 +56,12 @@ void NSwitch_Init( void ); void NSwitch_Shutdown( void ); #endif +#if XASH_PSVITA +void PSVita_Init( void ); +void PSVita_Shutdown( void ); +qboolean PSVita_GetBasePath( char *buf, const size_t buflen ); +#endif + /* ============================================================================== diff --git a/engine/platform/posix/net.h b/engine/platform/posix/net.h index 91ba7562..8353baf1 100644 --- a/engine/platform/posix/net.h +++ b/engine/platform/posix/net.h @@ -17,7 +17,9 @@ GNU General Public License for more details. #include #include +#if !XASH_PSVITA #include +#endif #include #include #include @@ -79,7 +81,7 @@ static int ioctl_stub( int d, unsigned long r, ... ) return 0; } #define ioctlsocket ioctl_stub -#else // XASH_EMSCRIPTEN +#elif !XASH_PSVITA // XASH_EMSCRIPTEN #define ioctlsocket ioctl #endif // XASH_EMSCRIPTEN #define closesocket close diff --git a/engine/platform/posix/sys_posix.c b/engine/platform/posix/sys_posix.c index 3872f8da..85f5500f 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 && !XASH_NSWITCH +#if !XASH_ANDROID && !XASH_NSWITCH && !XASH_PSVITA void Platform_ShellExecute( const char *path, const char *parms ) { char xdgOpen[128]; diff --git a/engine/platform/psvita/net_psvita.h b/engine/platform/psvita/net_psvita.h new file mode 100644 index 00000000..23014c72 --- /dev/null +++ b/engine/platform/psvita/net_psvita.h @@ -0,0 +1,50 @@ +/* +net.h - psvita network stubs +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. +*/ + +#pragma once +#ifndef NET_PSVITA_H +#define NET_PSVITA_H + +#include + +/* we're missing IPv6 support; define some trash */ + +#ifndef IN6_IS_ADDR_V4MAPPED +#define IN6_IS_ADDR_V4MAPPED( p ) ( 0 ) +#endif + +#ifndef IPPROTO_IPV6 +#define IPPROTO_IPV6 41 +#endif + +#ifndef IPV6_MULTICAST_LOOP +#define IPV6_MULTICAST_LOOP 19 +#endif + +#ifndef IPV6_V6ONLY +#define IPV6_V6ONLY 26 +#endif + +#ifndef FIONBIO +#define FIONBIO SO_NONBLOCK +#endif + +// this is only used to set non-blocking on sockets +static inline int ioctlsocket( int fd, int req, unsigned int *arg ) +{ + return setsockopt( fd, SOL_SOCKET, SO_NONBLOCK, arg, sizeof( *arg ) ); +} + +#endif // NET_PSVITA_H diff --git a/engine/platform/psvita/sce_sys/icon0.png b/engine/platform/psvita/sce_sys/icon0.png new file mode 100644 index 00000000..5203ef32 Binary files /dev/null and b/engine/platform/psvita/sce_sys/icon0.png differ diff --git a/engine/platform/psvita/sce_sys/livearea/contents/bg.png b/engine/platform/psvita/sce_sys/livearea/contents/bg.png new file mode 100644 index 00000000..f1a02015 Binary files /dev/null and b/engine/platform/psvita/sce_sys/livearea/contents/bg.png differ diff --git a/engine/platform/psvita/sce_sys/livearea/contents/startup.png b/engine/platform/psvita/sce_sys/livearea/contents/startup.png new file mode 100644 index 00000000..c53af6f8 Binary files /dev/null and b/engine/platform/psvita/sce_sys/livearea/contents/startup.png differ diff --git a/engine/platform/psvita/sce_sys/livearea/contents/template.xml b/engine/platform/psvita/sce_sys/livearea/contents/template.xml new file mode 100644 index 00000000..1bfb8460 --- /dev/null +++ b/engine/platform/psvita/sce_sys/livearea/contents/template.xml @@ -0,0 +1,11 @@ + + + + + bg.png + + + + startup.png + + diff --git a/engine/platform/psvita/sys_psvita.c b/engine/platform/psvita/sys_psvita.c new file mode 100644 index 00000000..296ee64f --- /dev/null +++ b/engine/platform/psvita/sys_psvita.c @@ -0,0 +1,117 @@ +/* +sys_psvita.c - psvita 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 + +#define DATA_PATH "data/xash3d" + +/* HACKHACK: force-export stuff required by the dynamic libs */ + +extern void *__aeabi_idiv; +extern void *__aeabi_uidiv; +extern void *__aeabi_idivmod; +extern void *__aeabi_d2ulz; +extern void *__aeabi_ul2d; + +static const vrtld_export_t aux_exports[] = +{ + VRTLD_EXPORT_SYMBOL( __aeabi_d2ulz ), + VRTLD_EXPORT_SYMBOL( __aeabi_idiv ), + VRTLD_EXPORT_SYMBOL( __aeabi_idivmod ), + VRTLD_EXPORT_SYMBOL( __aeabi_uidiv ), + VRTLD_EXPORT_SYMBOL( __aeabi_ul2d ), + VRTLD_EXPORT_SYMBOL( ctime ), + VRTLD_EXPORT_SYMBOL( vasprintf ), + VRTLD_EXPORT_SYMBOL( vprintf ), + VRTLD_EXPORT_SYMBOL( printf ), + VRTLD_EXPORT_SYMBOL( putchar ), + VRTLD_EXPORT_SYMBOL( puts ), + VRTLD_EXPORT_SYMBOL( tolower ), + VRTLD_EXPORT_SYMBOL( toupper ), + VRTLD_EXPORT_SYMBOL( strchrnul ), + VRTLD_EXPORT_SYMBOL( rand ), + VRTLD_EXPORT_SYMBOL( srand ), +}; + +const vrtld_export_t *__vrtld_exports = aux_exports; +const size_t __vrtld_num_exports = sizeof( aux_exports ) / sizeof( *aux_exports ); + +/* end of export crap */ + +SceUInt32 sceUserMainThreadStackSize = 1 * 1024 * 1024; +unsigned int _newlib_heap_size_user = 128 * 1024 * 1024; + +void Platform_ShellExecute( const char *path, const char *parms ) +{ + Con_Reportf( S_WARN "Tried to shell execute ;%s; -- not supported\n", path ); +} + +void PSVita_Init( void ) +{ + char xashdir[1024] = { 0 }; + + // cd to the base dir immediately for library loading to work + if ( PSVita_GetBasePath( xashdir, sizeof( xashdir ) ) ) + { + chdir( xashdir ); + } + + sceCtrlSetSamplingModeExt( SCE_CTRL_MODE_ANALOG_WIDE ); + sceTouchSetSamplingState( SCE_TOUCH_PORT_FRONT, SCE_TOUCH_SAMPLING_STATE_START ); + scePowerSetArmClockFrequency( 444 ); + scePowerSetBusClockFrequency( 222 ); + scePowerSetGpuClockFrequency( 222 ); + scePowerSetGpuXbarClockFrequency( 166 ); + sceSysmoduleLoadModule( SCE_SYSMODULE_NET ); + + if ( vrtld_init( 0 ) < 0 ) + { + Sys_Error( "Could not init vrtld: %s\n", vrtld_dlerror( ) ); + } +} + +void PSVita_Shutdown( void ) +{ + vrtld_quit( ); +} + +qboolean PSVita_GetBasePath( char *buf, const size_t buflen ) +{ + // check if a xash3d folder exists on one of these drives + // default to the last one (ux0) + static const char *drives[] = { "uma0", "imc0", "ux0" }; + SceUID dir; + size_t i; + + for ( i = 0; i < sizeof( drives ) / sizeof( *drives ); ++i ) + { + Q_snprintf( buf, buflen, "%s:" DATA_PATH, drives[i] ); + dir = sceIoDopen( buf ); + if ( dir >= 0 ) + { + sceIoDclose( dir ); + return true; + } + } + + return false; +} diff --git a/engine/platform/sdl/sys_sdl.c b/engine/platform/sdl/sys_sdl.c index ed1c3661..75a8b613 100644 --- a/engine/platform/sdl/sys_sdl.c +++ b/engine/platform/sdl/sys_sdl.c @@ -69,6 +69,8 @@ void Platform_Init( void ) Wcon_CreateConsole(); // system console used by dedicated server or show fatal errors #elif XASH_POSIX Posix_Daemonize(); +#elif XASH_PSVITA + PSVita_Init(); #endif SDLash_InitCursors(); @@ -82,5 +84,7 @@ void Platform_Shutdown( void ) NSwitch_Shutdown(); #elif XASH_WIN32 Wcon_DestroyConsole(); +#elif XASH_PSVITA + PSVita_Shutdown(); #endif } diff --git a/engine/wscript b/engine/wscript index d650a457..7878f0f1 100644 --- a/engine/wscript +++ b/engine/wscript @@ -58,8 +58,20 @@ def configure(conf): if not conf.env.HAVE_SDL2: conf.fatal('SDL2 not availiable! Install switch-sdl2!') conf.define('XASH_SDL', 2) + # then remove them to avoid them getting linked to shared objects conf.env.LDFLAGS.remove('-lstdc++') conf.env.LDFLAGS.remove('-lm') + elif conf.env.DEST_OS == 'psvita': + # allow the SDL2 sanity check to complete properly by linking in some deps missing from the pkg-config file + extra_libs = ['-lstdc++', '-lm', '-lSceShaccCgExt', '-lSceShaccCg_stub', '-ltaihen_stub', '-lSceKernelDmacMgr_stub'] + conf.env.LDFLAGS += extra_libs + conf.load('sdl2') + if not conf.env.HAVE_SDL2: + conf.fatal('SDL2 not availiable! Install switch-sdl2!') + conf.define('XASH_SDL', 2) + # then remove them to avoid them getting linked to shared objects + for lib in extra_libs: + conf.env.LDFLAGS.remove(lib) elif conf.options.FBDEV_SW: # unused, XASH_LINUX without XASH_SDL gives fbdev & alsa support # conf.define('XASH_FBDEV', 1) @@ -135,7 +147,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' and bld.env.DEST_OS != 'nswitch': #posix + elif bld.env.DEST_OS not in ['dos', 'nswitch', 'psvita']: #posix libs += [ 'M', 'RT', 'PTHREAD', 'ASOUND'] if not bld.env.STATIC: libs += ['DL'] @@ -178,6 +190,32 @@ def build(bld): libs += [ 'SOLDER' ] source += bld.path.ant_glob(['platform/posix/*.c']) source += bld.path.ant_glob(['platform/nswitch/*.c']) + # HACK: link in the entirety of libstdc++ so that dynamic libs could use all of it without manual exporting + # we can't do this right away because std::filesystem will complain about not having pathconf(), + # which we have defined in sys_nswitch.c + bld.env.LDFLAGS += ['-Wl,--whole-archive', '-lstdc++', '-Wl,--no-whole-archive', '-lm'] + + if bld.env.DEST_OS == 'psvita': + libs += [ 'VRTLD' ] + source += bld.path.ant_glob(['platform/posix/*.c']) + source += bld.path.ant_glob(['platform/psvita/*.c']) + # HACK: link in the entirety of libstdc++ and -lm so that dynamic libs could use all of them without manual exporting + # also link in all the funky dependencies that aren't in SDL2's LDFLAGS + bld.env.LDFLAGS += [ + '-Wl,--whole-archive', + '-lstdc++', + '-lpthread', + '-Wl,--no-whole-archive', + '-lm', + '-lkubridge_stub', + '-lSceShaccCgExt', + '-lSceShaccCg_stub', + '-ltaihen_stub', + '-lSceKernelModulemgr_stub', + '-lSceSblSsMgr_stub', + '-lSceVshBridge_stub', + '-lSceKernelDmacMgr_stub' + ] # add client files if not bld.env.DEDICATED: @@ -189,12 +227,8 @@ def build(bld): includes = ['server', 'client', 'client/vgui' ] - # Switch has custom parameters - if bld.env.DEST_OS == 'nswitch': - # HACK: link in the entirety of libstdc++ so that dynamic libs could use all of it without manual exporting - # we can't do this right away because std::filesystem will complain about not having pathconf(), - # which we have defined in sys_nswitch.c - bld.env.LDFLAGS += ['-Wl,--whole-archive', '-lstdc++', '-Wl,--no-whole-archive', '-lm'] + # Switch and PSVita have custom parameters + if bld.env.DEST_OS in ['nswitch', 'psvita']: bld(source = source, target = 'xash', features = 'c cxxprogram', @@ -203,7 +237,9 @@ def build(bld): install_path = None, nro_install_path = bld.env.BINDIR, nacp = 'platform/nswitch/xash3d-fwgs.nacp', - icon = 'platform/nswitch/icon.jpg') + icon = 'platform/nswitch/icon.jpg', + sce_sys = 'platform/psvita/sce_sys', + ) else: if bld.env.SINGLE_BINARY: install_path = bld.env.BINDIR @@ -222,5 +258,5 @@ def build(bld): use = libs, install_path = install_path, subsystem = bld.env.MSVC_SUBSYSTEM, - rpath = '$ORIGIN' + rpath = '$ORIGIN', ) diff --git a/filesystem/dir.c b/filesystem/dir.c index 550754a5..b4b9987b 100644 --- a/filesystem/dir.c +++ b/filesystem/dir.c @@ -21,8 +21,10 @@ GNU General Public License for more details. #include #if XASH_POSIX #include +#if !XASH_PSVITA #include #endif +#endif #if XASH_LINUX #include #ifndef FS_CASEFOLD_FL // for compatibility with older distros diff --git a/filesystem/wscript b/filesystem/wscript index 362892b1..5be558ff 100644 --- a/filesystem/wscript +++ b/filesystem/wscript @@ -23,10 +23,18 @@ def configure(conf): def build(bld): bld(name = 'filesystem_includes', export_includes = '.') + + libs = [ 'filesystem_includes' ] + # on PSVita do not link any libraries that are already in the main executable, but add the includes target + if bld.env.DEST_OS == 'psvita': + libs += [ 'sdk_includes' ] + else: + libs += [ 'public' ] + bld.shlib(target = 'filesystem_stdio', features = 'cxx', source = bld.path.ant_glob(['*.c', '*.cpp']), - use = 'filesystem_includes public', + use = libs, install_path = bld.env.LIBDIR, subsystem = bld.env.MSVC_SUBSYSTEM) @@ -36,7 +44,7 @@ def build(bld): bld.program(features = 'test', source = 'tests/caseinsensitive.c', target = 'test_caseinsensitive', - use = 'filesystem_includes public DL', + use = libs + [ 'DL' ], rpath = '$ORIGIN', subsystem = bld.env.CONSOLE_SUBSYSTEM, install_path = None) diff --git a/public/build.c b/public/build.c index c54c887f..5e48f1a1 100644 --- a/public/build.c +++ b/public/build.c @@ -113,6 +113,8 @@ const char *Q_PlatformStringByID( const int platform ) return "irix"; case PLATFORM_NSWITCH: return "nswitch"; + case PLATFORM_PSVITA: + return "psvita"; } assert( 0 ); diff --git a/public/build.h b/public/build.h index ba1944e5..636d97a4 100644 --- a/public/build.h +++ b/public/build.h @@ -84,6 +84,7 @@ Then you can use another oneliner to query all variables: #undef XASH_WIN32 #undef XASH_X86 #undef XASH_NSWITCH +#undef XASH_PSVITA //================================================================ // @@ -130,12 +131,14 @@ Then you can use another oneliner to query all variables: #endif // TARGET_OS_IOS #elif defined __SWITCH__ #define XASH_NSWITCH 1 + #elif defined __vita__ + #define XASH_PSVITA 1 #else #error #endif #endif -#if XASH_ANDROID || defined XASH_IOS || defined XASH_NSWITCH +#if XASH_ANDROID || defined XASH_IOS || defined XASH_NSWITCH || defined XASH_PSVITA #define XASH_MOBILE_PLATFORM 1 #endif diff --git a/public/buildenums.h b/public/buildenums.h index 81f7516d..50266b1c 100644 --- a/public/buildenums.h +++ b/public/buildenums.h @@ -40,7 +40,8 @@ GNU General Public License for more details. #define PLATFORM_SERENITY 11 #define PLATFORM_IRIX 12 #define PLATFORM_NSWITCH 13 -#define PLATFORM_LINUX_UNKNOWN 14 +#define PLATFORM_PSVITA 14 +#define PLATFORM_LINUX_UNKNOWN 15 #if XASH_WIN32 #define XASH_PLATFORM PLATFORM_WIN32 @@ -70,6 +71,8 @@ GNU General Public License for more details. #define XASH_PLATFORM PLATFORM_IRIX #elif XASH_NSWITCH #define XASH_PLATFORM PLATFORM_NSWITCH +#elif XASH_PSVITA + #define XASH_PLATFORM PLATFORM_PSVITA #else #error #endif diff --git a/public/matrixlib.c b/public/matrixlib.c index 435474d5..522732ac 100644 --- a/public/matrixlib.c +++ b/public/matrixlib.c @@ -19,7 +19,7 @@ GNU General Public License for more details. #include "com_model.h" #include "xash3d_mathlib.h" -const matrix3x4 matrix3x4_identity = +const matrix3x4 m_matrix3x4_identity = { { 1, 0, 0, 0 }, // PITCH [forward], org[0] { 0, 1, 0, 0 }, // YAW [right] , org[1] @@ -295,7 +295,7 @@ void Matrix3x4_TransformAABB( const matrix3x4 world, const vec3_t mins, const ve VectorAdd( worldCenter, worldExtents, absmax ); } -const matrix4x4 matrix4x4_identity = +const matrix4x4 m_matrix4x4_identity = { { 1, 0, 0, 0 }, // PITCH { 0, 1, 0, 0 }, // YAW diff --git a/public/xash3d_mathlib.h b/public/xash3d_mathlib.h index 02c10c3e..55fe77ed 100644 --- a/public/xash3d_mathlib.h +++ b/public/xash3d_mathlib.h @@ -171,7 +171,7 @@ float ApproachVal( float target, float value, float speed ); // // matrixlib.c // -#define Matrix3x4_LoadIdentity( mat ) Matrix3x4_Copy( mat, matrix3x4_identity ) +#define Matrix3x4_LoadIdentity( mat ) Matrix3x4_Copy( mat, m_matrix3x4_identity ) #define Matrix3x4_Copy( out, in ) memcpy( out, in, sizeof( matrix3x4 )) void Matrix3x4_VectorTransform( const matrix3x4 in, const float v[3], float out[3] ); @@ -189,7 +189,7 @@ void Matrix3x4_OriginFromMatrix( const matrix3x4 in, float *out ); void Matrix3x4_AnglesFromMatrix( const matrix3x4 in, vec3_t out ); void Matrix3x4_Transpose( matrix3x4 out, const matrix3x4 in1 ); -#define Matrix4x4_LoadIdentity( mat ) Matrix4x4_Copy( mat, matrix4x4_identity ) +#define Matrix4x4_LoadIdentity( mat ) Matrix4x4_Copy( mat, m_matrix4x4_identity ) #define Matrix4x4_Copy( out, in ) memcpy( out, in, sizeof( matrix4x4 )) void Matrix4x4_VectorTransform( const matrix4x4 in, const float v[3], float out[3] ); @@ -234,8 +234,8 @@ int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p ); extern vec3_t vec3_origin; extern int boxpnt[6][4]; -extern const matrix3x4 matrix3x4_identity; -extern const matrix4x4 matrix4x4_identity; +extern const matrix3x4 m_matrix3x4_identity; +extern const matrix4x4 m_matrix4x4_identity; extern const float m_bytenormals[NUMVERTEXNORMALS][3]; #endif // XASH3D_MATHLIB_H diff --git a/ref/gl/wscript b/ref/gl/wscript index b8678e46..3416d00e 100644 --- a/ref/gl/wscript +++ b/ref/gl/wscript @@ -32,7 +32,12 @@ def configure(conf): conf.check_cc(lib='log') def build(bld): - libs = [ 'engine_includes', 'public', 'M' ] + libs = [ 'engine_includes' ] + # on PSVita do not link any libraries that are already in the main executable, but add the includes target + if bld.env.DEST_OS == 'psvita': + libs += [ 'sdk_includes' ] + else: + libs += [ 'public', 'M' ] source = bld.path.ant_glob(['*.c']) includes = '.' diff --git a/ref/soft/wscript b/ref/soft/wscript index e5cf7ca2..78de52d3 100644 --- a/ref/soft/wscript +++ b/ref/soft/wscript @@ -22,6 +22,13 @@ def configure(conf): conf.env.append_unique('DEFINES', 'REF_DLL') def build(bld): + libs = [ 'engine_includes' ] + # on PSVita do not link any libraries that are already in the main executable, but add the includes target + if bld.env.DEST_OS == 'psvita': + libs += [ 'sdk_includes' ] + else: + libs += [ 'public', 'M' ] + if bld.env.DEDICATED: return @@ -29,7 +36,7 @@ def build(bld): target = 'ref_soft', features = 'c', includes = '.', - use = 'engine_includes public M', + use = libs, install_path = bld.env.LIBDIR, subsystem = bld.env.MSVC_SUBSYSTEM ) diff --git a/scripts/waifulib/compiler_optimizations.py b/scripts/waifulib/compiler_optimizations.py index 110b0762..218e99fe 100644 --- a/scripts/waifulib/compiler_optimizations.py +++ b/scripts/waifulib/compiler_optimizations.py @@ -172,5 +172,10 @@ def get_optimization_flags(conf): if conf.env.DEST_OS == 'nswitch' and conf.options.BUILD_TYPE == 'debug': # enable remote debugger cflags.append('-DNSWITCH_DEBUG') + elif conf.env.DEST_OS == 'psvita': + # this optimization is broken in vitasdk + cflags.append('-fno-optimize-sibling-calls') + # remove fvisibility to allow everything to be exported by default + cflags.remove('-fvisibility=hidden') return cflags, linkflags diff --git a/scripts/waifulib/psvita.py b/scripts/waifulib/psvita.py new file mode 100644 index 00000000..a459e9c9 --- /dev/null +++ b/scripts/waifulib/psvita.py @@ -0,0 +1,110 @@ +# encoding: utf-8 +# psvita.py -- PSVita VPK task +# Copyright (C) 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. + +from waflib.Tools import ccroot +from waflib import * + +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 + +def configure(conf): + conf.find_program('vita-elf-create', var='ELF_CREATE') + conf.find_program('vita-make-fself', var='MAKE_FSELF') + conf.find_program('vita-mksfoex', var='MKSFOEX') + conf.find_program('vita-pack-vpk', var='PACKVPK') + +class mkvelf(Task.Task): + color = 'CYAN' + run_str = '${ELF_CREATE} -g ${YMLFILE} ${ELFFILE} ${TGT}' + +class mkfself(Task.Task): + color = 'CYAN' + run_str = '${MAKE_FSELF} ${VELFFILE} ${TGT}' + +class mksfoex(Task.Task): + color = 'CYAN' + # ATTRIBUTE2=12 enables the biggest extended memory mode + run_str = '${MKSFOEX} -s TITLE_ID=${TITLEID} -d ATTRIBUTE2=12 ${APPNAME} ${TGT}' + +class mkvpk(Task.Task): + color = 'CYAN' + run_str = '${PACKVPK} -s ${SFOFILE} -b ${FSELFFILE} -a ${SCESYS}=sce_sys ${TGT}' + +@TaskGen.feature('cxxprogram') +@TaskGen.after_method('apply_link') +def apply_velf(self): + elffile = self.link_task.outputs[0] + in_nodes = [elffile] + + ymlfile = elffile.change_ext('.yml') + velffile = elffile.change_ext('.velf') + out_nodes = [velffile, ymlfile] + + self.env.ELFFILE = str(elffile) + self.env.VELFFILE = str(velffile) + self.env.YMLFILE = str(ymlfile) + + self.velf_task = self.create_task('mkvelf', in_nodes) + self.velf_task.set_outputs(out_nodes) + +@TaskGen.feature('cxxprogram') +@TaskGen.after_method('apply_velf') +def apply_fself(self): + velffile = self.velf_task.outputs[0] + in_nodes = [velffile] + + fselffile = velffile.change_ext('.bin') + out_nodes = [fselffile] + + self.env.FSELFFILE = str(fselffile) + + self.fself_task = self.create_task('mkfself', in_nodes) + self.fself_task.set_outputs(out_nodes) + +@TaskGen.feature('cxxprogram') +@TaskGen.after_method('apply_fself') +def apply_sfo(self): + fselffile = self.fself_task.outputs[0] + in_nodes = [fselffile] + + sfofile = fselffile.change_ext('.sfo') + out_nodes = [sfofile] + + self.env.SFOFILE = str(sfofile) + + self.sfo_task = self.create_task('mksfoex', in_nodes) + self.sfo_task.set_outputs(out_nodes) + +@TaskGen.feature('cxxprogram') +@TaskGen.after_method('apply_sfo') +def apply_vpk(self): + fselffile = self.fself_task.outputs[0] + sfofile = self.sfo_task.outputs[0] + in_nodes = [fselffile, sfofile] + scesysdir = add_source_file(self, in_nodes, getattr(self, 'sce_sys', None)) + + vpkfile = sfofile.change_ext('.vpk') + out_nodes = [vpkfile] + + if scesysdir: self.env.SCESYS = str(scesysdir) + self.env.VPKFILE = str(vpkfile) + + self.vpk_task = self.create_task('mkvpk', in_nodes) + self.vpk_task.set_outputs(out_nodes) diff --git a/scripts/waifulib/xcompile.py b/scripts/waifulib/xcompile.py index 21631d38..8cd9d1a9 100644 --- a/scripts/waifulib/xcompile.py +++ b/scripts/waifulib/xcompile.py @@ -32,6 +32,8 @@ ANDROID_64BIT_API_MIN = 21 # minimal API level that supports 64-bit targets NSWITCH_ENVVARS = ['DEVKITPRO'] +PSVITA_ENVVARS = ['VITASDK'] + # This class does support ONLY r10e and r19c/r20 NDK class Android: ctx = None # waf context @@ -432,6 +434,73 @@ class NintendoSwitch: ldflags = [] # ['-lm', '-lstdc++'] return ldflags +class PSVita: + ctx = None # waf context + arch ='armeabi-v7a-hard' + vitasdk_dir = None + + def __init__(self, ctx): + self.ctx = ctx + + for i in PSVITA_ENVVARS: + self.vitasdk_dir = os.getenv(i) + if self.vitasdk_dir != None: + break + else: + ctx.fatal('Set %s environment variable pointing to the VitaSDK directory!' % + ' or '.join(PSVITA_ENVVARS)) + + def gen_toolchain_prefix(self): + return 'arm-vita-eabi-' + + def gen_gcc_toolchain_path(self): + return os.path.join(self.vitasdk_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 ar(self): + return self.gen_gcc_toolchain_path() + 'ar' + + def pkgconfig(self): + return self.gen_gcc_toolchain_path() + 'pkg-config' + + def cflags(self, cxx = False): + cflags = [] + # arch flags + cflags += ['-D__vita__', '-mtune=cortex-a9', '-mfpu=neon'] + # necessary linker flags + cflags += ['-Wl,-q', '-Wl,-z,nocopyreloc'] + # this optimization is broken in vitasdk + cflags += ['-fno-optimize-sibling-calls'] + # disable some ARM bullshit + cflags += ['-fsigned-char', '-Wno-attributes'] + # base include dir + cflags += ['-isystem %s/arm-vita-eabi/include' % self.vitasdk_dir] + # SDL include dir + cflags += ['-I%s/arm-vita-eabi/include/SDL2' % self.vitasdk_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 = ['-Wl,--hash-style=sysv', '-Wl,-q', '-Wl,-z,nocopyreloc', '-mtune=cortex-a9', '-mfpu=neon'] + return linkflags + + def ldflags(self): + ldflags = [] + return ldflags + def options(opt): xc = opt.add_option_group('Cross compile options') xc.add_option('--android', action='store', dest='ANDROID_OPTS', default=None, @@ -442,6 +511,8 @@ def options(opt): 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]') + xc.add_option('--psvita', action='store_true', dest='PSVITA', default = False, + help ='enable building for PlayStation Vita [default: %default]') def configure(conf): if conf.options.ANDROID_OPTS: @@ -507,10 +578,25 @@ def configure(conf): conf.env.HAVE_M = True conf.env.LIB_M = ['m'] conf.env.DEST_OS = 'nswitch' + elif conf.options.PSVITA: + conf.psvita = psvita = PSVita(conf) + conf.environ['CC'] = psvita.cc() + conf.environ['CXX'] = psvita.cxx() + conf.environ['STRIP'] = psvita.strip() + conf.environ['AR'] = psvita.ar() + conf.env.PKGCONFIG = psvita.pkgconfig() + conf.env.CFLAGS += psvita.cflags() + conf.env.CXXFLAGS += psvita.cflags(True) + conf.env.LINKFLAGS += psvita.linkflags() + conf.env.LDFLAGS += psvita.ldflags() + conf.env.HAVE_M = True + conf.env.LIB_M = ['m'] + conf.env.VRTLD = ['vrtld'] + conf.env.DEST_OS = 'psvita' conf.env.MAGX = conf.options.MAGX conf.env.MSVC_WINE = conf.options.MSVC_WINE - MACRO_TO_DESTOS = OrderedDict({ '__ANDROID__' : 'android', '__SWITCH__' : 'nswitch' }) + MACRO_TO_DESTOS = OrderedDict({ '__ANDROID__' : 'android', '__SWITCH__' : 'nswitch', '__vita__' : 'psvita' }) 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 03105e6c..c327ea8b 100644 --- a/wscript +++ b/wscript @@ -135,6 +135,9 @@ def configure(conf): if conf.options.NSWITCH: conf.load('nswitch') + if conf.options.PSVITA: + conf.load('psvita') + # HACKHACK: override msvc DEST_CPU value by something that we understand if conf.env.DEST_CPU == 'amd64': conf.env.DEST_CPU = 'x86_64' @@ -179,6 +182,14 @@ def configure(conf): conf.options.SINGLE_BINARY = True conf.options.NO_ASYNC_RESOLVE = True conf.options.USE_STBTT = True + elif conf.env.DEST_OS == 'psvita': + 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 + # we'll specify -fPIC by hand for shared libraries only + enforce_pic = False if conf.env.STATIC_LINKING: enforce_pic = False # PIC may break full static builds @@ -253,6 +264,16 @@ def configure(conf): conf.env.append_unique('LINKFLAGS_cshlib', ['-nostdlib', '-nostartfiles']) conf.env.append_unique('LINKFLAGS_cxxshlib', ['-nostdlib', '-nostartfiles']) + # same on the vita + if conf.env.DEST_OS == 'psvita': + conf.env.append_unique('CFLAGS_cshlib', ['-fPIC']) + conf.env.append_unique('CXXFLAGS_cxxshlib', ['-fPIC', '-fno-use-cxa-atexit']) + conf.env.append_unique('LINKFLAGS_cshlib', ['-nostdlib', '-Wl,--unresolved-symbols=ignore-all']) + conf.env.append_unique('LINKFLAGS_cxxshlib', ['-nostdlib', '-Wl,--unresolved-symbols=ignore-all']) + # set the metadata + conf.env.TITLEID = 'XASH10000' + conf.env.APPNAME = 'xash3d-fwgs' + # And here C++ flags starts to be treated separately cxxflags = list(cflags) if conf.env.COMPILER_CC != 'msvc' and not conf.options.DISABLE_WERROR: @@ -306,6 +327,8 @@ def configure(conf): 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 + elif conf.env.DEST_OS == 'psvita': + conf.check_cc(lib='vrtld', mandatory=True) else: conf.check_cc(lib='dl', mandatory=False)