VC: Disabled backface culling on detached car parts

Fixes #25
This commit is contained in:
Silent 2024-05-17 17:35:46 +02:00
parent d4374df50a
commit 96bc50ee26
No known key found for this signature in database
GPG Key ID: AE53149BB0C45AF1
14 changed files with 129 additions and 46 deletions

View File

@ -1,5 +1,3 @@
#include "RWGTA.h"
#include "Utils/MemoryMgr.h" #include "Utils/MemoryMgr.h"
#include "Utils/Patterns.h" #include "Utils/Patterns.h"
@ -17,21 +15,25 @@ void** rwengine = []() -> void** {
// Thanks Steam III... // Thanks Steam III...
// Locate RwRenderStateSet // Locate RwRenderStateSet
auto renderStateSetPtr = hook::get_pattern( "D1 7C 24 2C", 4 ); try
auto renderStateSet = reinterpret_cast<uintptr_t>(Memory::ReadCallFrom( renderStateSetPtr ));
// Test III 1.0/1.1/VC
if ( *reinterpret_cast<uint8_t*>(renderStateSet) == 0xA1 )
{ {
return *reinterpret_cast<void***>(renderStateSet + 1); auto renderStateSetPtr = hook::txn::get_pattern( "D1 7C 24 2C", 4 );
} auto renderStateSet = reinterpret_cast<uintptr_t>(Memory::ReadCallFrom( renderStateSetPtr ));
// Test III Steam // Test III 1.0/1.1/VC
renderStateSet += 3; if ( *reinterpret_cast<uint8_t*>(renderStateSet) == 0xA1 )
if ( *reinterpret_cast<uint8_t*>(renderStateSet) == 0xA1 ) {
{ return *reinterpret_cast<void***>(renderStateSet + 1);
return *reinterpret_cast<void***>(renderStateSet + 1); }
// Test III Steam
renderStateSet += 3;
if ( *reinterpret_cast<uint8_t*>(renderStateSet) == 0xA1 )
{
return *reinterpret_cast<void***>(renderStateSet + 1);
}
} }
TXN_CATCH();
assert(!"Could not locate RwEngineInstance!"); assert(!"Could not locate RwEngineInstance!");
return nullptr; return nullptr;
@ -52,5 +54,15 @@ RwReal RwIm2DGetNearScreenZ()
return RWSRCGLOBAL(dOpenDevice).zBufferNear; return RWSRCGLOBAL(dOpenDevice).zBufferNear;
} }
RwBool RwRenderStateGet(RwRenderState state, void *value)
{
return RWSRCGLOBAL(dOpenDevice).fpRenderStateGet(state, value);
}
RwBool RwRenderStateSet(RwRenderState state, void *value)
{
return RWSRCGLOBAL(dOpenDevice).fpRenderStateSet(state, value);
}
// Unreachable stub // Unreachable stub
RwBool RwMatrixDestroy(RwMatrix* mpMat) { assert(!"Unreachable!"); return TRUE; } RwBool RwMatrixDestroy(RwMatrix* mpMat) { assert(!"Unreachable!"); return TRUE; }

View File

@ -1 +0,0 @@
#pragma once

View File

@ -3,26 +3,25 @@
#include <rwcore.h> #include <rwcore.h>
#include <rpworld.h> #include <rpworld.h>
template<RwRenderState State>
class RwScopedRenderState class RwScopedRenderState
{ {
public: public:
RwScopedRenderState( RwRenderState state ) explicit RwScopedRenderState()
: m_state( state )
{ {
[[maybe_unused]] RwBool result = RwRenderStateGet( m_state, &m_value ); [[maybe_unused]] RwBool result = RwRenderStateGet( State, &m_value );
assert( result != FALSE ); assert( result != FALSE );
} }
~RwScopedRenderState() ~RwScopedRenderState()
{ {
[[maybe_unused]] RwBool result = RwRenderStateSet( m_state, m_value ); [[maybe_unused]] RwBool result = RwRenderStateSet( State, m_value );
assert( result != FALSE ); assert( result != FALSE );
} }
private:
RwScopedRenderState( const RwScopedRenderState& ) = delete; RwScopedRenderState( const RwScopedRenderState& ) = delete;
const RwRenderState m_state; private:
void* m_value = nullptr; void* m_value = nullptr;
}; };

View File

@ -66,7 +66,6 @@
<ClInclude Include="..\SilentPatch\debugmenu_public.h" /> <ClInclude Include="..\SilentPatch\debugmenu_public.h" />
<ClInclude Include="..\SilentPatch\Desktop.h" /> <ClInclude Include="..\SilentPatch\Desktop.h" />
<ClInclude Include="..\SilentPatch\Maths.h" /> <ClInclude Include="..\SilentPatch\Maths.h" />
<ClInclude Include="..\SilentPatch\RWGTA.h" />
<ClInclude Include="..\SilentPatch\StdAfx.h" /> <ClInclude Include="..\SilentPatch\StdAfx.h" />
<ClInclude Include="..\SilentPatch\StoredCar.h" /> <ClInclude Include="..\SilentPatch\StoredCar.h" />
<ClInclude Include="..\SilentPatch\SVF.h" /> <ClInclude Include="..\SilentPatch\SVF.h" />

