Compare commits

...

11 commits

Author SHA1 Message Date
Echo J
870e3d63a1 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)
2024-11-13 21:17:52 +02:00
Echo J
3f26e0045e SilentPatchIII: Add GCC/Clang-specific inline assembly statements
This also matches the MSVC statements more closely to the GCC/Clang
ones
2024-11-13 21:17:49 +02:00
Echo J
b7a08843be SilentPatchIII: Add a missing functional header include
MinGW GCC doesn't implicitly include it either
2024-11-13 21:09:26 +02:00
Echo J
fd395f3c6a SilentPatch: Add missing cmath header include
It's required for the modf() function (and it isn't implicitly
included on MinGW GCC)
2024-11-13 21:09:26 +02:00
Echo J
d9c3561d7b SilentPatch: Move a header include in SVF
This makes sure the fixed-width integer types are included in SVF.h
2024-11-13 21:09:26 +02:00
Echo J
8a930e6e4b SilentPatch: Define a replacement for _stricmp() on non-MSVC
MinGW GCC doesn't have this MSVC-specific function
2024-11-13 21:09:26 +02:00
Echo J
90e5ba15ab SilentPatch: Move RwEngineInstance definition to headers
MinGW GCC can't locate it in some files otherwise
2024-11-13 21:09:26 +02:00
Echo J
f9adddf0e1 SilentPatch: Simplify RwIm2DRenderLine function pointer declaration
MinGW GCC doesn't seem to unwind the layers of the macro define
properly (which causes it to not find the declaration type)
2024-11-13 21:09:26 +02:00
Echo J
d49e03e372 SilentPatch: Don't define certain Rw* functions if not needed
Redefining them can cause strange compile errors with MinGW GCC
2024-11-13 21:09:26 +02:00
Echo J
4445c9e24a DDraw: Cast the memcpy() source argument
This works around the MinGW GCC type strictness
2024-11-13 21:09:26 +02:00
Echo J
23af8cd7ca DDraw: Use a pragma for DirectDrawCreateEx export on MSVC
The .def file is either going to have issues on MSVC or MinGW GCC
(so replace it with a pragma on MSVC)
2024-11-13 21:06:45 +02:00
13 changed files with 505 additions and 91 deletions

View file

@ -1,3 +1,3 @@
LIBRARY DDRAW LIBRARY DDRAW
EXPORTS EXPORTS
DirectDrawCreateEx=_DirectDrawCreateEx@16 @10 DirectDrawCreateEx = DirectDrawCreateEx@16

View file

@ -83,7 +83,6 @@
<AdditionalOptions>/Zc:threadSafeInit- /Zc:strictStrings %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/Zc:threadSafeInit- /Zc:strictStrings %(AdditionalOptions)</AdditionalOptions>
</ClCompile> </ClCompile>
<Link> <Link>
<ModuleDefinitionFile>ddraw.def</ModuleDefinitionFile>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
<DelayLoadDLLs>shell32.dll;shlwapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs> <DelayLoadDLLs>shell32.dll;shlwapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<LargeAddressAware>true</LargeAddressAware> <LargeAddressAware>true</LargeAddressAware>
@ -113,7 +112,6 @@
<Link> <Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>ddraw.def</ModuleDefinitionFile>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
<DelayLoadDLLs>shell32.dll;shlwapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs> <DelayLoadDLLs>shell32.dll;shlwapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<LargeAddressAware>true</LargeAddressAware> <LargeAddressAware>true</LargeAddressAware>
@ -143,7 +141,6 @@
<Link> <Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>ddraw.def</ModuleDefinitionFile>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
<DelayLoadDLLs>shell32.dll;shlwapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs> <DelayLoadDLLs>shell32.dll;shlwapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<LargeAddressAware>true</LargeAddressAware> <LargeAddressAware>true</LargeAddressAware>
@ -172,4 +169,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>
</Project> </Project>

View file

