From 9ddf557948f9fb681d91fc9fe4e1710fa6b11f2c Mon Sep 17 00:00:00 2001 From: Allusive <154700875+AllusiveWheat@users.noreply.github.com> Date: Thu, 20 Aug 2026 19:33:16 -0700 Subject: [PATCH] Default compile constants to 0 if not defined (#932) * default ifdef constants to 0 --------- Co-authored-by: Will <39478251+sonny-tel@users.noreply.github.com> Co-authored-by: Will <39478251+VITALISED@users.noreply.github.com> --- primedev/squirrel/squirrel.cpp | 50 ++++++++++++++++++- .../squirrel_re/squirrel/sqcompiler.h | 4 +- .../languages/squirrel_re/squirrel/sqstate.h | 4 +- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/primedev/squirrel/squirrel.cpp b/primedev/squirrel/squirrel.cpp index e96a7550..dddcf2fa 100644 --- a/primedev/squirrel/squirrel.cpp +++ b/primedev/squirrel/squirrel.cpp @@ -20,7 +20,7 @@ AUTOHOOK_INIT() SquirrelManagerManager g_pSquirrel; - +thread_local SQCompiler* pIfDirectiveCompiler; std::shared_ptr getSquirrelLoggerByContext(ScriptContext context) { switch (context) @@ -326,9 +326,43 @@ bool IsUIVM(ScriptContext context, HSQUIRRELVM pSqvm) return ScriptContext(pSqvm->sharedState->cSquirrelVM->vmContext) == ScriptContext::UI; } +template std::int64_t (*SQCompiler_ParseDirective)(SQCompiler* pCompiler); +template std::int64_t __fastcall SQCompiler_ParseDirectiveHook(SQCompiler* pCompiler) +{ + SQCompiler* pPreviousCompiler = pIfDirectiveCompiler; + pIfDirectiveCompiler = pCompiler; + const std::int64_t result = SQCompiler_ParseDirective(pCompiler); + pIfDirectiveCompiler = pPreviousCompiler; + return result; +} + +template +bool (*SQCompiler_ResolveLocalOrConstant)(void* pFunctionState, SQObject* pIdentifier, SQObject* pValue, std::uintptr_t* pType); +template +bool __fastcall SQCompiler_ResolveLocalOrConstantHook(void* pFunctionState, SQObject* pIdentifier, SQObject* pValue, std::uintptr_t* pType) +{ + if (SQCompiler_ResolveLocalOrConstant(pFunctionState, pIdentifier, pValue, pType)) + return true; + // if we're not in a preprocessor directive, we don't want to resolve the identifier as a constant + if (!pIfDirectiveCompiler || pIfDirectiveCompiler->preprocessorDepth <= 0) + return false; + + // evaluate to 0 if we're doing directives because #if with a compile error is stupid + pValue->_Type = OT_INTEGER; + pValue->structNumber = 0; + pValue->_VAL.as64Integer = 0; + constexpr std::uint32_t typeHashMagic = 0x9E3779B9u - 0x61C88647u; + constexpr std::uint32_t typeHash = typeHashMagic * static_cast(OT_INTEGER); + constexpr std::size_t typeIndex = (typeHash / 0xF499u) & 0x3FFFu; + SQSharedState* pSharedState = pIfDirectiveCompiler->pSQVM->sharedState; + *pType = reinterpret_cast(&pSharedState->compilerTypeDescriptors[typeIndex]); + return true; +} + template void* (*sq_compiler_create)(HSQUIRRELVM sqvm, void* a2, void* a3, SQBool bShouldThrowError); template void* __fastcall sq_compiler_createHook(HSQUIRRELVM sqvm, void* a2, void* a3, SQBool bShouldThrowError) { + pIfDirectiveCompiler = nullptr; // store whether errors generated from this compile should be fatal if (IsUIVM(context, sqvm)) g_pSquirrel[ScriptContext::UI]->m_bFatalCompilationErrors = bShouldThrowError; @@ -789,6 +823,13 @@ ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (CModule module)) MAKEHOOK(module.Offset(0x8AD0), &sq_compiler_createHook, &sq_compiler_create); + MAKEHOOK( + module.Offset(0x58590), &SQCompiler_ParseDirectiveHook, &SQCompiler_ParseDirective); + MAKEHOOK( + module.Offset(0x65CB0), + &SQCompiler_ResolveLocalOrConstantHook, + &SQCompiler_ResolveLocalOrConstant); + MAKEHOOK(module.Offset(0x12B00), &SQPrintHook, &SQPrint); MAKEHOOK(module.Offset(0x12BA0), &SQPrintHook, &SQPrint); @@ -868,6 +909,13 @@ ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (CModule module)) MAKEHOOK(module.Offset(0x8AA0), &sq_compiler_createHook, &sq_compiler_create); + MAKEHOOK( + module.Offset(0x58530), &SQCompiler_ParseDirectiveHook, &SQCompiler_ParseDirective); + MAKEHOOK( + module.Offset(0x65C50), + &SQCompiler_ResolveLocalOrConstantHook, + &SQCompiler_ResolveLocalOrConstant); + MAKEHOOK(module.Offset(0x1FE90), &SQPrintHook, &SQPrint); MAKEHOOK(module.Offset(0x260E0), &CreateNewVMHook, &CreateNewVM); MAKEHOOK(module.Offset(0x26E20), &DestroyVMHook, &DestroyVM); diff --git a/primedev/vscript/languages/squirrel_re/squirrel/sqcompiler.h b/primedev/vscript/languages/squirrel_re/squirrel/sqcompiler.h index 5a54751c..1b50dc7d 100644 --- a/primedev/vscript/languages/squirrel_re/squirrel/sqcompiler.h +++ b/primedev/vscript/languages/squirrel_re/squirrel/sqcompiler.h @@ -14,7 +14,9 @@ struct SQCompiler int64_t qword98; BYTE gapA0[280]; bool bFatalError; - BYTE gap1B9[143]; + BYTE gap1B9[11]; + int preprocessorDepth; + BYTE gap1C8[128]; int64_t qword248; int64_t qword250; int64_t qword258; diff --git a/primedev/vscript/languages/squirrel_re/squirrel/sqstate.h b/primedev/vscript/languages/squirrel_re/squirrel/sqstate.h index d5282ac7..b226f2f3 100644 --- a/primedev/vscript/languages/squirrel_re/squirrel/sqstate.h +++ b/primedev/vscript/languages/squirrel_re/squirrel/sqstate.h @@ -58,7 +58,9 @@ struct SQSharedState SQTable* _entityTypesMaybe; SQObjectType unknownTable2Type; SQTable* unknownTable2; - unsigned char gap_41D8[64]; + unsigned char gap_41D8[16]; + SQObject* compilerTypeDescriptors; + unsigned char gap_41F0[40]; SQCompiler* pCompiler; SQObjectType _compilerKeywordsType; SQTable* _compilerKeywords;