Compare commits

...

20 commits

Author SHA1 Message Date
Echo J.
f53acc255b
Merge c6885c4d03 into 2a597da1bc 2024-11-29 11:27:52 +01:00
Echo J
c6885c4d03 SilentPatchVC: Add GCC-style inline assembly statements
This also includes a small wrapper to call a C++ function from GCC-style inline ASM

These statements almost work on llvm-mingw too (but there's some stubborn call instructions)
2024-11-29 12:20:52 +02:00
Echo J
c2e58d36e8 SilentPatchIII: Add GCC-style inline assembly statements
These almost work on llvm-mingw too (but there's some stubborn call instructions)
2024-11-29 12:20:52 +02:00
Echo J
d6f3ea8b0a SilentPatchIII: Add a missing functional header include
MinGW GCC doesn't implicitly include it either
2024-11-29 12:20:52 +02:00
Echo J
1b174a3724 SilentPatch: Add missing cmath header include
It's required for the modf() function (and it isn't implicitly
included on MinGW GCC)
2024-11-29 12:20:52 +02:00
Echo J
d3e5495666 SilentPatch: Move a header include in SVF
This makes sure the fixed-width integer types are included in SVF.h
2024-11-29 12:20:52 +02:00
Echo J
50b1c1353d SilentPatch: Define a replacement for _stricmp() on non-MSVC
MinGW GCC doesn't have this MSVC-specific function
2024-11-29 12:20:52 +02:00
Echo J
77f5e908c0 SilentPatch: Move RwEngineInstance definition to headers
MinGW GCC can't locate it in some files otherwise
2024-11-29 12:20:52 +02:00
Echo J
4ba23dbf75 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-29 12:20:52 +02:00
Echo J
80b4fa1ece SilentPatch: Don't define certain Rw* functions if not needed
Redefining them can cause strange compile errors with MinGW GCC
2024-11-29 12:20:52 +02:00
Echo J
acc4af21bd DDraw: Cast the memcpy() source argument
This works around the MinGW GCC type strictness
2024-11-29 12:20:49 +02:00
Echo J
940c68983d 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-29 12:19:33 +02:00
Echo J
1af97eef26 SilentPatchIII/VC/SA: Mark some function pointers as inline
MinGW GCC's linker can't find them otherwise
2024-11-29 12:19:27 +02:00
Echo J
04f74335c1 SilentPatchIII/VC: Remove extern from ppUserFilesDir variable definitions
This fixes compile warnings with MinGW GCC
2024-11-29 12:17:46 +02:00
Echo J
58905270bc SilentPatchIII/VC/SA: Add GCC/Clang-compatible safebuffers equivalent
And switch to a common define for this attribute (this fixes
compile warnings on MinGW GCC)
2024-11-29 12:17:46 +02:00
Echo J
b5483bbf59 Use reinterpret_cast for function pointer casts
MSVC (wrongly) allows those casts to succeed with static_cast:
https://stackoverflow.com/questions/74002657/why-cant-i-static-cast-a-void-to-a-pointer-to-function
(so adjust those casts for better compiler compatibility including MinGW GCC)
2024-11-29 12:17:46 +02:00
Echo J
fe6f98c314 Set Windows defines earlier
This avoids compile warnings on MinGW GCC (because standard C++
headers eventually import the Windows stuff)
2024-11-29 12:17:46 +02:00
Echo J
c15fbc549d Use lowercase names for Windows headers
This fixes missing header issues on a case-sensitive filesystem
with MinGW GCC
2024-11-29 12:17:46 +02:00
Echo J
f33f5c131b Remove unused dllmain.cpp file
It seems to be used in the early days of SilentPatch (but it's
no longer included since the III/VC/SA code split and serves no purpose)
2024-11-29 12:17:46 +02:00
Silent
2a597da1bc
III: Backport one more fix from VC to fix the timer initialize lingering the audio entities on New Game
Fixes #123
2024-11-28 20:41:17 +01:00
30 changed files with 549 additions and 2131 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>

View file

@ -4,8 +4,8 @@
#include <windows.h> #include <windows.h>
#include <stdio.h> #include <stdio.h>
#include <Shlwapi.h> #include <shlwapi.h>
#include <ShlObj.h> #include <shlobj.h>
#include "Utils/MemoryMgr.h" #include "Utils/MemoryMgr.h"
#include "Utils/Patterns.h" #include "Utils/Patterns.h"
#include "Utils/ScopedUnprotect.hpp" #include "Utils/ScopedUnprotect.hpp"
@ -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)
{ {
@ -196,9 +197,11 @@ static bool PatchIAT()
static bool PatchIAT_ByPointers() static bool PatchIAT_ByPointers()
{ {
using namespace Memory::VP;
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 ); InjectHook( pOrgSystemParametersInfoA, SystemParametersInfoA_OverwritingHook, HookType::Jump );
return true; return true;
} }

View file

@ -6,7 +6,7 @@
<SILENTPATCH_EXT>.dll</SILENTPATCH_EXT> <SILENTPATCH_EXT>.dll</SILENTPATCH_EXT>
<SILENTPATCH_FULL_NAME>SilentPatch DDraw Component</SILENTPATCH_FULL_NAME> <SILENTPATCH_FULL_NAME>SilentPatch DDraw Component</SILENTPATCH_FULL_NAME>
<SILENTPATCH_REVISION_ID>6</SILENTPATCH_REVISION_ID> <SILENTPATCH_REVISION_ID>6</SILENTPATCH_REVISION_ID>
<SILENTPATCH_BUILD_ID>0</SILENTPATCH_BUILD_ID> <SILENTPATCH_BUILD_ID>1</SILENTPATCH_BUILD_ID>
<SILENTPATCH_COPYRIGHT>2014-2024</SILENTPATCH_COPYRIGHT> <SILENTPATCH_COPYRIGHT>2014-2024</SILENTPATCH_COPYRIGHT>
</PropertyGroup> </PropertyGroup>
<PropertyGroup /> <PropertyGroup />

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();

View file

@ -2,6 +2,13 @@
#include <cstdint> #include <cstdint>
// Workaround for old MSVC inline function bugs
#if defined(_MSC_VER) && _MSC_VER < 1930
#define STATIC_INLINE static
#else
#define STATIC_INLINE static inline
#endif
namespace ExtraCompSpecularity namespace ExtraCompSpecularity
{ {
void ReadExtraCompSpecularityExceptions(const wchar_t* pPath); void ReadExtraCompSpecularityExceptions(const wchar_t* pPath);

View file

@ -1,22 +1,20 @@
#include "Common_ddraw.h"
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#define WINVER 0x0501 #define WINVER 0x0501
#define _WIN32_WINNT 0x0501 #define _WIN32_WINNT 0x0501
#define NOMINMAX #define NOMINMAX
#include "Common_ddraw.h"
#include <windows.h> #include <windows.h>
#include <Shlwapi.h> #include <shlwapi.h>
#include <ShlObj.h> #include <shlobj.h>
#include "Utils/MemoryMgr.h" #include "Utils/MemoryMgr.h"
#include "Utils/Patterns.h" #include "Utils/Patterns.h"
#pragma comment(lib, "shlwapi.lib") #pragma comment(lib, "shlwapi.lib")
extern char** ppUserFilesDir;
namespace Common { namespace Common {
char* GetMyDocumentsPath() char* GetMyDocumentsPath()
{ {

View file

@ -2,6 +2,8 @@
#include <cstdint> #include <cstdint>
extern char** ppUserFilesDir;
namespace Common namespace Common
{ {
namespace Patches namespace Patches

View file

@ -1,11 +1,11 @@
#include "Desktop.h"
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#define WINVER 0x0501 #define WINVER 0x0501
#define _WIN32_WINNT 0x0501 #define _WIN32_WINNT 0x0501
#define NOMINMAX #define NOMINMAX
#include "Desktop.h"
#include <windows.h> #include <windows.h>
std::pair<uint32_t, uint32_t> GetDesktopResolution() std::pair<uint32_t, uint32_t> GetDesktopResolution()

View file

@ -1,5 +1,3 @@
#include "FriendlyMonitorNames.h"
// This API is Win7 only, so make sure we use dynamic imports // This API is Win7 only, so make sure we use dynamic imports
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
@ -7,6 +5,8 @@
#define WINVER 0x0602 #define WINVER 0x0602
#define _WIN32_WINNT 0x0602 #define _WIN32_WINNT 0x0602
#include "FriendlyMonitorNames.h"
#include <windows.h> #include <windows.h>
#include <memory> #include <memory>

View file

@ -6,6 +6,15 @@
#include <rwcore.h> #include <rwcore.h>
// FIXME: Common.h might be a better place for this (but SA doesn't include it)
#ifdef _MSC_VER
#define NOBUFFERCHECKS __declspec(safebuffers)
#elif defined(__GNUC__) && !defined(__clang__)
#define NOBUFFERCHECKS __attribute__((optimize("-fno-stack-protector")))
#else
#define NOBUFFERCHECKS __attribute__((no_stack_protector))
#endif
constexpr double RAD_TO_DEG (180.0/M_PI); constexpr double RAD_TO_DEG (180.0/M_PI);
constexpr double DEG_TO_RAD (M_PI/180.0); constexpr double DEG_TO_RAD (M_PI/180.0);

View file

@ -1,8 +1,9 @@
#include "ParseUtils.hpp"
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#define NOMINMAX #define NOMINMAX
#include <Windows.h>
#include "ParseUtils.hpp"
#include <windows.h>
static std::string WcharToUTF8(std::wstring_view str) static std::string WcharToUTF8(std::wstring_view str)
{ {

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; }
@ -78,19 +78,19 @@ bool RWGTA::Patches::TryLocateRwD3D8() try
auto pfnRwD3D8SetRenderState = [] { auto pfnRwD3D8SetRenderState = [] {
try { try {
// Everything except for III Steam // Everything except for III Steam
return static_cast<decltype(RwD3D8SetRenderState)*>(get_pattern("39 0C C5 ? ? ? ? 74 31", -8)); return reinterpret_cast<decltype(RwD3D8SetRenderState)*>(get_pattern("39 0C C5 ? ? ? ? 74 31", -8));
} catch (const hook::txn_exception&) { } catch (const hook::txn_exception&) {
// III Steam // III Steam
return static_cast<decltype(RwD3D8SetRenderState)*>(get_pattern("8B 0C C5 ? ? ? ? 3B CA", -8)); return reinterpret_cast<decltype(RwD3D8SetRenderState)*>(get_pattern("8B 0C C5 ? ? ? ? 3B CA", -8));
} }
}(); }();
auto pfnRwD3D8GetRenderState = [] { auto pfnRwD3D8GetRenderState = [] {
try { try {
// Everything except for III Steam // Everything except for III Steam
return static_cast<decltype(RwD3D8GetRenderState)*>(get_pattern("8B 0C C5 ? ? ? ? 89 0A C3", -8)); return reinterpret_cast<decltype(RwD3D8GetRenderState)*>(get_pattern("8B 0C C5 ? ? ? ? 89 0A C3", -8));
} catch (const hook::txn_exception&) { } catch (const hook::txn_exception&) {
// III Steam // III Steam
return static_cast<decltype(RwD3D8GetRenderState)*>(get_pattern("8B 04 C5 ? ? ? ? 89 02 C3", -8)); return reinterpret_cast<decltype(RwD3D8GetRenderState)*>(get_pattern("8B 04 C5 ? ? ? ? 89 02 C3", -8));
} }
}(); }();

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
{ {

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 )

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <cstdint>
#include <functional> #include <functional>
#include <string> #include <string>

View file

@ -1,7 +1,7 @@
#include "TheFLAUtils.h" #include "TheFLAUtils.h"
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <Windows.h> #include <windows.h>
#include "Utils/ModuleList.hpp" #include "Utils/ModuleList.hpp"

View file

@ -1,6 +1,8 @@
#ifndef __TIMER #ifndef __TIMER
#define __TIMER #define __TIMER
#include <cmath>
class CTimer class CTimer
{ {
public: public:

@ -1 +1 @@
Subproject commit 95e523fa7494c0353b7ecfab408024a9d7b7e161 Subproject commit 70cab494523e76d56063b5044c34345c14803c96

File diff suppressed because it is too large Load diff

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

@ -12,7 +12,7 @@
#include <array> #include <array>
#include <memory> #include <memory>
#include <Shlwapi.h> #include <shlwapi.h>
#include "Utils/ModuleList.hpp" #include "Utils/ModuleList.hpp"
#include "Utils/Patterns.h" #include "Utils/Patterns.h"
@ -196,6 +196,7 @@ void ResetMousePos()
__declspec(naked) void M16StatsFix() __declspec(naked) void M16StatsFix()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
add eax, 0x34 add eax, 0x34
@ -204,11 +205,23 @@ __declspec(naked) void M16StatsFix()
inc dword ptr [ecx] inc dword ptr [ecx]
ret ret
} }
#else
__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; static const float fMinusOne = -1.0f;
__declspec(naked) void HeadlightsFix() __declspec(naked) void HeadlightsFix()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
fld dword ptr [esp+0x708-0x690] fld dword ptr [esp+0x708-0x690]
@ -226,6 +239,27 @@ __declspec(naked) void HeadlightsFix()
fld st fld st
jmp HeadlightsFix_JumpBack jmp HeadlightsFix_JumpBack
} }
#else
__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,6 +348,7 @@ float FixedRefValue()
__declspec(naked) void SubtitlesShadowFix() __declspec(naked) void SubtitlesShadowFix()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
push eax push eax
@ -322,10 +357,24 @@ __declspec(naked) void SubtitlesShadowFix()
fadd fShadowYSize fadd fShadowYSize
jmp SubtitlesShadowFix_JumpBack jmp SubtitlesShadowFix_JumpBack
} }
#else
__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
} }
__declspec(naked) void III_SensResetFix() __declspec(naked) void III_SensResetFix()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
mov ecx, 0x3A76 mov ecx, 0x3A76
@ -337,12 +386,26 @@ __declspec(naked) void III_SensResetFix()
fstp dword ptr [ebp+0x194] fstp dword ptr [ebp+0x194]
ret ret
} }
#else
__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);
__declspec(naked) void RadarBoundsCheckCoordBlip() __declspec(naked) void RadarBoundsCheckCoordBlip()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
mov edx, RadarBoundsCheckCoordBlip_Count mov edx, RadarBoundsCheckCoordBlip_Count
@ -357,11 +420,30 @@ __declspec(naked) void RadarBoundsCheckCoordBlip()
fcompp fcompp
ret ret
} }
#else
__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);
__declspec(naked) void RadarBoundsCheckEntityBlip() __declspec(naked) void RadarBoundsCheckEntityBlip()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
mov edx, RadarBoundsCheckCoordBlip_Count mov edx, RadarBoundsCheckCoordBlip_Count
@ -375,12 +457,29 @@ __declspec(naked) void RadarBoundsCheckEntityBlip()
or eax, -1 or eax, -1
ret ret
} }
#else
__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
} }
extern char** ppUserFilesDir = AddressByVersion<char**>(0x580C16, 0x580F66, 0x580E66); char** ppUserFilesDir = AddressByVersion<char**>(0x580C16, 0x580F66, 0x580E66);
static LARGE_INTEGER FrameTime; static LARGE_INTEGER FrameTime;
__declspec(safebuffers) int32_t GetTimeSinceLastFrame() NOBUFFERCHECKS int32_t GetTimeSinceLastFrame()
{ {
LARGE_INTEGER curTime; LARGE_INTEGER curTime;
QueryPerformanceCounter(&curTime); QueryPerformanceCounter(&curTime);
@ -413,6 +512,7 @@ unsigned int __cdecl AutoPilotTimerCalculation_III(unsigned int nTimer, int nSca
__declspec(naked) void AutoPilotTimerFix_III() __declspec(naked) void AutoPilotTimerFix_III()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
push dword ptr [esp + 0x4] push dword ptr [esp + 0x4]
@ -427,6 +527,23 @@ __declspec(naked) void AutoPilotTimerFix_III()
pop ebx pop ebx
ret 4 ret 4
} }
#else
__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
@ -543,7 +660,7 @@ namespace Localization
// ============= Call cDMAudio::IsAudioInitialised before adding one shot sounds, like in VC ============= // ============= Call cDMAudio::IsAudioInitialised before adding one shot sounds, like in VC =============
namespace AudioInitializedFix namespace AudioInitializedFix
{ {
auto IsAudioInitialised = static_cast<bool(*)()>(Memory::ReadCallFrom( hook::get_pattern( "E8 ? ? ? ? 84 C0 74 ? 0F B7 47 10" ) )); auto IsAudioInitialised = reinterpret_cast<bool(*)()>(Memory::ReadCallFrom( hook::get_pattern( "E8 ? ? ? ? 84 C0 74 ? 0F B7 47 10" ) ));
void* (*operatorNew)(size_t size); void* (*operatorNew)(size_t size);
void* operatorNew_InitializedCheck( size_t size ) void* operatorNew_InitializedCheck( size_t size )
@ -581,6 +698,7 @@ 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+0x50] mov ah, [ecx+0x50]
@ -594,6 +712,21 @@ namespace RemoveDriverStatusFix
DontSetStatus: DontSetStatus:
ret ret
} }
#else
__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
} }
} }
@ -626,6 +759,7 @@ namespace EvasiveDiveFix
__declspec(naked) static void CalculateAngle_Hook() __declspec(naked) static void CalculateAngle_Hook()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
push dword ptr [esi+0x7C] push dword ptr [esi+0x7C]
@ -636,6 +770,19 @@ namespace EvasiveDiveFix
mov ecx, ebp mov ecx, ebp
ret ret
} }
#else
__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
} }
} }
@ -648,27 +795,48 @@ 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
} }
#else
__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
} }
#else
__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
@ -678,6 +846,18 @@ namespace NullTerminatedLines
add ecx, [esp+0xAC-0x98] add ecx, [esp+0xAC-0x98]
ret ret
} }
#else
__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
} }
} }
@ -704,6 +884,7 @@ 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
@ -715,6 +896,21 @@ namespace DodoKeyboardControls
CheatDisabled: CheatDisabled:
ret ret
} }
#else
__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
} }
} }
@ -722,7 +918,7 @@ namespace DodoKeyboardControls
// ============= Resetting stats and variables on New Game ============= // ============= Resetting stats and variables on New Game =============
namespace VariableResets namespace VariableResets
{ {
static auto TimerInitialise = reinterpret_cast<void(*)()>(hook::get_pattern("83 E4 F8 68 ? ? ? ? E8", -6)); static void (*TimerInitialise)();
using VarVariant = std::variant< bool*, int* >; using VarVariant = std::variant< bool*, int* >;
std::vector<VarVariant> GameVariablesToReset; std::vector<VarVariant> GameVariablesToReset;
@ -736,8 +932,6 @@ namespace VariableResets
}, var ); }, var );
} }
// Functions that should have been called by the game but aren't...
TimerInitialise();
PurpleNinesGlitchFix(); PurpleNinesGlitchFix();
} }
@ -757,8 +951,22 @@ namespace VariableResets
void GameInitialise(const char* path) void GameInitialise(const char* path)
{ {
ReInitOurVariables(); ReInitOurVariables();
TimerInitialise();
orgGameInitialise(path); orgGameInitialise(path);
} }
static void (__fastcall* DestroyAllGameCreatedEntities)(void* DMAudio);
template<std::size_t Index>
static void (__fastcall* orgService)(void* DMAudio);
template<std::size_t Index>
static void __fastcall Service_AndDestroyEntities(void* DMAudio)
{
DestroyAllGameCreatedEntities(DMAudio);
orgService<Index>(DMAudio);
}
HOOK_EACH_INIT(Service, orgService, Service_AndDestroyEntities);
} }
@ -771,6 +979,7 @@ namespace GenerateNewPickup_ReuseObjectFix
__declspec(naked) static void GiveUsAPickUpObject_CleanUpObject() __declspec(naked) static void GiveUsAPickUpObject_CleanUpObject()
{ {
#ifdef _MSC_VER
_asm _asm
{ {
mov eax, pPickupObject mov eax, pPickupObject
@ -796,6 +1005,36 @@ namespace GenerateNewPickup_ReuseObjectFix
NoPickup: NoPickup:
jmp orgGiveUsAPickUpObject jmp orgGiveUsAPickUpObject
} }
#else
__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
} }
} }
@ -1028,7 +1267,7 @@ namespace SlidingTextsScalingFixes
static inline float** pHorShadowValue; static inline float** pHorShadowValue;
template<std::size_t Index> template<std::size_t Index>
static void (*orgPrintString)(float,float,const wchar_t*); STATIC_INLINE void (*orgPrintString)(float,float,const wchar_t*);
template<std::size_t Index> template<std::size_t Index>
static void PrintString_Slide(float fX, float fY, const wchar_t* pText) static void PrintString_Slide(float fX, float fY, const wchar_t* pText)
@ -1055,7 +1294,7 @@ namespace SlidingTextsScalingFixes
static inline bool bSlidingEnabled = false; static inline bool bSlidingEnabled = false;
template<std::size_t Index> template<std::size_t Index>
static void (*orgPrintString)(float,float,const wchar_t*); STATIC_INLINE void (*orgPrintString)(float,float,const wchar_t*);
template<std::size_t Index> template<std::size_t Index>
static void PrintString_Slide(float fX, float fY, const wchar_t* pText) static void PrintString_Slide(float fX, float fY, const wchar_t* pText)
@ -2354,8 +2593,22 @@ void Patch_III_Common()
get_pattern("C6 05 ? ? ? ? ? E8 ? ? ? ? C7 05", 7) get_pattern("C6 05 ? ? ? ? ? E8 ? ? ? ? C7 05", 7)
}; };
TimerInitialise = reinterpret_cast<decltype(TimerInitialise)>(get_pattern("83 E4 F8 68 ? ? ? ? E8", -6));
// In GTA III, we also need to backport one more fix from VC to avoid issues with looping audio entities:
// CMenuManager::DoSettingsBeforeStartingAGame needs to call cDMAudio::DestroyAllGameCreatedEntities
DestroyAllGameCreatedEntities = reinterpret_cast<decltype(DestroyAllGameCreatedEntities)>(ReadCallFrom(
get_pattern("B9 ? ? ? ? E8 ? ? ? ? 31 DB BD ? ? ? ? 8D 40 00", 5)));
auto audio_service = pattern("B9 ? ? ? ? E8 ? ? ? ? B9 ? ? ? ? C6 05 ? ? ? ? ? E8").count(2);
std::array<void*, 2> audio_service_instances = {
audio_service.get(0).get<void>(5),
audio_service.get(1).get<void>(5),
};
InterceptCall(game_initialise, orgGameInitialise, GameInitialise); InterceptCall(game_initialise, orgGameInitialise, GameInitialise);
HookEach_ReInitGameObjectVariables(reinit_game_object_variables, InterceptCall); HookEach_ReInitGameObjectVariables(reinit_game_object_variables, InterceptCall);
HookEach_Service(audio_service_instances, InterceptCall);
// Variables to reset // Variables to reset
GameVariablesToReset.emplace_back(*get_pattern<bool*>("80 3D ? ? ? ? ? 74 2A", 2)); // Free resprays GameVariablesToReset.emplace_back(*get_pattern<bool*>("80 3D ? ? ? ? ? 74 2A", 2)); // Free resprays

