diff --git a/SilentPatchVC/SilentPatchVC.cpp b/SilentPatchVC/SilentPatchVC.cpp index 1f49d1d..69f5be1 100644 --- a/SilentPatchVC/SilentPatchVC.cpp +++ b/SilentPatchVC/SilentPatchVC.cpp @@ -671,10 +671,11 @@ float FixedRefValue() void __declspec(naked) SubtitlesShadowFix() { +#ifdef MSC_VER _asm { mov [esp], eax - fild [esp] + fild dword ptr [esp] push eax lea eax, [esp+20h-18h] push eax @@ -683,17 +684,50 @@ void __declspec(naked) SubtitlesShadowFix() call Recalculate 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() { +#ifdef MSC_VER _asm { push eax mov ecx, ebp 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(0x6022AA, 0x60228A, 0x601ECA); @@ -733,9 +767,11 @@ unsigned int __cdecl AutoPilotTimerCalculation_VC(unsigned int nTimer, int nScal void __declspec(naked) AutoPilotTimerFix_VC() { - _asm { - push dword ptr[esp + 0xC] - push dword ptr[ebx + 0x10] +#ifdef MSC_VER + _asm + { + push dword ptr [esp + 0xC] + push dword ptr [ebx + 0x10] push eax call AutoPilotTimerCalculation_VC add esp, 0xC @@ -743,8 +779,24 @@ void __declspec(naked) AutoPilotTimerFix_VC() add esp, 0x30 pop ebp 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() { +#ifdef MSC_VER _asm { - mov dword ptr [esi+1Ch], 1Ch + mov dword ptr [esi+0x1C], 0x1C // al = 0 - high pitched siren // al = 1 - normal siren - cmp dword ptr [ebp+14h], 90 // fbiranch + cmp dword ptr [ebp+0x14], 90 // fbiranch je IsFBIRanchOrFBICar_HighPitchSiren - cmp dword ptr [ebp+14h], 17 // fbicar + cmp dword ptr [ebp+0x14], 17 // fbicar setne al - retn + ret IsFBIRanchOrFBICar_HighPitchSiren: 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) // m_nStatus = STATUS_ABANDONED; +#ifdef MSC_VER _asm { - mov cl, [ebx+50h] + mov cl, [ebx+0x50] mov al, cl - and cl, 0F8h - cmp cl, 28h + and cl, 0xF8 + cmp cl, 0x28 je DontSetStatus and al, 7 - or al, 20h + or al, 0x20 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; __declspec(naked) static void sscanf1_LoadPath_Terminate() { +#ifdef MSC_VER _asm { mov eax, [esp+4] mov byte ptr [eax+ecx], 0 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() { +#ifdef MSC_VER _asm { - mov byte ptr [esp+184h-170h], 0 - mov dword ptr [esp+184h-174h], 37 - retn + mov byte ptr [esp+0x184-0x170], 0 + mov dword ptr [esp+0x184-0x174], 37 + 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() { +#ifdef MSC_VER _asm { cmp ecx, 294 // minigun2 jnz NotMinigun2 - mov byte ptr [esp+184h-170h], 0 + mov byte ptr [esp+0x184-0x170], 0 xor eax, eax jmp Return @@ -1087,8 +1194,25 @@ namespace PickupEffectsFixes Return: 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() { // 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 { test bl, bl @@ -1118,13 +1243,38 @@ namespace IsPlayerTargettingCharFix jz ReturnToUpdateCompareFlag CmpAndReturn: - cmp byte ptr [esp+11Ch-10Ch], 0 - retn + cmp byte ptr [esp+0x11C-0x10C], 0 + ret ReturnToUpdateCompareFlag: 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; __declspec(naked) static void __fastcall EntityRender_Original(CEntity*) { +#ifdef MSC_VER _asm { push ebx mov ebx, ecx - cmp dword ptr [ebx+4Ch], 0 + cmp dword ptr [ebx+0x4C], 0 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) @@ -1392,14 +1553,26 @@ namespace TommyFistShakeWithWeapons static __declspec(naked) void CheckWeaponGroupHook() { +#ifdef MSC_VER _asm { push dword ptr [eax] call WeaponProhibitsFistShake add esp, 4 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