diff --git a/regamedll/build.gradle b/regamedll/build.gradle index 4e46ebce..3486ce33 100644 --- a/regamedll/build.gradle +++ b/regamedll/build.gradle @@ -24,6 +24,7 @@ import org.apache.commons.compress.archivers.ArchiveInputStream apply plugin: 'cpp' apply plugin: IccCompilerPlugin +apply plugin: GccCompilerPlugin apply plugin: RegamedllPlayTestPlugin apply plugin: gradlecpp.CppUnitTestPlugin @@ -59,11 +60,11 @@ void createIntergrationTestTask(NativeBinarySpec b) { testDemos = project.configurations.regamedll_tests testFor = b - //inputs/outputs for up-to-date check + // inputs/outputs for up-to-date check inputs.files testDemos.files outputs.dir regamedllTestLogs - //dependencies on test executable + // dependencies on test executable if (unitTestTask) { dependsOn unitTestTask } @@ -90,6 +91,7 @@ void postEvaluate(NativeBinarySpec b) { void setupToolchain(NativeBinarySpec b) { + boolean useGcc = project.hasProperty("useGcc") boolean unitTestExecutable = b.component.name.endsWith('_tests') boolean regamedllFixes = b.flavor.name.contains('regamedllFixes') @@ -127,10 +129,13 @@ void setupToolchain(NativeBinarySpec b) } else if (cfg instanceof GccToolchainConfig) { - cfg.compilerOptions.pchConfig = new GccToolchainConfig.PrecompilerHeaderOptions( - enabled: true, - pchSourceSet: 'regamedll_pch' - ); + if (!useGcc) + { + cfg.compilerOptions.pchConfig = new GccToolchainConfig.PrecompilerHeaderOptions( + enabled: true, + pchSourceSet: 'regamedll_pch' + ); + } cfg.compilerOptions.languageStandard = 'c++14' cfg.defines([ @@ -145,8 +150,22 @@ void setupToolchain(NativeBinarySpec b) '_access' : 'access' ]) - cfg.linkerOptions.args '-no-opt-class-analysis' - cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-g0', '-fno-rtti', '-fno-exceptions' + if (useGcc) { + // Produce code optimized for the most common IA32/AMD64/EM64T processors. + // As new processors are deployed in the marketplace, the behavior of this option will change. + cfg.compilerOptions.args '-mtune=generic', '-msse3', '-Wno-write-strings', '-Wno-invalid-offsetof', '-fpermissive', '-fno-devirtualize' + } else { + cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp' + + // Not use c++ class hierarchy for analyze and resolve C++ virtual function calls at compile time. + // + // Example issue: + // Expected: FF .. call dword ptr + offset, pEntity->Spawn(); + // Got: E8 .. call CBaseEntity::Spawn(); + cfg.linkerOptions.args '-qno-opt-class-analysis' + } + + cfg.compilerOptions.args '-g0', '-fno-rtti', '-fno-exceptions' cfg.projectLibpath(project, '/lib/linux32') cfg.extraLibs 'dl', 'm', 'stdc++', 'aelf32' } @@ -243,7 +262,10 @@ model { toolChains { visualCpp(VisualCpp) { } - icc(Icc) { + if (project.hasProperty("useGcc")) { + gcc(Gcc) + } else { + icc(Icc) } } diff --git a/regamedll/common/mathlib.h b/regamedll/common/mathlib.h index 52723986..410d1de9 100644 --- a/regamedll/common/mathlib.h +++ b/regamedll/common/mathlib.h @@ -29,7 +29,7 @@ #pragma once #ifdef PLAY_GAMEDLL -// NOTE: In some cases we need high precision of floating-point, +// NOTE: In some cases we need high precision of floating-point, // so use double instead of float, otherwise unittest will fail typedef double real_t; #else @@ -85,6 +85,7 @@ const T& clamp(const T& a, const T& min, const T& max) { return (a > max) ? max #define clamp(val, min, max) (((val) > (max)) ? (max) : (((val) < (min)) ? (min) : (val))) #endif // __cplusplus +#ifdef HAVE_SSE inline float M_sqrt(float value) { return _mm_cvtss_f32(_mm_sqrt_ss(_mm_load_ss(&value))); } @@ -93,12 +94,14 @@ inline double M_sqrt(double value) { auto v = _mm_load_sd(&value); return _mm_cvtsd_f64(_mm_sqrt_sd(v, v)); } +#endif template inline double M_sqrt(T value) { return sqrt(value); } +#ifdef HAVE_SSE inline float M_min(float a, float b) { return _mm_cvtss_f32(_mm_min_ss(_mm_load_ss(&a), _mm_load_ss(&b))); } @@ -106,12 +109,14 @@ inline float M_min(float a, float b) { inline double M_min(double a, double b) { return _mm_cvtsd_f64(_mm_min_sd(_mm_load_sd(&a), _mm_load_sd(&b))); } +#endif template inline T M_min(T a, T b) { return min(a, b); } +#ifdef HAVE_SSE inline float M_max(float a, float b) { return _mm_cvtss_f32(_mm_max_ss(_mm_load_ss(&a), _mm_load_ss(&b))); } @@ -119,12 +124,14 @@ inline float M_max(float a, float b) { inline double M_max(double a, double b) { return _mm_cvtsd_f64(_mm_max_sd(_mm_load_sd(&a), _mm_load_sd(&b))); } +#endif template inline T M_max(T a, T b) { return max(a, b); } +#ifdef HAVE_SSE inline float M_clamp(float a, float min, float max) { return _mm_cvtss_f32(_mm_min_ss(_mm_max_ss(_mm_load_ss(&a), _mm_load_ss(&min)), _mm_load_ss(&max))); } @@ -132,6 +139,7 @@ inline float M_clamp(float a, float min, float max) { inline double M_clamp(double a, double min, double max) { return _mm_cvtsd_f64(_mm_min_sd(_mm_max_sd(_mm_load_sd(&a), _mm_load_sd(&min)), _mm_load_sd(&max))); } +#endif template inline T M_clamp(T a, T min, T max) { diff --git a/regamedll/dlls/animation.cpp b/regamedll/dlls/animation.cpp index 78b3ff67..e8f0ab0f 100644 --- a/regamedll/dlls/animation.cpp +++ b/regamedll/dlls/animation.cpp @@ -527,7 +527,7 @@ C_DLLEXPORT int Server_GetBlendingInterface(int version, struct sv_blending_inte return 1; } -#ifdef REGAMEDLL_FIXES // SSE2 version +#if defined(REGAMEDLL_FIXES) && defined(HAVE_SSE) // SSE2 version void AngleQuaternion(vec_t *angles, vec_t *quaternion) { static const ALIGN16_BEG size_t ps_signmask[4] ALIGN16_END = { 0x80000000, 0, 0x80000000, 0 }; diff --git a/regamedll/dlls/player.cpp b/regamedll/dlls/player.cpp index e4325422..e54521a7 100644 --- a/regamedll/dlls/player.cpp +++ b/regamedll/dlls/player.cpp @@ -8296,6 +8296,9 @@ void CBasePlayer::ClientCommand(const char *cmd, const char *arg1, const char *a auto pEntity = ENT(pev); +#ifdef NO_AMXX_HACKS // a1ba: not needed for non-x86 port + ::ClientCommand_(pEntity); +#else // NO_AMXX_HACKS // NOTE: force __cdecl to allow cstrike amxx module to hook ClientCommand #if defined _MSC_VER || defined __INTEL_COMPILER __asm @@ -8307,13 +8310,13 @@ void CBasePlayer::ClientCommand(const char *cmd, const char *arg1, const char *a #else asm volatile ( "pushl %0\n\t" - "call %1\n\t" - "addl %%esp, $4\n\t" - :: - "g" (pEntity), - "g" (ClientCommand_), + "call *%1\n\t" + "addl $4, %%esp\n\t" + : /* no outputs */ + : "g" (pEntity), "g" (ClientCommand_) ); #endif // _MSC_VER || defined __INTEL_COMPILER +#endif // NO_AMXX_HACKS UseBotArgs = false; } diff --git a/regamedll/dlls/saverestore.cpp b/regamedll/dlls/saverestore.cpp index 3a03b562..0522ce8f 100644 --- a/regamedll/dlls/saverestore.cpp +++ b/regamedll/dlls/saverestore.cpp @@ -160,6 +160,28 @@ void EntvarsKeyvalue(entvars_t *pev, KeyValueData *pkvd) } } +const int CSaveRestoreBuffer::m_Sizes[] = +{ + sizeof(float), // FIELD_FLOAT + sizeof(int), // FIELD_STRING + sizeof(int), // FIELD_ENTITY + sizeof(int), // FIELD_CLASSPTR + sizeof(int), // FIELD_EHANDLE + sizeof(int), // FIELD_entvars_t + sizeof(int), // FIELD_EDICT + sizeof(float) * 3, // FIELD_VECTOR + sizeof(float) * 3, // FIELD_POSITION_VECTOR + sizeof(int *), // FIELD_POINTER + sizeof(int), // FIELD_INTEGER + sizeof(int *), // FIELD_FUNCTION + sizeof(int), // FIELD_BOOLEAN + sizeof(short), // FIELD_SHORT + sizeof(char), // FIELD_CHARACTER + sizeof(float), // FIELD_TIME + sizeof(int), // FIELD_MODELNAME + sizeof(int), // FIELD_SOUNDNAME +}; + CSaveRestoreBuffer::CSaveRestoreBuffer() { m_pData = nullptr; diff --git a/regamedll/dlls/saverestore.h b/regamedll/dlls/saverestore.h index be5d429c..8da3fdb5 100644 --- a/regamedll/dlls/saverestore.h +++ b/regamedll/dlls/saverestore.h @@ -85,26 +85,7 @@ public: unsigned short TokenHash(const char *pszToken); protected: - static constexpr int m_Sizes[] = { - sizeof(float), // FIELD_FLOAT - sizeof(int), // FIELD_STRING - sizeof(int), // FIELD_ENTITY - sizeof(int), // FIELD_CLASSPTR - sizeof(int), // FIELD_EHANDLE - sizeof(int), // FIELD_entvars_t - sizeof(int), // FIELD_EDICT - sizeof(float) * 3, // FIELD_VECTOR - sizeof(float) * 3, // FIELD_POSITION_VECTOR - sizeof(int *), // FIELD_POINTER - sizeof(int), // FIELD_INTEGER - sizeof(int *), // FIELD_FUNCTION - sizeof(int), // FIELD_BOOLEAN - sizeof(short), // FIELD_SHORT - sizeof(char), // FIELD_CHARACTER - sizeof(float), // FIELD_TIME - sizeof(int), // FIELD_MODELNAME - sizeof(int), // FIELD_SOUNDNAME - }; + static const int m_Sizes[]; SAVERESTOREDATA *m_pData; void BufferRewind(int size); diff --git a/regamedll/dlls/util.h b/regamedll/dlls/util.h index 3066eecc..90465823 100644 --- a/regamedll/dlls/util.h +++ b/regamedll/dlls/util.h @@ -323,7 +323,8 @@ inline T *UTIL_FindEntityInSphere(T *pStartEntity, const Vector &vecCenter, floa pentEntity = FIND_ENTITY_IN_SPHERE(pentEntity, vecCenter, flRadius); if (!FNullEnt(pentEntity)) { - return (T *)CBaseEntity::Instance(pentEntity); + // a1ba: can't use CBaseEntity::Instance here, because circular dependency in cbase.h + return GET_PRIVATE(pentEntity); } return nullptr; diff --git a/regamedll/engine/osconfig.h b/regamedll/engine/osconfig.h index f9bc5835..1077e7d1 100644 --- a/regamedll/engine/osconfig.h +++ b/regamedll/engine/osconfig.h @@ -47,6 +47,12 @@ #include #include +// enable SSE code only if it's enabled in compiler options +#if defined(__SSE__) || defined(__SSE2__) || defined(_M_IX86_FP) || defined(_M_AMD64) || defined(_M_X64) + // #error "SSE enabled" + #define HAVE_SSE +#endif + #ifdef _WIN32 // WINDOWS #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include @@ -87,9 +93,10 @@ #include #include +#ifdef HAVE_SSE #include #include - +#endif // HAVE_SSE #ifdef _WIN32 // WINDOWS // Define __func__ on VS less than 2015 @@ -97,6 +104,8 @@ #define __func__ __FUNCTION__ #endif + // We'll not use __func__ on windows because we want 'A::foo' instead of 'foo' + #define __FUNC__ __FUNCTION__ #define _CRT_SECURE_NO_WARNINGS #define WIN32_LEAN_AND_MEAN @@ -151,6 +160,7 @@ typedef unsigned int UNINT32; #define FASTCALL + #define __FUNC__ __func__ #define CDECL __attribute__ ((cdecl)) #define STDCALL __attribute__ ((stdcall)) #define HIDDEN __attribute__((visibility("hidden"))) diff --git a/regamedll/regamedll/hookchains_impl.cpp b/regamedll/regamedll/hookchains_impl.cpp index 2ba024ce..f9a98228 100644 --- a/regamedll/regamedll/hookchains_impl.cpp +++ b/regamedll/regamedll/hookchains_impl.cpp @@ -49,11 +49,11 @@ bool AbstractHookChainRegistry::findHook(void* hookFunc) const void AbstractHookChainRegistry::addHook(void* hookFunc, int priority) { if (!hookFunc) { - Sys_Error("%s: Parameter hookFunc can't be a nullptr", __func__); + Sys_Error("%s: Parameter hookFunc can't be a nullptr", __FUNC__); } if (findHook(hookFunc)) { - Sys_Error("%s: The same handler can't be used twice on the hookchain.", __func__); + Sys_Error("%s: The same handler can't be used twice on the hookchain.", __FUNC__); } for (auto i = 0; i < MAX_HOOKS_IN_CHAIN; i++) @@ -72,7 +72,7 @@ void AbstractHookChainRegistry::addHook(void* hookFunc, int priority) } if (m_NumHooks >= MAX_HOOKS_IN_CHAIN) { - Sys_Error("%s: MAX_HOOKS_IN_CHAIN limit hit", __func__); + Sys_Error("%s: MAX_HOOKS_IN_CHAIN limit hit", __FUNC__); } m_NumHooks++; diff --git a/regamedll/regamedll/hookchains_impl.h b/regamedll/regamedll/hookchains_impl.h index 96452b4a..f3a4a7af 100644 --- a/regamedll/regamedll/hookchains_impl.h +++ b/regamedll/regamedll/hookchains_impl.h @@ -54,7 +54,7 @@ public: IHookChainImpl(void** hooks, origfunc_t orig) : m_Hooks(hooks), m_OriginalFunc(orig) { if (orig == nullptr && !is_void(orig)) - Sys_Error("%s: Non-void HookChain without original function.", __func__); + Sys_Error("%s: Non-void HookChain without original function.", __FUNC__); } virtual ~IHookChainImpl() {} @@ -90,7 +90,7 @@ public: IHookChainClassImpl(void** hooks, origfunc_t orig) : m_Hooks(hooks), m_OriginalFunc(orig) { if (orig == nullptr && !is_void(orig)) - Sys_Error("%s: Non-void HookChain without original function.", __func__); + Sys_Error("%s: Non-void HookChain without original function.", __FUNC__); } virtual ~IHookChainClassImpl() {} @@ -126,7 +126,7 @@ public: IHookChainClassEmptyImpl(void** hooks, origfunc_t orig, t_class *object) : m_Hooks(hooks), m_OriginalFunc(orig), m_Object(object) { if (orig == nullptr && !is_void(orig)) - Sys_Error("%s: Non-void HookChain without original function.", __func__); + Sys_Error("%s: Non-void HookChain without original function.", __FUNC__); } virtual ~IHookChainClassEmptyImpl() {} diff --git a/regamedll/regamedll/precompiled.h b/regamedll/regamedll/precompiled.h index f3799aea..2b9aa3df 100644 --- a/regamedll/regamedll/precompiled.h +++ b/regamedll/regamedll/precompiled.h @@ -34,7 +34,9 @@ #include "basetypes.h" #include "archtypes.h" +#ifdef HAVE_SSE #include "sse_mathfun.h" +#endif #include "asmlib.h" #include "MemPool.h" diff --git a/regamedll/regamedll/sse_mathfun.cpp b/regamedll/regamedll/sse_mathfun.cpp index 3e59aa8f..52f9b5ac 100644 --- a/regamedll/regamedll/sse_mathfun.cpp +++ b/regamedll/regamedll/sse_mathfun.cpp @@ -31,6 +31,8 @@ misrepresented as being the original software. #include "precompiled.h" +#ifdef HAVE_SSE + /* natural logarithm computed for 4 simultaneous float return NaN for x <= 0 */ @@ -445,3 +447,4 @@ void sincos_ps(v4sf x, v4sf *s, v4sf *c) { *s = _mm_xor_ps(xmm1, sign_bit_sin); *c = _mm_xor_ps(xmm2, sign_bit_cos); } +#endif // HAVE_SSE diff --git a/shared.gradle b/shared.gradle index e9690f20..c25cc848 100644 --- a/shared.gradle +++ b/shared.gradle @@ -8,6 +8,7 @@ import org.gradle.nativeplatform.toolchain.VisualCpp apply from: 'shared_msvc.gradle' apply from: 'shared_icc.gradle' +apply from: 'shared_gcc.gradle' rootProject.ext.createToolchainConfig = { NativeBinarySpec bin -> BinaryKind binaryKind @@ -37,6 +38,10 @@ rootProject.ext.createToolchainConfig = { NativeBinarySpec bin -> { return rootProject.createIccConfig(releaseBuild, binaryKind) } + else if (bin.toolChain instanceof Gcc) + { + return rootProject.createGccConfig(releaseBuild, binaryKind) + } else { throw new RuntimeException("Unknown native toolchain: ${bin.toolChain.class.name}") diff --git a/shared_gcc.gradle b/shared_gcc.gradle new file mode 100644 index 00000000..03654bc8 --- /dev/null +++ b/shared_gcc.gradle @@ -0,0 +1,55 @@ +import org.doomedsociety.gradlecpp.cfg.BinaryKind +import org.doomedsociety.gradlecpp.gcc.GccToolchainConfig +import org.doomedsociety.gradlecpp.gcc.OptimizationLevel + +rootProject.ext.createGccConfig = { boolean release, BinaryKind binKind -> + GccToolchainConfig cfg + if (release) { + cfg = new GccToolchainConfig( + compilerOptions: new GccToolchainConfig.CompilerOptions( + optimizationLevel: OptimizationLevel.LEVEL_3, + stackProtector: false, + noBuiltIn: true, + positionIndependentCode: false, + extraDefines: [ + '_GLIBCXX_USE_CXX11_ABI': 0, + ] + ), + + linkerOptions: new GccToolchainConfig.LinkerOptions( + stripSymbolTable: false, + staticLibGcc: false, + staticLibStdCpp: false, + ), + + librarianOptions: new GccToolchainConfig.LibrarianOptions( + + ) + ) + } else { + //debug + cfg = new GccToolchainConfig( + compilerOptions: new GccToolchainConfig.CompilerOptions( + optimizationLevel: OptimizationLevel.DISABLE, + stackProtector: true, + noBuiltIn: true, + extraDefines: [ + '_GLIBCXX_USE_CXX11_ABI': 0, + ] + ), + + linkerOptions: new GccToolchainConfig.LinkerOptions( + stripSymbolTable: false, + staticLibGcc: false, + staticLibStdCpp: false, + ), + + librarianOptions: new GccToolchainConfig.LibrarianOptions( + + ) + ) + } + + cfg.singleDefines('LINUX', '_LINUX') + return cfg +} diff --git a/shared_icc.gradle b/shared_icc.gradle index afa5aaec..424750f9 100644 --- a/shared_icc.gradle +++ b/shared_icc.gradle @@ -60,5 +60,6 @@ rootProject.ext.createIccConfig = { boolean release, BinaryKind binKind -> ) } + cfg.singleDefines('LINUX', '_LINUX') return cfg }