diff --git a/CMakeLists.txt b/CMakeLists.txt index 319f1ff3..77357714 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -186,6 +186,10 @@ else() add_definitions(-D_CRT_SILENCE_NONCONFORMING_TGMATH_H) endif() +if(VITA) + add_compile_options(-fno-use-cxa-atexit) +endif() + check_include_file("tgmath.h" HAVE_TGMATH_H) if(HAVE_TGMATH_H) if(NOT MSVC) diff --git a/README.md b/README.md index 8797f054..e1fbcccf 100644 --- a/README.md +++ b/README.md @@ -270,6 +270,32 @@ make -j ./waf build ``` +## PlayStation Vita + +### Prerequisites + +1. Set up [VitaSDK](https://vitasdk.org/). +2. Install [vita-rtld](https://github.com/fgsfdsfgs/vita-rtld): + ``` + git clone https://github.com/fgsfdsfgs/vita-rtld.git && cd vita-rtld + mkdir build && cd build + cmake -DCMAKE_BUILD_TYPE=Release .. + make -j2 install + ``` + +### Building with waf: +``` +./waf configure -T release --psvita +./waf build +``` + +### Building with CMake: +``` +mkdir build && cd build +cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE="$VITASDK/share/vita.toolchain.cmake" -DCMAKE_PROJECT_HLSDK-PORTABLE_INCLUDE="$VITASDK/share/vrtld_shim.cmake" .. +make -j +``` + ## Other platforms Building on other architectures (e.g x86_64 or arm) and POSIX-compliant OSes (e.g. FreeBSD) is supported. diff --git a/cmake/LibraryNaming.cmake b/cmake/LibraryNaming.cmake index 156ab672..3c2b8968 100644 --- a/cmake/LibraryNaming.cmake +++ b/cmake/LibraryNaming.cmake @@ -43,6 +43,7 @@ check_symbol_exists(XASH_WIN32 "build.h" XASH_WIN32) check_symbol_exists(XASH_WIN64 "build.h" XASH_WIN64) check_symbol_exists(XASH_X86 "build.h" XASH_X86) check_symbol_exists(XASH_NSWITCH "build.h" XASH_NSWITCH) +check_symbol_exists(XASH_PSVITA "build.h" XASH_PSVITA) unset(CMAKE_REQUIRED_INCLUDES) # engine/common/build.c @@ -66,6 +67,8 @@ elseif(XASH_SERENITY) set(BUILDOS "serenityos") elseif(XASH_NSWITCH) set(BUILDOS "nswitch") +elseif(XASH_PSVITA) + set(BUILDOS "psvita") else() message(SEND_ERROR "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug") endif() diff --git a/public/build.h b/public/build.h index 521e4675..4e4fe110 100644 --- a/public/build.h +++ b/public/build.h @@ -80,6 +80,7 @@ For more information, please refer to #undef XASH_WIN64 #undef XASH_X86 #undef XASH_NSWITCH +#undef XASH_PSVITA //================================================================ // @@ -101,6 +102,10 @@ For more information, please refer to #define XASH_NSWITCH 1 #define XASH_LITTLE_ENDIAN 1 #define XASH_POSIX 1 +#elif defined __vita__ + #define XASH_PSVITA 1 + #define XASH_LITTLE_ENDIAN 1 + #define XASH_POSIX 1 #elif defined(__linux__) #define XASH_LINUX 1 #if defined(__ANDROID__) @@ -139,7 +144,7 @@ For more information, please refer to #error "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug" #endif -#if defined XASH_ANDROID || defined XASH_IOS || defined XASH_NSWITCH +#if defined XASH_ANDROID || defined XASH_IOS || defined XASH_NSWITCH || defined XASH_PSVITA #define XASH_MOBILE_PLATFORM 1 #endif diff --git a/scripts/waifulib/compiler_optimizations.py b/scripts/waifulib/compiler_optimizations.py index e964c812..688c6f55 100644 --- a/scripts/waifulib/compiler_optimizations.py +++ b/scripts/waifulib/compiler_optimizations.py @@ -30,7 +30,7 @@ compiler_optimizations.CFLAGS['gottagofast'] = { } ''' -VALID_BUILD_TYPES = ['fastnative', 'fast', 'release', 'debug', 'nooptimize', 'sanitize', 'none'] +VALID_BUILD_TYPES = ['fastnative', 'fast', 'release', 'debug', 'sanitize', 'msan', 'none'] LINKFLAGS = { 'common': { @@ -38,9 +38,14 @@ LINKFLAGS = { 'gcc': ['-Wl,--no-undefined'], 'owcc': ['-Wl,option stack=512k'] }, + 'msan': { + 'clang': ['-fsanitize=memory', '-pthread'], + 'default': ['NO_MSAN_HERE'] + }, 'sanitize': { 'clang': ['-fsanitize=undefined', '-fsanitize=address', '-pthread'], 'gcc': ['-fsanitize=undefined', '-fsanitize=address', '-pthread'], + 'msvc': ['/SAFESEH:NO'] }, 'debug': { 'msvc': ['/INCREMENTAL', '/SAFESEH:NO'] @@ -50,7 +55,7 @@ LINKFLAGS = { CFLAGS = { 'common': { # disable thread-safe local static initialization for C++11 code, as it cause crashes on Windows XP - 'msvc': ['/D_USING_V110_SDK71_', '/FS', '/Zc:threadSafeInit-', '/MT'], + 'msvc': ['/D_USING_V110_SDK71_', '/FS', '/Zc:threadSafeInit-', '/MT', '/MP', '/Zc:__cplusplus'], 'clang': ['-g', '-gdwarf-2', '-fvisibility=hidden', '-fno-threadsafe-statics'], 'gcc': ['-g', '-fvisibility=hidden'], 'owcc': ['-fno-short-enum', '-ffloat-store', '-g3'] @@ -80,16 +85,16 @@ CFLAGS = { 'owcc': ['-O0', '-fno-omit-frame-pointer', '-funwind-tables', '-fno-omit-leaf-frame-pointer'], 'default': ['-O0'] }, + 'msan': { + 'clang': ['-O2', '-g', '-fno-omit-frame-pointer', '-fsanitize=memory', '-pthread'], + 'default': ['NO_MSAN_HERE'] + }, 'sanitize': { - 'msvc': ['/Od', '/RTC1', '/Zi'], - 'gcc': ['-Og', '-fsanitize=undefined', '-fsanitize=address', '-pthread'], + 'msvc': ['/Od', '/RTC1', '/Zi', '/fsanitize=address'], + 'gcc': ['-O0', '-fsanitize=undefined', '-fsanitize=address', '-pthread'], 'clang': ['-O0', '-fsanitize=undefined', '-fsanitize=address', '-pthread'], 'default': ['-O0'] }, - 'nooptimize': { - 'msvc': ['/Od', '/Zi'], - 'default': ['-O0'] - } } LTO_CFLAGS = { @@ -164,4 +169,11 @@ 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') + elif conf.env.DEST_OS == 'psvita': + # this optimization is broken in vitasdk + cflags.append('-fno-optimize-sibling-calls') + return cflags, linkflags diff --git a/scripts/waifulib/library_naming.py b/scripts/waifulib/library_naming.py index 3709bc76..b8985c92 100644 --- a/scripts/waifulib/library_naming.py +++ b/scripts/waifulib/library_naming.py @@ -62,6 +62,7 @@ DEFINES = [ 'XASH_WIN64', 'XASH_X86', 'XASH_NSWITCH', +'XASH_PSVITA', ] def configure(conf): @@ -95,6 +96,8 @@ def configure(conf): buildos = "serenityos" elif conf.env.XASH_NSWITCH: buildos = "nswitch" + elif conf.env.XASH_PSVITA: + buildos = "psvita" else: conf.fatal("Place your operating system name in build.h and library_naming.py!\n" "If this is a mistake, try to fix conditions above and report a bug") diff --git a/scripts/waifulib/xcompile.py b/scripts/waifulib/xcompile.py index 51d8ec87..08e90228 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 @@ -399,7 +401,7 @@ class NintendoSwitch: return self.gen_gcc_toolchain_path() + 'strip' def pkgconfig(self): - # counter-intuitively, this motherfucker is in portlibs/switch/bin + # 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): @@ -410,10 +412,8 @@ class NintendoSwitch: 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: - # while these are supported, they could fuck up the crappy dynamic linker - cflags += ['-fno-exceptions', '-fno-rtti'] - # the game wants GNU extensions cflags += ['-std=gnu++17', '-D_GNU_SOURCE'] else: cflags += ['-std=gnu11', '-D_GNU_SOURCE'] @@ -434,6 +434,70 @@ 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 += ['-fno-short-enums', '-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] + 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'] + # enforce no-short-enums again + linkflags += ['-Wl,-no-enum-size-warning', '-fno-short-enums'] + 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, @@ -444,6 +508,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: @@ -509,10 +575,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 28f80df5..f125a186 100644 --- a/wscript +++ b/wscript @@ -76,7 +76,7 @@ def configure(conf): if conf.env.DEST_OS == 'android': conf.options.GOLDSRC = conf.env.GOLDSRC = False conf.env.SERVER_NAME = 'server' # can't be any other name, until specified - elif conf.env.DEST_OS == 'nswitch': + elif conf.env.DEST_OS in ['nswitch', 'psvita']: conf.options.GOLDSRC = conf.env.GOLDSRC = False if conf.env.MAGX: @@ -150,12 +150,19 @@ def configure(conf): cflags += conf.filter_cflags(compiler_optional_flags + c_compiler_optional_flags, cflags) cxxflags += conf.filter_cxxflags(compiler_optional_flags, cflags) - # on the Switch, allow undefined symbols by default, which is needed for libsolder to work + # on the Switch and the PSVita, allow undefined symbols by default, + # which is needed for the dynamic loaders to work # 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']) + elif conf.env.DEST_OS == 'psvita': + linkflags.remove('-Wl,--no-undefined') + 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']) conf.env.append_unique('CFLAGS', cflags) conf.env.append_unique('CXXFLAGS', cxxflags)