View File

@ -89,9 +89,6 @@
<ClInclude Include="..\SilentPatch\debugmenu_public.h"> <ClInclude Include="..\SilentPatch\debugmenu_public.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\SilentPatch\RWGTA.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\SilentPatch\Maths.h"> <ClInclude Include="..\SilentPatch\Maths.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>

View File

@ -69,10 +69,10 @@ void CObject::Render()
std::pair<void**,void*> materialRestoreData[256]; std::pair<void**,void*> materialRestoreData[256];
size_t numMaterialsToRestore = 0; size_t numMaterialsToRestore = 0;
RwScopedRenderState cullState(rwRENDERSTATECULLMODE); RwScopedRenderState<rwRENDERSTATECULLMODE> cullState;
const int32_t carPartModelIndex = m_wCarPartModelIndex.Get(); const int32_t carPartModelIndex = m_wCarPartModelIndex.Get();
if ( carPartModelIndex != -1 && m_objectCreatedBy == TEMP_OBJECT && bObjectFlag7 && RwObjectGetType(m_pRwObject) == rpATOMIC ) if ( carPartModelIndex != -1 && m_objectCreatedBy == TEMP_OBJECT && bUseVehicleColours && RwObjectGetType(m_pRwObject) == rpATOMIC )
{ {
auto* pData = materialRestoreData; auto* pData = materialRestoreData;

View File

@ -260,7 +260,7 @@ public:
bool bObjectFlag4 : 1; bool bObjectFlag4 : 1;
bool bObjectFlag5 : 1; bool bObjectFlag5 : 1;
bool m_bIsExploded : 1; bool m_bIsExploded : 1;
bool bObjectFlag7 : 1; bool bUseVehicleColours : 1;
bool m_bIsLampPost : 1; bool m_bIsLampPost : 1;
bool m_bIsTargetable : 1; bool m_bIsTargetable : 1;
bool m_bIsBroken : 1; bool m_bIsBroken : 1;

View File

@ -68,7 +68,7 @@ void CPed::RenderWeapon(bool bWeapon, bool bMuzzleFlash, bool bForShadow)
if ( bMuzzleFlash && m_pMuzzleFlashFrame != nullptr ) if ( bMuzzleFlash && m_pMuzzleFlashFrame != nullptr )
{ {
RwScopedRenderState zWrite(rwRENDERSTATEZWRITEENABLE); RwScopedRenderState<rwRENDERSTATEZWRITEENABLE> zWrite;
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE);
SetGunFlashAlpha(bRightGun); SetGunFlashAlpha(bRightGun);

View File

@ -375,7 +375,7 @@ static RpAtomic* RenderAtomic(RpAtomic* pAtomic, float fComp)
static RpAtomic* StaticPropellerRender(RpAtomic* pAtomic) static RpAtomic* StaticPropellerRender(RpAtomic* pAtomic)
{ {
RwScopedRenderState alphaRef(rwRENDERSTATEALPHATESTFUNCTIONREF); RwScopedRenderState<rwRENDERSTATEALPHATESTFUNCTIONREF> alphaRef;
RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, 0); RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, 0);
pAtomic = AtomicDefaultRenderCallBack(pAtomic); pAtomic = AtomicDefaultRenderCallBack(pAtomic);
@ -385,8 +385,8 @@ static RpAtomic* StaticPropellerRender(RpAtomic* pAtomic)
static RpAtomic* MovingPropellerRender(RpAtomic* pAtomic) static RpAtomic* MovingPropellerRender(RpAtomic* pAtomic)
{ {
RwScopedRenderState alphaRef(rwRENDERSTATEALPHATESTFUNCTIONREF); RwScopedRenderState<rwRENDERSTATEALPHATESTFUNCTIONREF> alphaRef;
RwScopedRenderState vertexAlpha(rwRENDERSTATEVERTEXALPHAENABLE); RwScopedRenderState<rwRENDERSTATEVERTEXALPHAENABLE> vertexAlpha;
RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, 0); RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, 0);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast<void*>(TRUE)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast<void*>(TRUE));
@ -430,9 +430,9 @@ void RenderWeapon(CPed* pPed)
void RenderWeaponPedsForPC() void RenderWeaponPedsForPC()
{ {
RwScopedRenderState vertexAlpha(rwRENDERSTATEVERTEXALPHAENABLE); RwScopedRenderState<rwRENDERSTATEVERTEXALPHAENABLE> vertexAlpha;
RwScopedRenderState zWrite(rwRENDERSTATEZWRITEENABLE); RwScopedRenderState<rwRENDERSTATEZWRITEENABLE> zWrite;
RwScopedRenderState fogEnable(rwRENDERSTATEFOGENABLE); RwScopedRenderState<rwRENDERSTATEFOGENABLE> fogEnable;
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast<void*>(TRUE)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast<void*>(TRUE));
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, reinterpret_cast<void*>(TRUE)); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, reinterpret_cast<void*>(TRUE));
@ -1869,7 +1869,7 @@ namespace StaticShadowAlphaFix
static void (*orgRenderStaticShadows)(); static void (*orgRenderStaticShadows)();
static void RenderStaticShadows_StateFix() static void RenderStaticShadows_StateFix()
{ {
RwScopedRenderState state(rwRENDERSTATEALPHATESTFUNCTION); RwScopedRenderState<rwRENDERSTATEALPHATESTFUNCTION> state;
RwRenderStateSet( rwRENDERSTATEALPHATESTFUNCTION, (void*)rwALPHATESTFUNCTIONALWAYS ); RwRenderStateSet( rwRENDERSTATEALPHATESTFUNCTION, (void*)rwALPHATESTFUNCTIONALWAYS );
orgRenderStaticShadows(); orgRenderStaticShadows();
@ -1878,7 +1878,7 @@ namespace StaticShadowAlphaFix
static void (*orgRenderStoredShadows)(); static void (*orgRenderStoredShadows)();
static void RenderStoredShadows_StateFix() static void RenderStoredShadows_StateFix()
{ {
RwScopedRenderState state(rwRENDERSTATEALPHATESTFUNCTION); RwScopedRenderState<rwRENDERSTATEALPHATESTFUNCTION> state;
RwRenderStateSet( rwRENDERSTATEALPHATESTFUNCTION, (void*)rwALPHATESTFUNCTIONALWAYS ); RwRenderStateSet( rwRENDERSTATEALPHATESTFUNCTION, (void*)rwALPHATESTFUNCTIONALWAYS );
orgRenderStoredShadows(); orgRenderStoredShadows();
@ -1935,7 +1935,7 @@ namespace MoonphasesFix
return mask; return mask;
} (); } ();
RwScopedRenderState alphaTest( rwRENDERSTATEALPHATESTFUNCTION ); RwScopedRenderState<rwRENDERSTATEALPHATESTFUNCTION> alphaTest;
if ( gpMoonMask != nullptr ) if ( gpMoonMask != nullptr )
{ {

View File

@ -247,6 +247,7 @@ copy /y "$(TargetPath)" "H:\Rockstar Games\Grand Theft Auto San Andreas\SilentPa
<ClInclude Include="..\SilentPatch\Desktop.h" /> <ClInclude Include="..\SilentPatch\Desktop.h" />
<ClInclude Include="..\SilentPatch\Maths.h" /> <ClInclude Include="..\SilentPatch\Maths.h" />
<ClInclude Include="..\SilentPatch\resource1.h" /> <ClInclude Include="..\SilentPatch\resource1.h" />
<ClInclude Include="..\SilentPatch\RWUtils.hpp" />
<ClInclude Include="..\SilentPatch\SVF.h" /> <ClInclude Include="..\SilentPatch\SVF.h" />
<ClInclude Include="..\SilentPatch\TheFLAUtils.h" /> <ClInclude Include="..\SilentPatch\TheFLAUtils.h" />
<ClInclude Include="..\SilentPatch\Utils\DelimStringReader.h" /> <ClInclude Include="..\SilentPatch\Utils\DelimStringReader.h" />
@ -264,7 +265,6 @@ copy /y "$(TargetPath)" "H:\Rockstar Games\Grand Theft Auto San Andreas\SilentPa
<ClInclude Include="PNGFile.h" /> <ClInclude Include="PNGFile.h" />
<ClInclude Include="PoolsSA.h" /> <ClInclude Include="PoolsSA.h" />
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />
<ClInclude Include="RWUtils.hpp" />
<ClInclude Include="ScriptSA.h" /> <ClInclude Include="ScriptSA.h" />
<ClInclude Include="StdAfxSA.h" /> <ClInclude Include="StdAfxSA.h" />
<ClInclude Include="TimerSA.h" /> <ClInclude Include="TimerSA.h" />

View File

@ -140,9 +140,6 @@
<ClInclude Include="FireManagerSA.h"> <ClInclude Include="FireManagerSA.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="RWUtils.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\SilentPatch\Utils\DelimStringReader.h"> <ClInclude Include="..\SilentPatch\Utils\DelimStringReader.h">
<Filter>Header Files\Utils</Filter> <Filter>Header Files\Utils</Filter>
</ClInclude> </ClInclude>
@ -164,6 +161,9 @@
<ClInclude Include="..\SilentPatch\Desktop.h"> <ClInclude Include="..\SilentPatch\Desktop.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\SilentPatch\RWUtils.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="..\SilentPatch\SilentPatch.rc"> <ResourceCompile Include="..\SilentPatch\SilentPatch.rc">

View File

@ -714,6 +714,63 @@ namespace VariableResets
} }
// ============= Disabled backface culling on detached car parts =============
namespace CarPartsBackfaceCulling
{
// Only the parts of CObject we need
enum // m_objectCreatedBy
{
GAME_OBJECT = 1,
MISSION_OBJECT = 2,
TEMP_OBJECT = 3,
};
struct Object
{
std::byte __pad[364];
uint8_t m_objectCreatedBy;
bool bObjectFlag0 : 1;
bool bObjectFlag1 : 1;
bool bObjectFlag2 : 1;
bool bObjectFlag3 : 1;
bool bObjectFlag4 : 1;
bool bObjectFlag5 : 1;
bool m_bIsExploded : 1;
bool bUseVehicleColours : 1;
std::byte __pad2[22];
FLAUtils::int16 m_wCarPartModelIndex;
};
static void* ObjectRender_Prologue_JumpBack;
__declspec(naked) static void __fastcall ObjectRender_Original(Object*)
{
_asm
{
push ebx
push esi
mov ebx, ecx
push edi
jmp [ObjectRender_Prologue_JumpBack]
}
}
// If CObject::Render is re-routed by another mod, we overwrite this later
static void (__fastcall *orgObjectRender)(Object* obj) = &ObjectRender_Original;
static void __fastcall ObjectRender_BackfaceCulling(Object* obj)
{
RwScopedRenderState<rwRENDERSTATECULLMODE> cullState;
if (obj->m_wCarPartModelIndex.Get() != -1 && obj->m_objectCreatedBy == TEMP_OBJECT && obj->bUseVehicleColours)
{
RwRenderStateSet(rwRENDERSTATECULLMODE, reinterpret_cast<void*>(rwCULLMODECULLNONE));
}
orgObjectRender(obj);
}
}
void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModulePath ) void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModulePath )
{ {
using namespace Memory; using namespace Memory;
@ -1613,6 +1670,26 @@ void Patch_VC_Common()
Nop(comment_delay_id2.get<void>(3), 4); Nop(comment_delay_id2.get<void>(3), 4);
} }
TXN_CATCH(); TXN_CATCH();
// Disabled backface culling on detached car parts
try
{
using namespace CarPartsBackfaceCulling;
auto object_render = pattern("55 83 EC 68 8A 43 54").get_one();
ObjectRender_Prologue_JumpBack = object_render.get<void>();
// Check if CObject::Render is already re-routed by something else
if (*object_render.get<uint8_t>(-5) == 0xE9)
{
ReadCall(object_render.get<void>(-5), orgObjectRender);
}
InjectHook(object_render.get<void>(-5), ObjectRender_BackfaceCulling, HookType::Jump);
}
TXN_CATCH();
} }
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)

