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/Patterns.h"
@ -17,21 +15,25 @@ void** rwengine = []() -> void** {
// Thanks Steam III...
// Locate RwRenderStateSet
auto renderStateSetPtr = hook::get_pattern( "D1 7C 24 2C", 4 );
auto renderStateSet = reinterpret_cast<uintptr_t>(Memory::ReadCallFrom( renderStateSetPtr ));
// Test III 1.0/1.1/VC
if ( *reinterpret_cast<uint8_t*>(renderStateSet) == 0xA1 )
try
{
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
renderStateSet += 3;
if ( *reinterpret_cast<uint8_t*>(renderStateSet) == 0xA1 )
{
return *reinterpret_cast<void***>(renderStateSet + 1);
// Test III 1.0/1.1/VC
if ( *reinterpret_cast<uint8_t*>(renderStateSet) == 0xA1 )
{
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!");
return nullptr;
@ -52,5 +54,15 @@ RwReal RwIm2DGetNearScreenZ()
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
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 <rpworld.h>
template<RwRenderState State>
class RwScopedRenderState
{
public:
RwScopedRenderState( RwRenderState state )
: m_state( state )
explicit RwScopedRenderState()
{
[[maybe_unused]] RwBool result = RwRenderStateGet( m_state, &m_value );
[[maybe_unused]] RwBool result = RwRenderStateGet( State, &m_value );
assert( result != FALSE );
}
~RwScopedRenderState()
{
[[maybe_unused]] RwBool result = RwRenderStateSet( m_state, m_value );
[[maybe_unused]] RwBool result = RwRenderStateSet( State, m_value );
assert( result != FALSE );
}
private:
RwScopedRenderState( const RwScopedRenderState& ) = delete;
const RwRenderState m_state;
private:
void* m_value = nullptr;
};

View file

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

View file

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

View file

@ -69,10 +69,10 @@ void CObject::Render()
std::pair<void**,void*> materialRestoreData[256];
size_t numMaterialsToRestore = 0;
RwScopedRenderState cullState(rwRENDERSTATECULLMODE);
RwScopedRenderState<rwRENDERSTATECULLMODE> cullState;
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;

View file

@ -260,7 +260,7 @@ public:
bool bObjectFlag4 : 1;
bool bObjectFlag5 : 1;
bool m_bIsExploded : 1;
bool bObjectFlag7 : 1;
bool bUseVehicleColours : 1;
bool m_bIsLampPost : 1;
bool m_bIsTargetable : 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 )
{
RwScopedRenderState zWrite(rwRENDERSTATEZWRITEENABLE);
RwScopedRenderState<rwRENDERSTATEZWRITEENABLE> zWrite;
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE);
SetGunFlashAlpha(bRightGun);

View file

@ -375,7 +375,7 @@ static RpAtomic* RenderAtomic(RpAtomic* pAtomic, float fComp)
static RpAtomic* StaticPropellerRender(RpAtomic* pAtomic)
{
RwScopedRenderState alphaRef(rwRENDERSTATEALPHATESTFUNCTIONREF);
RwScopedRenderState<rwRENDERSTATEALPHATESTFUNCTIONREF> alphaRef;
RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, 0);
pAtomic = AtomicDefaultRenderCallBack(pAtomic);
@ -385,8 +385,8 @@ static RpAtomic* StaticPropellerRender(RpAtomic* pAtomic)
static RpAtomic* MovingPropellerRender(RpAtomic* pAtomic)
{
RwScopedRenderState alphaRef(rwRENDERSTATEALPHATESTFUNCTIONREF);
RwScopedRenderState vertexAlpha(rwRENDERSTATEVERTEXALPHAENABLE);
RwScopedRenderState<rwRENDERSTATEALPHATESTFUNCTIONREF> alphaRef;
RwScopedRenderState<rwRENDERSTATEVERTEXALPHAENABLE> vertexAlpha;
RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, 0);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast<void*>(TRUE));
@ -430,9 +430,9 @@ void RenderWeapon(CPed* pPed)
void RenderWeaponPedsForPC()
{
RwScopedRenderState vertexAlpha(rwRENDERSTATEVERTEXALPHAENABLE);
RwScopedRenderState zWrite(rwRENDERSTATEZWRITEENABLE);
RwScopedRenderState fogEnable(rwRENDERSTATEFOGENABLE);
RwScopedRenderState<rwRENDERSTATEVERTEXALPHAENABLE> vertexAlpha;
RwScopedRenderState<rwRENDERSTATEZWRITEENABLE> zWrite;
RwScopedRenderState<rwRENDERSTATEFOGENABLE> fogEnable;
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast<void*>(TRUE));
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, reinterpret_cast<void*>(TRUE));
@ -1869,7 +1869,7 @@ namespace StaticShadowAlphaFix
static void (*orgRenderStaticShadows)();
static void RenderStaticShadows_StateFix()
{
RwScopedRenderState state(rwRENDERSTATEALPHATESTFUNCTION);
RwScopedRenderState<rwRENDERSTATEALPHATESTFUNCTION> state;
RwRenderStateSet( rwRENDERSTATEALPHATESTFUNCTION, (void*)rwALPHATESTFUNCTIONALWAYS );
orgRenderStaticShadows();
@ -1878,7 +1878,7 @@ namespace StaticShadowAlphaFix
static void (*orgRenderStoredShadows)();
static void RenderStoredShadows_StateFix()
{
RwScopedRenderState state(rwRENDERSTATEALPHATESTFUNCTION);
RwScopedRenderState<rwRENDERSTATEALPHATESTFUNCTION> state;
RwRenderStateSet( rwRENDERSTATEALPHATESTFUNCTION, (void*)rwALPHATESTFUNCTIONALWAYS );
orgRenderStoredShadows();
@ -1935,7 +1935,7 @@ namespace MoonphasesFix
return mask;
} ();
RwScopedRenderState alphaTest( rwRENDERSTATEALPHATESTFUNCTION );
RwScopedRenderState<rwRENDERSTATEALPHATESTFUNCTION> alphaTest;
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\Maths.h" />
<ClInclude Include="..\SilentPatch\resource1.h" />
<ClInclude Include="..\SilentPatch\RWUtils.hpp" />
<ClInclude Include="..\SilentPatch\SVF.h" />
<ClInclude Include="..\SilentPatch\TheFLAUtils.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="PoolsSA.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="RWUtils.hpp" />
<ClInclude Include="ScriptSA.h" />
<ClInclude Include="StdAfxSA.h" />
<ClInclude Include="TimerSA.h" />

View file

@ -140,9 +140,6 @@
<ClInclude Include="FireManagerSA.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RWUtils.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\SilentPatch\Utils\DelimStringReader.h">
<Filter>Header Files\Utils</Filter>
</ClInclude>
@ -164,6 +161,9 @@
<ClInclude Include="..\SilentPatch\Desktop.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\SilentPatch\RWUtils.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<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 )
{
using namespace Memory;
@ -1613,6 +1670,26 @@ void Patch_VC_Common()
Nop(comment_delay_id2.get<void>(3), 4);
}
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)

View file

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

View file

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