@ -14,6 +14,7 @@
#include "Desktop.h" #include "Desktop.h"
#pragma comment(lib, "shlwapi.lib") #pragma comment(lib, "shlwapi.lib")
#pragma comment(linker, "/EXPORT:DirectDrawCreateEx=_DirectDrawCreateEx@16")
extern "C" HRESULT WINAPI DirectDrawCreateEx(GUID FAR *lpGUID, LPVOID *lplpDD, REFIID iid, IUnknown FAR *pUnkOuter) extern "C" HRESULT WINAPI DirectDrawCreateEx(GUID FAR *lpGUID, LPVOID *lplpDD, REFIID iid, IUnknown FAR *pUnkOuter)
{ {
@ -197,7 +198,7 @@ static bool PatchIAT()
static bool PatchIAT_ByPointers() static bool PatchIAT_ByPointers()
{ {
pOrgSystemParametersInfoA = SystemParametersInfoA; pOrgSystemParametersInfoA = SystemParametersInfoA;
memcpy( orgCode, pOrgSystemParametersInfoA, sizeof(orgCode) ); memcpy( orgCode, reinterpret_cast<void*>(pOrgSystemParametersInfoA), sizeof(orgCode) );
Memory::VP::InjectHook( pOrgSystemParametersInfoA, SystemParametersInfoA_OverwritingHook, Memory::HookType::Jump ); Memory::VP::InjectHook( pOrgSystemParametersInfoA, SystemParametersInfoA_OverwritingHook, Memory::HookType::Jump );
return true; return true;
} }

View file

@ -34,7 +34,7 @@ namespace HandlingNameLoadFix
// ============= Corona lines rendering fix ============= // ============= Corona lines rendering fix =============
namespace CoronaLinesFix namespace CoronaLinesFix
{ {
static decltype(RwIm2DRenderLine)* orgRwIm2DRenderLine; static RwIm2DRenderLineFunction orgRwIm2DRenderLine;
static RwBool RenderLine_SetRecipZ( RwIm2DVertex *vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2 ) static RwBool RenderLine_SetRecipZ( RwIm2DVertex *vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2 )
{ {
const RwReal nearScreenZ = RwIm2DGetNearScreenZ(); const RwReal nearScreenZ = RwIm2DGetNearScreenZ();
@ -379,4 +379,4 @@ namespace Common {
TXN_CATCH(); TXN_CATCH();
} }
} }
} }

View file

@ -1,8 +1,6 @@
#include "Utils/MemoryMgr.h" #include "Utils/MemoryMgr.h"
#include "Utils/Patterns.h" #include "Utils/Patterns.h"
#define RwEngineInstance (*rwengine)
#include <rwcore.h> #include <rwcore.h>
#include "RWGTA.h" #include "RWGTA.h"
@ -52,6 +50,7 @@ void RwD3D8GetRenderState(RwUInt32 state, void* value)
fnRwD3D8GetRenderState(state, value); fnRwD3D8GetRenderState(state, value);
} }
#ifndef RwIm2DGetNearScreenZ
RwReal RwIm2DGetNearScreenZ() RwReal RwIm2DGetNearScreenZ()
{ {
return RWSRCGLOBAL(dOpenDevice).zBufferNear; return RWSRCGLOBAL(dOpenDevice).zBufferNear;
@ -66,6 +65,7 @@ RwBool RwRenderStateSet(RwRenderState state, void *value)
{ {
return RWSRCGLOBAL(dOpenDevice).fpRenderStateSet(state, value); return RWSRCGLOBAL(dOpenDevice).fpRenderStateSet(state, value);
} }
#endif
// Unreachable stub // Unreachable stub
RwBool RwMatrixDestroy(RwMatrix* /*mpMat*/) { assert(!"Unreachable!"); return TRUE; } RwBool RwMatrixDestroy(RwMatrix* /*mpMat*/) { assert(!"Unreachable!"); return TRUE; }

View file

@ -1,5 +1,9 @@
#pragma once #pragma once
#define RwEngineInstance (*rwengine)
extern void** rwengine;
namespace RWGTA::Patches namespace RWGTA::Patches
{ {
bool TryLocateRwD3D8(); bool TryLocateRwD3D8();

View file

@ -3,6 +3,10 @@
#include <rwcore.h> #include <rwcore.h>
#include <rpworld.h> #include <rpworld.h>
#define RwEngineInstance (*rwengine)
extern void** rwengine;
template<RwRenderState State> template<RwRenderState State>
class RwScopedRenderState class RwScopedRenderState
{ {
@ -68,4 +72,4 @@ Pred RpGeometryForAllMaterials(RpGeometry* geometry, Pred callback)
break; break;
} }
return callback; return callback;
} }

View file

@ -1,9 +1,13 @@
#include "SVF.h" #include "SVF.h"
#include <cstdint>
#include <algorithm> #include <algorithm>
#include <map> #include <map>
#ifndef _MSC_VER
#include <cstring>
#define _stricmp strcasecmp
#endif
namespace SVF namespace SVF
{ {
Feature GetFeatureFromName( const char* featureName ) Feature GetFeatureFromName( const char* featureName )
@ -233,4 +237,4 @@ __declspec(dllexport) void DisableStockVehiclesForSpecialVehicleFeature( const c
SVF::DisableStockVehiclesForFeature( SVF::GetFeatureFromName(featureName) ); SVF::DisableStockVehiclesForFeature( SVF::GetFeatureFromName(featureName) );
} }
} }

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <cstdint>
#include <functional> #include <functional>
#include <string> #include <string>
@ -60,4 +61,4 @@ namespace SVF
void RegisterGetModelInfoCB(void*(*func)(const char*, int*)); void RegisterGetModelInfoCB(void*(*func)(const char*, int*));
void MarkModelNamesReady(); void MarkModelNamesReady();
}; };