View File

@ -170,7 +170,7 @@
<ClInclude Include="..\SilentPatch\debugmenu_public.h" /> <ClInclude Include="..\SilentPatch\debugmenu_public.h" />
<ClInclude Include="..\SilentPatch\Desktop.h" /> <ClInclude Include="..\SilentPatch\Desktop.h" />
<ClInclude Include="..\SilentPatch\Maths.h" /> <ClInclude Include="..\SilentPatch\Maths.h" />
<ClInclude Include="..\SilentPatch\RWGTA.h" /> <ClInclude Include="..\SilentPatch\RWUtils.hpp" />
<ClInclude Include="..\SilentPatch\StdAfx.h" /> <ClInclude Include="..\SilentPatch\StdAfx.h" />
<ClInclude Include="..\SilentPatch\StoredCar.h" /> <ClInclude Include="..\SilentPatch\StoredCar.h" />
<ClInclude Include="..\SilentPatch\SVF.h" /> <ClInclude Include="..\SilentPatch\SVF.h" />

View File

@ -51,9 +51,6 @@
<ClInclude Include="..\SilentPatch\debugmenu_public.h"> <ClInclude Include="..\SilentPatch\debugmenu_public.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\SilentPatch\RWGTA.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\SilentPatch\Maths.h"> <ClInclude Include="..\SilentPatch\Maths.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@ -66,6 +63,9 @@
<ClInclude Include="..\SilentPatch\TheFLAUtils.h"> <ClInclude Include="..\SilentPatch\TheFLAUtils.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\SilentPatch\RWUtils.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\SilentPatch\Timer.cpp"> <ClCompile Include="..\SilentPatch\Timer.cpp">