SilentPatchVC: Add GCC/Clang-specific inline assembly statements

This also includes a small wrapper to call a C++ function from inline ASM

(From III: This change also matches the MSVC statements more closely to
the GCC/Clang ones)
This commit is contained in:
Echo J 2024-11-07 10:11:20 +02:00
parent 135ceed86c
commit 00a48ec059

View file

@ -671,10 +671,11 @@ float FixedRefValue()
void __declspec(naked) SubtitlesShadowFix() void __declspec(naked) SubtitlesShadowFix()
{ {
#ifdef MSC_VER
_asm _asm
{ {
mov [esp], eax mov [esp], eax
fild [esp] fild dword ptr [esp]
push eax push eax
lea eax, [esp+20h-18h] lea eax, [esp+20h-18h]
push eax push eax
@ -683,17 +684,50 @@ void __declspec(naked) SubtitlesShadowFix()
call Recalculate call Recalculate
jmp SubtitlesShadowFix_JumpBack jmp SubtitlesShadowFix_JumpBack
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"mov [esp], eax\n"
"fild dword ptr [esp]\n"
"push eax\n"
"lea eax, [esp+0x20-0x18]\n"
"push eax\n"
"lea eax, [esp+0x24-0x14]\n"
"push eax\n"
"call %[Recalculate]\n"
"jmp %[SubtitlesShadowFix_JumpBack]\n"
:: [Recalculate] "i" (Recalculate),
[SubtitlesShadowFix_JumpBack] "m" (SubtitlesShadowFix_JumpBack)
);
#endif
}
// C-style wrapper for calling a C++ function in GCC-style inline assembly (the function signature is really important here)
RwFrame* __thiscall CVehicleModelInfo_GetExtrasFrame(CVehicleModelInfo* modelInfo, RpClump* clump)
{
return modelInfo->GetExtrasFrame(clump);
} }
void __declspec(naked) CreateInstance_BikeFix() void __declspec(naked) CreateInstance_BikeFix()
{ {
#ifdef MSC_VER
_asm _asm
{ {
push eax push eax
mov ecx, ebp mov ecx, ebp
call CVehicleModelInfo::GetExtrasFrame call CVehicleModelInfo::GetExtrasFrame
retn ret
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"push eax\n"
"mov ecx, ebp\n"
"call %[CVehicleModelInfo_GetExtrasFrame]\n"
"ret\n"
:: [CVehicleModelInfo_GetExtrasFrame] "i" (CVehicleModelInfo_GetExtrasFrame)
);
#endif
} }
char** ppUserFilesDir = AddressByVersion<char**>(0x6022AA, 0x60228A, 0x601ECA); char** ppUserFilesDir = AddressByVersion<char**>(0x6022AA, 0x60228A, 0x601ECA);
@ -733,9 +767,11 @@ unsigned int __cdecl AutoPilotTimerCalculation_VC(unsigned int nTimer, int nScal
void __declspec(naked) AutoPilotTimerFix_VC() void __declspec(naked) AutoPilotTimerFix_VC()
{ {
_asm { #ifdef MSC_VER
push dword ptr[esp + 0xC] _asm
push dword ptr[ebx + 0x10] {
push dword ptr [esp + 0xC]
push dword ptr [ebx + 0x10]
push eax push eax
call AutoPilotTimerCalculation_VC call AutoPilotTimerCalculation_VC
add esp, 0xC add esp, 0xC
@ -743,8 +779,24 @@ void __declspec(naked) AutoPilotTimerFix_VC()
add esp, 0x30 add esp, 0x30
pop ebp pop ebp
pop ebx pop ebx
retn 4 ret 4
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"push dword ptr [esp + 0xC]\n"
"push dword ptr [ebx + 0x10]\n"
"push eax\n"
"call %[AutoPilotTimerCalculation_VC]\n"
"add esp, 0xC\n"
"mov [ebx + 0xC], eax\n"
"add esp, 0x30\n"
"pop ebp\n"
"pop ebx\n"
"ret 4\n"
:: [AutoPilotTimerCalculation_VC] "i" (AutoPilotTimerCalculation_VC)
);
#endif
} }
@ -865,22 +917,41 @@ namespace SirenSwitchingFix
{ {
void __declspec(naked) IsFBIRanchOrFBICar() void __declspec(naked) IsFBIRanchOrFBICar()
{ {
#ifdef MSC_VER
_asm _asm
{ {
mov dword ptr [esi+1Ch], 1Ch mov dword ptr [esi+0x1C], 0x1C
// al = 0 - high pitched siren // al = 0 - high pitched siren
// al = 1 - normal siren // al = 1 - normal siren
cmp dword ptr [ebp+14h], 90 // fbiranch cmp dword ptr [ebp+0x14], 90 // fbiranch
je IsFBIRanchOrFBICar_HighPitchSiren je IsFBIRanchOrFBICar_HighPitchSiren
cmp dword ptr [ebp+14h], 17 // fbicar cmp dword ptr [ebp+0x14], 17 // fbicar
setne al setne al
retn ret
IsFBIRanchOrFBICar_HighPitchSiren: IsFBIRanchOrFBICar_HighPitchSiren:
xor al, al xor al, al
retn ret
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"mov dword ptr [esi+0x1C], 0x1C\n"
// al = 0 - high pitched siren
// al = 1 - normal siren
"cmp dword ptr [ebp+0x14], 90\n" // fbiranch
"je IsFBIRanchOrFBICar_HighPitchSiren\n"
"cmp dword ptr [ebp+0x14], 17\n" // fbicar
"setne al\n"
"ret\n"
"IsFBIRanchOrFBICar_HighPitchSiren:\n"
"xor al, al\n"
"ret\n"
);
#endif
} }
} }
@ -949,19 +1020,35 @@ namespace RemoveDriverStatusFix
{ {
// if (m_nStatus != STATUS_WRECKED) // if (m_nStatus != STATUS_WRECKED)
// m_nStatus = STATUS_ABANDONED; // m_nStatus = STATUS_ABANDONED;
#ifdef MSC_VER
_asm _asm
{ {
mov cl, [ebx+50h] mov cl, [ebx+0x50]
mov al, cl mov al, cl
and cl, 0F8h and cl, 0xF8
cmp cl, 28h cmp cl, 0x28
je DontSetStatus je DontSetStatus
and al, 7 and al, 7
or al, 20h or al, 0x20
DontSetStatus: DontSetStatus:
retn ret
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"mov cl, [ebx+0x50]\n"
"mov al, cl\n"
"and cl, 0xF8\n"
"cmp cl, 0x28\n"
"je DontSetStatus\n"
"and al, 7\n"
"or al, 0x20\n"
"DontSetStatus:\n"
"ret\n"
);
#endif
} }
} }
@ -1034,12 +1121,22 @@ namespace NullTerminatedLines
static void* orgSscanf_LoadPath; static void* orgSscanf_LoadPath;
__declspec(naked) static void sscanf1_LoadPath_Terminate() __declspec(naked) static void sscanf1_LoadPath_Terminate()
{ {
#ifdef MSC_VER
_asm _asm
{ {
mov eax, [esp+4] mov eax, [esp+4]
mov byte ptr [eax+ecx], 0 mov byte ptr [eax+ecx], 0
jmp [orgSscanf_LoadPath] jmp [orgSscanf_LoadPath]
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"mov eax, [esp+4]\n"
"mov byte ptr [eax+ecx], 0\n"
"jmp [%[orgSscanf_LoadPath]]\n"
:: [orgSscanf_LoadPath] "m" (orgSscanf_LoadPath)
);
#endif
} }
} }
@ -1064,21 +1161,31 @@ namespace PickupEffectsFixes
{ {
__declspec(naked) static void PickUpEffects_BigDollarColor() __declspec(naked) static void PickUpEffects_BigDollarColor()
{ {
#ifdef MSC_VER
_asm _asm
{ {
mov byte ptr [esp+184h-170h], 0 mov byte ptr [esp+0x184-0x170], 0
mov dword ptr [esp+184h-174h], 37 mov dword ptr [esp+0x184-0x174], 37
retn ret
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"mov byte ptr [esp+0x184-0x170], 0\n"
"mov dword ptr [esp+0x184-0x174], 37\n"
"ret\n"
);
#endif
} }
__declspec(naked) static void PickUpEffects_Minigun2Glow() __declspec(naked) static void PickUpEffects_Minigun2Glow()
{ {
#ifdef MSC_VER
_asm _asm
{ {
cmp ecx, 294 // minigun2 cmp ecx, 294 // minigun2
jnz NotMinigun2 jnz NotMinigun2
mov byte ptr [esp+184h-170h], 0 mov byte ptr [esp+0x184-0x170], 0
xor eax, eax xor eax, eax
jmp Return jmp Return
@ -1087,8 +1194,25 @@ namespace PickupEffectsFixes
Return: Return:
mov ebx, ecx mov ebx, ecx
retn ret
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"cmp ecx, 294\n" // minigun2
"jnz NotMinigun2\n"
"mov byte ptr [esp+0x184-0x170], 0\n"
"xor eax, eax\n"
"jmp Return\n"
"NotMinigun2:\n"
"lea eax, [ecx+1]\n"
"Return:\n"
"mov ebx, ecx\n"
"ret\n"
);
#endif
} }
} }
@ -1105,6 +1229,7 @@ namespace IsPlayerTargettingCharFix
__declspec(naked) static void IsPlayerTargettingChar_ExtraChecks() __declspec(naked) static void IsPlayerTargettingChar_ExtraChecks()
{ {
// After this extra block of code, there is a jz Return, so set ZF to 0 here if this path is to be entered // After this extra block of code, there is a jz Return, so set ZF to 0 here if this path is to be entered
#ifdef MSC_VER
_asm _asm
{ {
test bl, bl test bl, bl
@ -1118,13 +1243,38 @@ namespace IsPlayerTargettingCharFix
jz ReturnToUpdateCompareFlag jz ReturnToUpdateCompareFlag
CmpAndReturn: CmpAndReturn:
cmp byte ptr [esp+11Ch-10Ch], 0 cmp byte ptr [esp+0x11C-0x10C], 0
retn ret
ReturnToUpdateCompareFlag: ReturnToUpdateCompareFlag:
xor al, al xor al, al
retn ret
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"test bl, bl\n"
"jnz ReturnToUpdateCompareFlag\n"
"mov eax, [%[bUseMouse3rdPerson]]\n"
"cmp byte ptr [eax], 0\n"
"jne CmpAndReturn\n"
"mov ecx, [%[TheCamera]]\n"
"call [%[Using1stPersonWeaponMode]]\n"
"test al, al\n"
"jz ReturnToUpdateCompareFlag\n"
"CmpAndReturn:\n"
"cmp byte ptr [esp+0x11C-0x10C], 0\n"
"ret\n"
"ReturnToUpdateCompareFlag:\n"
"xor al, al\n"
"ret\n"
:: [bUseMouse3rdPerson] "m" (bUseMouse3rdPerson),
[TheCamera] "m" (TheCamera),
[Using1stPersonWeaponMode] "m" (Using1stPersonWeaponMode)
);
#endif
} }
} }
@ -1210,13 +1360,24 @@ namespace SelectableBackfaceCulling
static void* EntityRender_Prologue_JumpBack; static void* EntityRender_Prologue_JumpBack;
__declspec(naked) static void __fastcall EntityRender_Original(CEntity*) __declspec(naked) static void __fastcall EntityRender_Original(CEntity*)
{ {
#ifdef MSC_VER
_asm _asm
{ {
push ebx push ebx
mov ebx, ecx mov ebx, ecx
cmp dword ptr [ebx+4Ch], 0 cmp dword ptr [ebx+0x4C], 0
jmp [EntityRender_Prologue_JumpBack] jmp [EntityRender_Prologue_JumpBack]
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"push ebx\n"
"mov ebx, ecx\n"
"cmp dword ptr [ebx+0x4C], 0\n"
"jmp [%[EntityRender_Prologue_JumpBack]]\n"
:: [EntityRender_Prologue_JumpBack] "m" (EntityRender_Prologue_JumpBack)
);
#endif
} }
static bool ShouldDisableBackfaceCulling(const CEntity* entity) static bool ShouldDisableBackfaceCulling(const CEntity* entity)
@ -1392,14 +1553,26 @@ namespace TommyFistShakeWithWeapons
static __declspec(naked) void CheckWeaponGroupHook() static __declspec(naked) void CheckWeaponGroupHook()
{ {
#ifdef MSC_VER
_asm _asm
{ {
push dword ptr [eax] push dword ptr [eax]
call WeaponProhibitsFistShake call WeaponProhibitsFistShake
add esp, 4 add esp, 4
test al, al test al, al
retn ret
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"push dword ptr [eax]\n"
"call %[WeaponProhibitsFistShake]\n"
"add esp, 4\n"
"test al, al\n"
"ret\n"
:: [WeaponProhibitsFistShake] "i" (WeaponProhibitsFistShake)
);
#endif
} }
template<std::size_t Index> template<std::size_t Index>