View file

@ -2,7 +2,7 @@
#define __AUDIOHARDWARE #define __AUDIOHARDWARE
// IStream // IStream
#include <Objidl.h> #include <objidl.h>
enum eDecoderType enum eDecoderType
{ {

View file

@ -3,8 +3,8 @@
#include "AudioHardwareSA.h" #include "AudioHardwareSA.h"
// libflac // libflac
#include "FLAC\stream_decoder.h" #include "FLAC/stream_decoder.h"
#include "FLAC\metadata.h" #include "FLAC/metadata.h"
class CAEFLACDecoder final : public CAEStreamingDecoder class CAEFLACDecoder final : public CAEStreamingDecoder
{ {

View file

@ -2,6 +2,7 @@
#define __GENERAL #define __GENERAL
#include <stdint.h> #include <stdint.h>
#include "Common.h"
#include "TheFLAUtils.h" #include "TheFLAUtils.h"
class CSimpleTransform class CSimpleTransform

View file

@ -3,9 +3,9 @@
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <d3d9.h> #include <d3d9.h>
#include <Shlwapi.h> #include <shlwapi.h>
#include <ShlObj.h> #include <shlobj.h>
#include <ShellAPI.h> #include <shellapi.h>
#include <cinttypes> #include <cinttypes>
#include "ScriptSA.h" #include "ScriptSA.h"
@ -950,7 +950,7 @@ char* GetMyDocumentsPathSA()
} }
static LARGE_INTEGER FrameTime; static LARGE_INTEGER FrameTime;
__declspec(safebuffers) int32_t GetTimeSinceLastFrame() NOBUFFERCHECKS int32_t GetTimeSinceLastFrame()
{ {
LARGE_INTEGER curTime; LARGE_INTEGER curTime;
QueryPerformanceCounter(&curTime); QueryPerformanceCounter(&curTime);
@ -2851,7 +2851,7 @@ namespace CreditsScalingFixes
static const unsigned int FIXED_RES_HEIGHT_SCALE = 448; static const unsigned int FIXED_RES_HEIGHT_SCALE = 448;
template<std::size_t Index> template<std::size_t Index>
static void (*orgPrintString)(float,float,const wchar_t*); STATIC_INLINE void (*orgPrintString)(float,float,const wchar_t*);
template<std::size_t Index> template<std::size_t Index>
static void PrintString_ScaleY(float fX, float fY, const wchar_t* pText) static void PrintString_ScaleY(float fX, float fY, const wchar_t* pText)
@ -2888,7 +2888,7 @@ namespace SlidingTextsScalingFixes
static inline bool bSlidingEnabled = false; static inline bool bSlidingEnabled = false;
template<std::size_t Index> template<std::size_t Index>
static void (*orgPrintString)(float,float,const wchar_t*); STATIC_INLINE void (*orgPrintString)(float,float,const wchar_t*);
template<std::size_t Index> template<std::size_t Index>
static void PrintString_Slide(float fX, float fY, const wchar_t* pText) static void PrintString_Slide(float fX, float fY, const wchar_t* pText)
@ -2898,7 +2898,7 @@ namespace SlidingTextsScalingFixes
} }
template<std::size_t Index> template<std::size_t Index>
static void (*orgSetRightJustifyWrap)(float wrap); STATIC_INLINE void (*orgSetRightJustifyWrap)(float wrap);
template<std::size_t Index> template<std::size_t Index>
static void SetRightJustifyWrap_Slide(float wrap) static void SetRightJustifyWrap_Slide(float wrap)
@ -2915,7 +2915,7 @@ namespace SlidingTextsScalingFixes
static inline bool bSlidingEnabled = false; static inline bool bSlidingEnabled = false;
template<std::size_t Index> template<std::size_t Index>
static void (*orgPrintString)(float,float,const wchar_t*); STATIC_INLINE void (*orgPrintString)(float,float,const wchar_t*);
template<std::size_t Index> template<std::size_t Index>
static void PrintString_Slide(float fX, float fY, const wchar_t* pText) static void PrintString_Slide(float fX, float fY, const wchar_t* pText)
@ -3960,7 +3960,7 @@ __declspec(naked) void DarkVehiclesFix4()
} }
// 1.0 ONLY ENDS HERE // 1.0 ONLY ENDS HERE
__declspec(safebuffers) static int _Timers_ftol_internal( double timer, double& remainder ) NOBUFFERCHECKS static int _Timers_ftol_internal( double timer, double& remainder )
{ {
double integral; double integral;
remainder = modf( timer + remainder, &integral ); remainder = modf( timer + remainder, &integral );
@ -7680,7 +7680,7 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
// Fixed escalators crash // Fixed escalators crash
try try
{ {
orgEscalatorsUpdate = static_cast<decltype(orgEscalatorsUpdate)>(get_pattern( "80 3D ? ? ? ? ? 74 23 56" )); orgEscalatorsUpdate = reinterpret_cast<decltype(orgEscalatorsUpdate)>(get_pattern( "80 3D ? ? ? ? ? 74 23 56" ));
auto updateEscalators = get_pattern("80 3D ? ? ? ? ? 74 22 56"); auto updateEscalators = get_pattern("80 3D ? ? ? ? ? 74 22 56");
auto removeEscalatorsForEntity = pattern( "80 7E F5 00 74 56" ).get_one(); auto removeEscalatorsForEntity = pattern( "80 7E F5 00 74 56" ).get_one();
@ -8539,7 +8539,7 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
ppRWD3D9 = *get_pattern<IDirect3D9**>("33 ED A3 ? ? ? ? 3B C5", 2 + 1); ppRWD3D9 = *get_pattern<IDirect3D9**>("33 ED A3 ? ? ? ? 3B C5", 2 + 1);
FrontEndMenuManager = *get_pattern<void**>("50 50 68 ? ? ? ? B9 ? ? ? ? E8", 7 + 1); // This has 2 identical matches, we just need one FrontEndMenuManager = *get_pattern<void**>("50 50 68 ? ? ? ? B9 ? ? ? ? E8", 7 + 1); // This has 2 identical matches, we just need one
orgGetDocumentsPath = static_cast<char*(*)()>(get_pattern( "8D 45 FC 50 68 19 00 02 00", -6 )); orgGetDocumentsPath = reinterpret_cast<char*(*)()>(get_pattern( "8D 45 FC 50 68 19 00 02 00", -6 ));
Patch(dialogBoxParam, &pDialogBoxParamA_New); Patch(dialogBoxParam, &pDialogBoxParamA_New);
Patch(setFocus, &pSetFocus_NOP); Patch(setFocus, &pSetFocus_NOP);

View file

@ -302,7 +302,7 @@ public:
private: private:
template<std::size_t Index> template<std::size_t Index>
static void (CVehicle::*orgDoHeadLightBeam)(int type, CMatrix& m, bool right); STATIC_INLINE void (CVehicle::*orgDoHeadLightBeam)(int type, CMatrix& m, bool right);
template<std::size_t Index> template<std::size_t Index>
void DoHeadLightBeam_LightBeamFixSaveObj(int type, CMatrix& m, bool right) void DoHeadLightBeam_LightBeamFixSaveObj(int type, CMatrix& m, bool right)
@ -337,7 +337,7 @@ public:
public: public:
template<std::size_t Index> template<std::size_t Index>
static void (CAutomobile::*orgAutomobilePreRender)(); STATIC_INLINE void (CAutomobile::*orgAutomobilePreRender)();
template<std::size_t Index> template<std::size_t Index>
void PreRender_SilentPatch() void PreRender_SilentPatch()
@ -352,7 +352,7 @@ public:
void HideDestroyedWheels_SilentPatch(void (CAutomobile::*spawnFlyingComponentCB)(int, unsigned int), int nodeID, unsigned int modelID); void HideDestroyedWheels_SilentPatch(void (CAutomobile::*spawnFlyingComponentCB)(int, unsigned int), int nodeID, unsigned int modelID);
template<std::size_t Index> template<std::size_t Index>
static void (CAutomobile::*orgSpawnFlyingComponent)(int, unsigned int); STATIC_INLINE void (CAutomobile::*orgSpawnFlyingComponent)(int, unsigned int);
template<std::size_t Index> template<std::size_t Index>
void SpawnFlyingComponent_HideWheels(int nodeID, unsigned int modelID) void SpawnFlyingComponent_HideWheels(int nodeID, unsigned int modelID)
@ -448,7 +448,7 @@ private:
private: private:
template<std::size_t Index> template<std::size_t Index>
static CVehicle* (CStoredCar::*orgRestoreCar)(); STATIC_INLINE CVehicle* (CStoredCar::*orgRestoreCar)();
template<std::size_t Index> template<std::size_t Index>
CVehicle* RestoreCar_SilentPatch() CVehicle* RestoreCar_SilentPatch()

View file

@ -16,7 +16,7 @@
#include <array> #include <array>
#include <memory> #include <memory>
#include <Shlwapi.h> #include <shlwapi.h>
#include <time.h> #include <time.h>
#include "Utils/ModuleList.hpp" #include "Utils/ModuleList.hpp"
@ -356,7 +356,7 @@ namespace RadarTraceOutlineFixes
} }
template<std::size_t Index> template<std::size_t Index>
static void (*orgShowRadarTraceWithHeight)(float, float, unsigned int, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char); STATIC_INLINE void (*orgShowRadarTraceWithHeight)(float, float, unsigned int, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char);
template<std::size_t Index> template<std::size_t Index>
static void ShowRadarTraceWithHeight_RecalculatePositions(float a1, float a2, unsigned int a3, unsigned char a4, unsigned char a5, unsigned char a6, unsigned char a7, unsigned char a8) static void ShowRadarTraceWithHeight_RecalculatePositions(float a1, float a2, unsigned int a3, unsigned char a4, unsigned char a5, unsigned char a6, unsigned char a7, unsigned char a8)
@ -456,7 +456,7 @@ namespace SlidingTextsScalingFixes
static inline bool bSlidingEnabled = false; static inline bool bSlidingEnabled = false;
template<std::size_t Index> template<std::size_t Index>
static void (*orgPrintString)(float,float,const wchar_t*); STATIC_INLINE void (*orgPrintString)(float,float,const wchar_t*);
template<std::size_t Index> template<std::size_t Index>
static void PrintString_Slide(float fX, float fY, const wchar_t* pText) static void PrintString_Slide(float fX, float fY, const wchar_t* pText)
@ -466,7 +466,7 @@ namespace SlidingTextsScalingFixes
} }
template<std::size_t Index> template<std::size_t Index>
static void (*orgSetRightJustifyWrap)(float wrap); STATIC_INLINE void (*orgSetRightJustifyWrap)(float wrap);
template<std::size_t Index> template<std::size_t Index>
static void SetRightJustifyWrap_Slide(float wrap) static void SetRightJustifyWrap_Slide(float wrap)
@ -483,7 +483,7 @@ namespace SlidingTextsScalingFixes
static inline bool bSlidingEnabled = false; static inline bool bSlidingEnabled = false;
template<std::size_t Index> template<std::size_t Index>
static void (*orgPrintString)(float,float,const wchar_t*); STATIC_INLINE void (*orgPrintString)(float,float,const wchar_t*);
template<std::size_t Index> template<std::size_t Index>
static void PrintString_Slide(float fX, float fY, const wchar_t* pText) static void PrintString_Slide(float fX, float fY, const wchar_t* pText)
@ -671,6 +671,7 @@ float FixedRefValue()
__declspec(naked) void SubtitlesShadowFix() __declspec(naked) void SubtitlesShadowFix()
{ {
#ifdef MSC_VER
_asm _asm
{ {
mov [esp], eax mov [esp], eax
@ -683,10 +684,33 @@ __declspec(naked) void SubtitlesShadowFix()
call Recalculate call Recalculate
jmp SubtitlesShadowFix_JumpBack jmp SubtitlesShadowFix_JumpBack
} }
#else
__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);
} }
__declspec(naked) void CreateInstance_BikeFix() __declspec(naked) void CreateInstance_BikeFix()
{ {
#ifdef MSC_VER
_asm _asm
{ {
push eax push eax
@ -694,12 +718,22 @@ __declspec(naked) void CreateInstance_BikeFix()
call CVehicleModelInfo::GetExtrasFrame call CVehicleModelInfo::GetExtrasFrame
ret ret
} }
#else
__asm__ volatile
(
"push eax\n"
"mov ecx, ebp\n"
"call %[CVehicleModelInfo_GetExtrasFrame]\n"
"ret"
:: [CVehicleModelInfo_GetExtrasFrame] "i" (CVehicleModelInfo_GetExtrasFrame)
);
#endif
} }
extern char** ppUserFilesDir = AddressByVersion<char**>(0x6022AA, 0x60228A, 0x601ECA); char** ppUserFilesDir = AddressByVersion<char**>(0x6022AA, 0x60228A, 0x601ECA);
static LARGE_INTEGER FrameTime; static LARGE_INTEGER FrameTime;
__declspec(safebuffers) int32_t GetTimeSinceLastFrame() NOBUFFERCHECKS int32_t GetTimeSinceLastFrame()
{ {
LARGE_INTEGER curTime; LARGE_INTEGER curTime;
QueryPerformanceCounter(&curTime); QueryPerformanceCounter(&curTime);
@ -733,6 +767,7 @@ unsigned int __cdecl AutoPilotTimerCalculation_VC(unsigned int nTimer, int nScal
__declspec(naked) void AutoPilotTimerFix_VC() __declspec(naked) void AutoPilotTimerFix_VC()
{ {
#ifdef MSC_VER
_asm _asm
{ {
push dword ptr [esp + 0xC] push dword ptr [esp + 0xC]
@ -746,6 +781,22 @@ __declspec(naked) void AutoPilotTimerFix_VC()
pop ebx pop ebx
ret 4 ret 4
} }
#else
__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
} }
@ -866,6 +917,7 @@ namespace SirenSwitchingFix
{ {
__declspec(naked) static void IsFBIRanchOrFBICar() __declspec(naked) static void IsFBIRanchOrFBICar()
{ {
#ifdef MSC_VER
_asm _asm
{ {
mov dword ptr [esi+0x1C], 0x1C mov dword ptr [esi+0x1C], 0x1C
@ -882,6 +934,24 @@ namespace SirenSwitchingFix
xor al, al xor al, al
ret ret
} }
#else
__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
} }
} }
@ -950,6 +1020,7 @@ 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+0x50] mov cl, [ebx+0x50]
@ -963,6 +1034,21 @@ namespace RemoveDriverStatusFix
DontSetStatus: DontSetStatus:
ret ret
} }
#else
__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
} }
} }
@ -1035,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
} }
#else
__asm__ volatile
(
"mov eax, [esp+4]\n"
"mov byte ptr [eax+ecx], 0\n"
"jmp %[orgSscanf_LoadPath]"
:: [orgSscanf_LoadPath] "m" (orgSscanf_LoadPath)
);
#endif
} }
} }
@ -1065,16 +1161,26 @@ namespace PickupEffectsFixes
{ {
__declspec(naked) static void PickUpEffects_BigDollarColor() __declspec(naked) static void PickUpEffects_BigDollarColor()
{ {
#ifdef MSC_VER
_asm _asm
{ {
mov byte ptr [esp+0x184-0x170], 0 mov byte ptr [esp+0x184-0x170], 0
mov dword ptr [esp+0x184-0x174], 37 mov dword ptr [esp+0x184-0x174], 37
ret ret
} }
#else
__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
@ -1090,6 +1196,23 @@ namespace PickupEffectsFixes
mov ebx, ecx mov ebx, ecx
ret ret
} }
#else
__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
} }
} }
@ -1106,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
@ -1126,6 +1250,31 @@ namespace IsPlayerTargettingCharFix
xor al, al xor al, al
ret ret
} }
#else
__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
} }
} }
@ -1133,7 +1282,7 @@ namespace IsPlayerTargettingCharFix
// ============= Resetting stats and variables on New Game ============= // ============= Resetting stats and variables on New Game =============
namespace VariableResets namespace VariableResets
{ {
static auto TimerInitialise = reinterpret_cast<void(*)()>(hook::get_pattern("83 E4 F8 68 ? ? ? ? E8", -6)); static void (*TimerInitialise)();
using VarVariant = std::variant< bool*, int* >; using VarVariant = std::variant< bool*, int* >;
std::vector<VarVariant> GameVariablesToReset; std::vector<VarVariant> GameVariablesToReset;
@ -1146,9 +1295,6 @@ namespace VariableResets
*v = {}; *v = {};
}, var ); }, var );
} }
// Functions that should have been called by the game but aren't...
TimerInitialise();
} }
template<std::size_t Index> template<std::size_t Index>
@ -1167,6 +1313,7 @@ namespace VariableResets
void GameInitialise(const char* path) void GameInitialise(const char* path)
{ {
ReInitOurVariables(); ReInitOurVariables();
TimerInitialise();
orgGameInitialise(path); orgGameInitialise(path);
} }
} }
@ -1211,6 +1358,7 @@ 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
@ -1218,6 +1366,16 @@ namespace SelectableBackfaceCulling
cmp dword ptr [ebx+0x4C], 0 cmp dword ptr [ebx+0x4C], 0
jmp EntityRender_Prologue_JumpBack jmp EntityRender_Prologue_JumpBack
} }
#else
__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)
@ -1393,6 +1551,7 @@ namespace TommyFistShakeWithWeapons
__declspec(naked) static void CheckWeaponGroupHook() __declspec(naked) static void CheckWeaponGroupHook()
{ {
#ifdef MSC_VER
_asm _asm
{ {
push dword ptr [eax] push dword ptr [eax]
@ -1401,6 +1560,17 @@ namespace TommyFistShakeWithWeapons
test al, al test al, al
ret ret
} }
#else
__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>
@ -1876,7 +2046,7 @@ void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModule
// Stuff to let us (re)initialize // Stuff to let us (re)initialize
static void (*HUDReInitialise)() = static_cast<decltype(HUDReInitialise)>(get_pattern("31 C0 53 0F EF C0 C6 05")); static void (*HUDReInitialise)() = reinterpret_cast<decltype(HUDReInitialise)>(get_pattern("31 C0 53 0F EF C0 C6 05"));
// This pattern has 5 hits - first 2 are in Reinitialise, the rest is in Initialise // This pattern has 5 hits - first 2 are in Reinitialise, the rest is in Initialise
auto reinitialise1 = pattern("C7 05 ? ? ? ? 05 00 00 00 66 C7 05 ? ? ? ? 00 00 C7 05 ? ? ? ? 00 00 00 00").count(5); auto reinitialise1 = pattern("C7 05 ? ? ? ? 05 00 00 00 66 C7 05 ? ? ? ? 00 00 C7 05 ? ? ? ? 00 00 00 00").count(5);
@ -2759,7 +2929,7 @@ void Patch_VC_Common()
using namespace IsPlayerTargettingCharFix; using namespace IsPlayerTargettingCharFix;
auto isPlayerTargettingChar = pattern("83 7C 24 ? ? A3 ? ? ? ? 0F 84").get_one(); auto isPlayerTargettingChar = pattern("83 7C 24 ? ? A3 ? ? ? ? 0F 84").get_one();
auto using1stPersonWeaponMode = static_cast<decltype(Using1stPersonWeaponMode)>(get_pattern("66 83 F8 07 74 18", -7)); auto using1stPersonWeaponMode = reinterpret_cast<decltype(Using1stPersonWeaponMode)>(get_pattern("66 83 F8 07 74 18", -7));
bool* useMouse3rdPerson = *get_pattern<bool*>("80 3D ? ? ? ? ? 75 09 66 C7 05 ? ? ? ? ? ? 8B 35", 2); bool* useMouse3rdPerson = *get_pattern<bool*>("80 3D ? ? ? ? ? 75 09 66 C7 05 ? ? ? ? ? ? 8B 35", 2);
void* theCamera = *get_pattern<void*>("B9 ? ? ? ? 31 DB E8", 1); void* theCamera = *get_pattern<void*>("B9 ? ? ? ? 31 DB E8", 1);
@ -2798,6 +2968,8 @@ void Patch_VC_Common()
get_pattern("C6 05 ? ? ? ? ? E8 ? ? ? ? C7 05", 7) get_pattern("C6 05 ? ? ? ? ? E8 ? ? ? ? C7 05", 7)
}; };
TimerInitialise = reinterpret_cast<decltype(TimerInitialise)>(get_pattern("83 E4 F8 68 ? ? ? ? E8", -6));
InterceptCall(game_initialise, orgGameInitialise, GameInitialise); InterceptCall(game_initialise, orgGameInitialise, GameInitialise);
HookEach_ReInitGameObjectVariables(reinit_game_object_variables, InterceptCall); HookEach_ReInitGameObjectVariables(reinit_game_object_variables, InterceptCall);

View file

@ -6,7 +6,7 @@
<SILENTPATCH_EXT>.asi</SILENTPATCH_EXT> <SILENTPATCH_EXT>.asi</SILENTPATCH_EXT>
<SILENTPATCH_FULL_NAME>SilentPatch for Vice City</SILENTPATCH_FULL_NAME> <SILENTPATCH_FULL_NAME>SilentPatch for Vice City</SILENTPATCH_FULL_NAME>
<SILENTPATCH_REVISION_ID>11</SILENTPATCH_REVISION_ID> <SILENTPATCH_REVISION_ID>11</SILENTPATCH_REVISION_ID>
<SILENTPATCH_BUILD_ID>1</SILENTPATCH_BUILD_ID> <SILENTPATCH_BUILD_ID>2</SILENTPATCH_BUILD_ID>
<SILENTPATCH_COPYRIGHT>2013-2024</SILENTPATCH_COPYRIGHT> <SILENTPATCH_COPYRIGHT>2013-2024</SILENTPATCH_COPYRIGHT>
</PropertyGroup> </PropertyGroup>
<PropertyGroup /> <PropertyGroup />