View file

@ -1,6 +1,8 @@
#ifndef __TIMER #ifndef __TIMER
#define __TIMER #define __TIMER
#include <cmath>
class CTimer class CTimer
{ {
public: public:
@ -16,4 +18,4 @@ public:
static void Update_SilentPatch(); static void Update_SilentPatch();
}; };
#endif #endif

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <functional>
#include "Maths.h" #include "Maths.h"
#include <rwcore.h> #include <rwcore.h>

View file

@ -196,36 +196,70 @@ void ResetMousePos()
void __declspec(naked) M16StatsFix() void __declspec(naked) M16StatsFix()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
add eax, 34h add eax, 0x34
add ebx, 34h add ebx, 0x34
mov ecx, [InstantHitsFiredByPlayer] mov ecx, InstantHitsFiredByPlayer
inc [ecx] inc dword ptr [ecx]
retn ret
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"add eax, 0x34\n"
"add ebx, 0x34\n"
"mov ecx, %[InstantHitsFiredByPlayer]\n"
"inc dword ptr [ecx]\n"
"ret"
:: [InstantHitsFiredByPlayer] "m" (InstantHitsFiredByPlayer)
);
#endif
} }
static const float fMinusOne = -1.0f;
void __declspec(naked) HeadlightsFix() void __declspec(naked) HeadlightsFix()
{ {
static const float fMinusOne = -1.0f; #ifdef _MSC_VER
_asm _asm
{ {
fld [esp+708h-690h] fld dword ptr [esp+0x708-0x690]
fcomp fMinusOne fcomp fMinusOne
fnstsw ax fnstsw ax
and ah, 5 and ah, 5
cmp ah, 1 cmp ah, 1
jnz HeadlightsFix_DontLimit jnz HeadlightsFix_DontLimit
fld fMinusOne fld fMinusOne
fstp [esp+708h-690h] fstp dword ptr [esp+0x708-0x690]
HeadlightsFix_DontLimit: HeadlightsFix_DontLimit:
fld [esp+708h-690h] fld dword ptr [esp+0x708-0x690]
fabs fabs
fld st fld st
jmp [HeadlightsFix_JumpBack] jmp HeadlightsFix_JumpBack
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"fld dword ptr [esp+0x708-0x690]\n"
"fcomp %[fMinusOne]\n"
"fnstsw ax\n"
"and ah, 5\n"
"cmp ah, 1\n"
"jnz HeadlightsFix_DontLimit\n"
"fld %[fMinusOne]\n"
"fstp dword ptr [esp+0x708-0x690]\n"
"HeadlightsFix_DontLimit:\n"
"fld dword ptr [esp+0x708-0x690]\n"
"fabs\n"
"fld st\n"
"jmp %[HeadlightsFix_JumpBack]"
:: [fMinusOne] "f" (fMinusOne),
[HeadlightsFix_JumpBack] "m" (HeadlightsFix_JumpBack)
);
#endif
} }
static float fShadowXSize, fShadowYSize; static float fShadowXSize, fShadowYSize;
@ -314,38 +348,67 @@ float FixedRefValue()
void __declspec(naked) SubtitlesShadowFix() void __declspec(naked) SubtitlesShadowFix()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
push eax push eax
call Recalculate call Recalculate
fadd [esp+50h+8] fadd dword ptr [esp+0x50+8]
fadd [fShadowYSize] fadd fShadowYSize
jmp SubtitlesShadowFix_JumpBack jmp SubtitlesShadowFix_JumpBack
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"push eax\n"
"call %[Recalculate]\n"
"fadd dword ptr [esp+0x50+8]\n"
"fadd %[fShadowYSize]\n"
"jmp %[SubtitlesShadowFix_JumpBack]"
:: [Recalculate] "i" (Recalculate),
[fShadowYSize] "m" (fShadowYSize),
[SubtitlesShadowFix_JumpBack] "m" (SubtitlesShadowFix_JumpBack)
);
#endif
} }
void __declspec(naked) III_SensResetFix() void __declspec(naked) III_SensResetFix()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
mov ecx, 3A76h mov ecx, 0x3A76
mov edi, ebp mov edi, ebp
fld dword ptr [ebp+194h] fld dword ptr [ebp+0x194]
fld dword ptr [ebp+198h] fld dword ptr [ebp+0x198]
rep stosd rep stosd
fstp dword ptr [ebp+198h] fstp dword ptr [ebp+0x198]
fstp dword ptr [ebp+194h] fstp dword ptr [ebp+0x194]
retn ret
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"mov ecx, 0x3A76\n"
"mov edi, ebp\n"
"fld dword ptr [ebp+0x194]\n"
"fld dword ptr [ebp+0x198]\n"
"rep stosd\n"
"fstp dword ptr [ebp+0x198]\n"
"fstp dword ptr [ebp+0x194]\n"
"ret"
);
#endif
} }
static void* RadarBoundsCheckCoordBlip_JumpBack = AddressByVersion<void*>(0x4A55B8, 0x4A56A8, 0x4A5638); static void* RadarBoundsCheckCoordBlip_JumpBack = AddressByVersion<void*>(0x4A55B8, 0x4A56A8, 0x4A5638);
static void* RadarBoundsCheckCoordBlip_Count = AddressByVersion<void*>(0x4A55AF, 0x4A569F, 0x4A562F); static void* RadarBoundsCheckCoordBlip_Count = AddressByVersion<void*>(0x4A55AF, 0x4A569F, 0x4A562F);
void __declspec(naked) RadarBoundsCheckCoordBlip() void __declspec(naked) RadarBoundsCheckCoordBlip()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
mov edx, dword ptr [RadarBoundsCheckCoordBlip_Count] mov edx, RadarBoundsCheckCoordBlip_Count
cmp cl, byte ptr [edx] cmp cl, byte ptr [edx]
jnb OutOfBounds jnb OutOfBounds
mov edx, ecx mov edx, ecx
@ -355,16 +418,35 @@ void __declspec(naked) RadarBoundsCheckCoordBlip()
OutOfBounds: OutOfBounds:
or eax, -1 or eax, -1
fcompp fcompp
retn ret
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"mov edx, %[RadarBoundsCheckCoordBlip_Count]\n"
"cmp cl, byte ptr [edx]\n"
"jnb OutOfBounds\n"
"mov edx, ecx\n"
"mov eax, [esp+4]\n"
"jmp %[RadarBoundsCheckCoordBlip_JumpBack]\n"
"OutOfBounds:\n"
"or eax, -1\n"
"fcompp\n"
"ret"
:: [RadarBoundsCheckCoordBlip_Count] "m" (RadarBoundsCheckCoordBlip_Count),
[RadarBoundsCheckCoordBlip_JumpBack] "m" (RadarBoundsCheckCoordBlip_JumpBack)
);
#endif
} }
static void* RadarBoundsCheckEntityBlip_JumpBack = AddressByVersion<void*>(0x4A565E, 0x4A574E, 0x4A56DE); static void* RadarBoundsCheckEntityBlip_JumpBack = AddressByVersion<void*>(0x4A565E, 0x4A574E, 0x4A56DE);
void __declspec(naked) RadarBoundsCheckEntityBlip() void __declspec(naked) RadarBoundsCheckEntityBlip()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
mov edx, dword ptr [RadarBoundsCheckCoordBlip_Count] mov edx, RadarBoundsCheckCoordBlip_Count
cmp cl, byte ptr [edx] cmp cl, byte ptr [edx]
jnb OutOfBounds jnb OutOfBounds
mov edx, ecx mov edx, ecx
@ -373,8 +455,25 @@ void __declspec(naked) RadarBoundsCheckEntityBlip()
OutOfBounds: OutOfBounds:
or eax, -1 or eax, -1
retn ret
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"mov edx, %[RadarBoundsCheckCoordBlip_Count]\n"
"cmp cl, byte ptr [edx]\n"
"jnb OutOfBounds2\n"
"mov edx, ecx\n"
"mov eax, [esp+4]\n"
"jmp %[RadarBoundsCheckEntityBlip_JumpBack]\n"
"OutOfBounds2:\n"
"or eax, -1\n"
"ret"
:: [RadarBoundsCheckCoordBlip_Count] "m" (RadarBoundsCheckCoordBlip_Count),
[RadarBoundsCheckEntityBlip_JumpBack] "m" (RadarBoundsCheckEntityBlip_JumpBack)
);
#endif
} }
char** ppUserFilesDir = AddressByVersion<char**>(0x580C16, 0x580F66, 0x580E66); char** ppUserFilesDir = AddressByVersion<char**>(0x580C16, 0x580F66, 0x580E66);
@ -413,9 +512,10 @@ unsigned int __cdecl AutoPilotTimerCalculation_III(unsigned int nTimer, int nSca
void __declspec(naked) AutoPilotTimerFix_III() void __declspec(naked) AutoPilotTimerFix_III()
{ {
#ifdef _MSC_VER
_asm { _asm {
push dword ptr[esp + 0x4] push dword ptr [esp + 0x4]
push dword ptr[ebx + 0x10] push dword ptr [ebx + 0x10]
push eax push eax
call AutoPilotTimerCalculation_III call AutoPilotTimerCalculation_III
add esp, 0xC add esp, 0xC
@ -424,8 +524,25 @@ void __declspec(naked) AutoPilotTimerFix_III()
pop ebp pop ebp
pop esi pop esi
pop ebx pop ebx
retn 4 ret 4
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"push dword ptr [esp + 0x4]\n"
"push dword ptr [ebx + 0x10]\n"
"push eax\n"
"call %[AutoPilotTimerCalculation_III]\n"
"add esp, 0xC\n"
"mov [ebx + 0xC], eax\n"
"add esp, 0x28\n"
"pop ebp\n"
"pop esi\n"
"pop ebx\n"
"ret 4"
:: [AutoPilotTimerCalculation_III] "i" (AutoPilotTimerCalculation_III)
);
#endif
} }
namespace ZeroAmmoFix namespace ZeroAmmoFix
@ -580,19 +697,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 ah, [ecx+50h] mov ah, [ecx+0x50]
mov al, ah mov al, ah
and ah, 0F8h and ah, 0xF8
cmp ah, 28h cmp ah, 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 ah, [ecx+0x50]\n"
"mov al, ah\n"
"and ah, 0xF8\n"
"cmp ah, 0x28\n"
"je DontSetStatus\n"
"and al, 7\n"
"or al, 0x20\n"
"DontSetStatus:\n"
"ret"
);
#endif
} }
} }
@ -625,16 +758,30 @@ namespace EvasiveDiveFix
__declspec(naked) void CalculateAngle_Hook() __declspec(naked) void CalculateAngle_Hook()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
push dword ptr [esi+7Ch] push dword ptr [esi+0x7C]
push dword ptr [esi+78h] push dword ptr [esi+0x78]
call CalculateAngle call CalculateAngle
add esp, 8 add esp, 8
mov ecx, ebp mov ecx, ebp
retn ret
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"push dword ptr [esi+0x7C]\n"
"push dword ptr [esi+0x78]\n"
"call %[CalculateAngle]\n"
"add esp, 8\n"
"mov ecx, ebp\n"
"ret"
:: [CalculateAngle] "i" (CalculateAngle)
);
#endif
} }
} }
@ -647,36 +794,69 @@ 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]"
:: [orgSscanf_LoadPath] "m" (orgSscanf_LoadPath)
);
#endif
} }
static void* orgSscanf1; static void* orgSscanf1;
__declspec(naked) static void sscanf1_Terminate() __declspec(naked) static void sscanf1_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 [orgSscanf1] jmp orgSscanf1
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"mov eax, [esp+4]\n"
"mov byte ptr [eax+ecx], 0\n"
"jmp %[orgSscanf1]"
:: [orgSscanf1] "m" (orgSscanf1)
);
#endif
} }
__declspec(naked) static void ReadTrackFile_Terminate() __declspec(naked) static void ReadTrackFile_Terminate()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
mov ecx, [gString] mov ecx, gString
mov byte ptr [ecx+edx], 0 mov byte ptr [ecx+edx], 0
mov ecx, [esi] mov ecx, [esi]
inc ebp inc ebp
add ecx, [esp+0ACh-98h] add ecx, [esp+0xAC-0x98]
retn ret
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"mov ecx, %[gString]\n"
"mov byte ptr [ecx+edx], 0\n"
"mov ecx, [esi]\n"
"inc ebp\n"
"add ecx, [esp+0xAC-0x98]\n"
"ret"
:: [gString] "m" (gString)
);
#endif
} }
} }
@ -703,17 +883,33 @@ namespace DodoKeyboardControls
static void* (*orgFindPlayerVehicle)(); static void* (*orgFindPlayerVehicle)();
__declspec(naked) static void FindPlayerVehicle_DodoCheck() __declspec(naked) static void FindPlayerVehicle_DodoCheck()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
call [orgFindPlayerVehicle] call orgFindPlayerVehicle
mov ecx, [bAllDodosCheat] mov ecx, bAllDodosCheat
cmp byte ptr [ecx], 0 cmp byte ptr [ecx], 0
je CheatDisabled je CheatDisabled
mov byte ptr [esp+1Ch-14h], 1 mov byte ptr [esp+0x1C-0x14], 1
CheatDisabled: CheatDisabled:
retn ret
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"call %[orgFindPlayerVehicle]\n"
"mov ecx, %[bAllDodosCheat]\n"
"cmp byte ptr [ecx], 0\n"
"je CheatDisabled\n"
"mov byte ptr [esp+0x1C-0x14], 1\n"
"CheatDisabled:\n"
"ret"
:: [orgFindPlayerVehicle] "m" (orgFindPlayerVehicle),
[bAllDodosCheat] "m" (bAllDodosCheat)
);
#endif
} }
} }
@ -770,9 +966,10 @@ namespace GenerateNewPickup_ReuseObjectFix
__declspec(naked) void GiveUsAPickUpObject_CleanUpObject() __declspec(naked) void GiveUsAPickUpObject_CleanUpObject()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
mov eax, [pPickupObject] mov eax, pPickupObject
add eax, ebp add eax, ebp
mov eax, [eax] mov eax, [eax]
test eax, eax test eax, eax
@ -781,7 +978,7 @@ namespace GenerateNewPickup_ReuseObjectFix
mov edi, eax mov edi, eax
push edi push edi
call [WorldRemove] call WorldRemove
add esp, 4 add esp, 4
// Call dtor // Call dtor
@ -793,8 +990,38 @@ namespace GenerateNewPickup_ReuseObjectFix
pop edi pop edi
NoPickup: NoPickup:
jmp [orgGiveUsAPickUpObject] jmp orgGiveUsAPickUpObject
} }
#elif defined(__GNUC__) || defined(__clang__)
__asm__ volatile
(
"mov eax, %[pPickupObject]\n"
"add eax, ebp\n"
"mov eax, [eax]\n"
"test eax, eax\n"
"jz NoPickup\n"
"push edi\n"
"mov edi, eax\n"
"push edi\n"
"call offset %[WorldRemove]\n"
"add esp, 4\n"
// Call dtor
"mov ecx, edi\n"
"mov eax, [edi]\n"
"push 1\n"
"call dword ptr [eax]\n"
"pop edi\n"
"NoPickup:\n"
"jmp %[orgGiveUsAPickUpObject]"
:: [pPickupObject] "m" (pPickupObject),
[WorldRemove] "m" (WorldRemove),
[orgGiveUsAPickUpObject] "m" (orgGiveUsAPickUpObject)
);
#endif
} }
} }

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]"
:: [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"
:: [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"
:: [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"
);
#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"
);
#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]"
:: [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"
);
#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"
);
#endif
} }
} }
@ -1105,26 +1229,52 @@ 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
jnz ReturnToUpdateCompareFlag jnz ReturnToUpdateCompareFlag
mov eax, [bUseMouse3rdPerson] mov eax, bUseMouse3rdPerson
cmp byte ptr [eax], 0 cmp byte ptr [eax], 0
jne CmpAndReturn jne CmpAndReturn
mov ecx, [TheCamera] mov ecx, TheCamera
call [Using1stPersonWeaponMode] call Using1stPersonWeaponMode
test al, al test al, al
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"
:: [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]"
:: [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"
:: [WeaponProhibitsFistShake] "i" (WeaponProhibitsFistShake)
);
#endif
} }
template<std::size_t Index> template<std::size_t Index>