commit 62052759e13f233e3af36e05ca0917692541f09f Author: Silent Date: Fri May 30 20:14:47 2014 +0200 Initial committ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..27d76c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,190 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Nn]ormal/ +[Nn]ightly/ +output/ +symbols/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +*.cso +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/* +## TODO: If the tool you use requires repositories.config, also uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) +!packages/build/ + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ diff --git a/IIIFix/IIIFix.vcxproj b/IIIFix/IIIFix.vcxproj new file mode 100644 index 0000000..20e4516 --- /dev/null +++ b/IIIFix/IIIFix.vcxproj @@ -0,0 +1,114 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + + + + + + {652975D8-60B0-48E4-A973-4F10BA54FFCB} + IIIFix + + + + DynamicLibrary + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + + .asi + + + .asi + + + + Level4 + Disabled + MultiThreadedDebug + false + SILENTPATCH_III_VER;%(PreprocessorDefinitions) + D:\RWSDK\Graphics\rwsdk\include\d3d9 + + + true + false + Windows + 5.0 + + + Winmm.lib + + + copy /y "$(TargetPath)" "D:\gry\Steam\steamapps\common\Grand Theft Auto 3\SilentPatchIII.asi" + + + + + Level4 + MaxSpeed + true + true + MultiThreaded + true + false + false + AnySuitable + Speed + true + SILENTPATCH_III_VER;%(PreprocessorDefinitions) + D:\RWSDK\Graphics\rwsdk\include\d3d9 + + + false + true + true + false + Windows + 5.0 + + + Winmm.lib + + + copy /y "$(TargetPath)" "D:\gry\Steam\steamapps\common\Grand Theft Auto 3\SilentPatchIII.asi" + + + + + + + \ No newline at end of file diff --git a/IIIFix/IIIFix.vcxproj.filters b/IIIFix/IIIFix.vcxproj.filters new file mode 100644 index 0000000..0f5957c --- /dev/null +++ b/IIIFix/IIIFix.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/SAFix/SAFix.vcxproj b/SAFix/SAFix.vcxproj new file mode 100644 index 0000000..e96da57 --- /dev/null +++ b/SAFix/SAFix.vcxproj @@ -0,0 +1,118 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {D3E18BC0-A120-451D-A16A-F77072625D66} + SAFix + + + + DynamicLibrary + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + .dll + + + .dll + + + + Level4 + Disabled + MultiThreadedDebug + SILENTPATCH_SA_VER;%(PreprocessorDefinitions) + D:\RWSDK\Graphics\rwsdk\include\d3d9 + Use + + + true + Windows + 5.0 + winmm.lib;%(AdditionalDependencies) + + + copy /y "$(TargetPath)" "D:\gry\GTA San Andreas clean\SilentPatchSA.asi" + + + + + Level4 + MaxSpeed + true + true + AnySuitable + Speed + true + SILENTPATCH_SA_VER;%(PreprocessorDefinitions) + true + MultiThreaded + D:\RWSDK\Graphics\rwsdk\include\d3d9 + Use + + + true + true + true + Windows + 5.0 + winmm.lib;%(AdditionalDependencies) + + + copy /y "$(TargetPath)" "D:\gry\GTA San Andreas clean\SilentPatchSA.asi" + + + + + + + + Create + Create + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SAFix/SAFix.vcxproj.filters b/SAFix/SAFix.vcxproj.filters new file mode 100644 index 0000000..f76985f --- /dev/null +++ b/SAFix/SAFix.vcxproj.filters @@ -0,0 +1,68 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/SilentPatch.sln b/SilentPatch.sln new file mode 100644 index 0000000..8036ff4 --- /dev/null +++ b/SilentPatch.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IIIFix", "IIIFix\IIIFix.vcxproj", "{652975D8-60B0-48E4-A973-4F10BA54FFCB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VCFix", "VCFix\VCFix.vcxproj", "{374D4CB4-548A-4DA0-AB68-8EA356424626}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SAFix", "SAFix\SAFix.vcxproj", "{D3E18BC0-A120-451D-A16A-F77072625D66}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {652975D8-60B0-48E4-A973-4F10BA54FFCB}.Debug|Win32.ActiveCfg = Debug|Win32 + {652975D8-60B0-48E4-A973-4F10BA54FFCB}.Debug|Win32.Build.0 = Debug|Win32 + {652975D8-60B0-48E4-A973-4F10BA54FFCB}.Release|Win32.ActiveCfg = Release|Win32 + {652975D8-60B0-48E4-A973-4F10BA54FFCB}.Release|Win32.Build.0 = Release|Win32 + {374D4CB4-548A-4DA0-AB68-8EA356424626}.Debug|Win32.ActiveCfg = Debug|Win32 + {374D4CB4-548A-4DA0-AB68-8EA356424626}.Debug|Win32.Build.0 = Debug|Win32 + {374D4CB4-548A-4DA0-AB68-8EA356424626}.Release|Win32.ActiveCfg = Release|Win32 + {374D4CB4-548A-4DA0-AB68-8EA356424626}.Release|Win32.Build.0 = Release|Win32 + {D3E18BC0-A120-451D-A16A-F77072625D66}.Debug|Win32.ActiveCfg = Debug|Win32 + {D3E18BC0-A120-451D-A16A-F77072625D66}.Debug|Win32.Build.0 = Debug|Win32 + {D3E18BC0-A120-451D-A16A-F77072625D66}.Release|Win32.ActiveCfg = Release|Win32 + {D3E18BC0-A120-451D-A16A-F77072625D66}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/SilentPatch/General.cpp b/SilentPatch/General.cpp new file mode 100644 index 0000000..081ab27 --- /dev/null +++ b/SilentPatch/General.cpp @@ -0,0 +1,12 @@ +#include "StdAfx.h" + +#include "General.h" + +// Wrappers +WRAPPER bool CalcScreenCoors(const CVector& vecIn, CVector* vecOut) { WRAPARG(vecIn); WRAPARG(vecOut); EAXJMP(0x71DAB0); } +WRAPPER void LoadingScreenLoadingFile(const char* pText) { WRAPARG(pText); EAXJMP(0x5B3680); } + +WRAPPER void CEntity::UpdateRW() { EAXJMP(0x446F90); } +WRAPPER void CEntity::RegisterReference(CEntity** pAddress) { WRAPARG(pAddress); EAXJMP(0x571B70); } +WRAPPER void CEntity::CleanUpOldReference(CEntity** pAddress) { WRAPARG(pAddress); EAXJMP(0x571A00); } +WRAPPER void CEntity::Render() { EAXJMP(0x534310); } diff --git a/SilentPatch/General.h b/SilentPatch/General.h new file mode 100644 index 0000000..47e462e --- /dev/null +++ b/SilentPatch/General.h @@ -0,0 +1,283 @@ +#ifndef __GENERAL +#define __GENERAL + +class CSimpleTransform +{ +public: + CVector m_translate; + float m_heading; +}; + +class CRGBA +{ +public: + BYTE r, g, b, a; + + inline CRGBA() {} + + inline CRGBA(const CRGBA& in) + : r(in.r), g(in.g), b(in.b), a(in.a) + {} + + inline CRGBA(const CRGBA& in, BYTE alpha) + : r(in.r), g(in.g), b(in.b), a(alpha) + {} + + + inline CRGBA(BYTE red, BYTE green, BYTE blue, BYTE alpha = 255) + : r(red), g(green), b(blue), a(alpha) + {} + + template + friend CRGBA Blend(const CRGBA& One, T OneStrength, const CRGBA& Two, T TwoStrength) + { T TotalStrength = OneStrength + TwoStrength; + return CRGBA( ((One.r * OneStrength) + (Two.r * TwoStrength))/TotalStrength, + ((One.g * OneStrength) + (Two.g * TwoStrength))/TotalStrength, + ((One.b * OneStrength) + (Two.b * TwoStrength))/TotalStrength, + ((One.a * OneStrength) + (Two.a * TwoStrength))/TotalStrength); } + + template + friend CRGBA Blend(const CRGBA& One, T OneStrength, const CRGBA& Two, T TwoStrength, const CRGBA& Three, T ThreeStrength) + { T TotalStrength = OneStrength + TwoStrength + ThreeStrength; + return CRGBA( ((One.r * OneStrength) + (Two.r * TwoStrength) + (Three.r * ThreeStrength))/TotalStrength, + ((One.g * OneStrength) + (Two.g * TwoStrength) + (Three.g * ThreeStrength))/TotalStrength, + ((One.b * OneStrength) + (Two.b * TwoStrength) + (Three.b * ThreeStrength))/TotalStrength, + ((One.a * OneStrength) + (Two.a * TwoStrength) + (Three.a * ThreeStrength))/TotalStrength); } + + void BaseColors__Constructor(); +}; + +class CRect +{ +public: + float x1, y1; + float x2, y2; + + inline CRect() {} + inline CRect(float a, float b, float c, float d) + : x1(a), y1(b), x2(c), y2(d) + {} +}; + + +class CPlaceable +{ +private: + CSimpleTransform m_transform; + CMatrix* m_pCoords; + +public: + // Line up the VMTs + virtual ~CPlaceable() {} + + inline CPlaceable() {} + + explicit inline CPlaceable(int dummy) + { + // Dummy ctor + UNREFERENCED_PARAMETER(dummy); + } + + inline CVector* GetCoords() + { return m_pCoords ? reinterpret_cast(&m_pCoords->matrix.pos) : &m_transform.m_translate; } + inline CMatrix* GetMatrix() + { return m_pCoords; } + inline CSimpleTransform& GetTransform() + { return m_transform; } + inline float GetHeading() + { return m_pCoords ? atan2(-m_pCoords->GetUp()->x, m_pCoords->GetUp()->y) : m_transform.m_heading; } + + inline void SetCoords(const CVector& pos) + { if ( m_pCoords ) { m_pCoords->matrix.pos.x = pos.x; m_pCoords->matrix.pos.y = pos.y; m_pCoords->matrix.pos.z = pos.z; } + else m_transform.m_translate = pos; } + inline void SetHeading(float fHeading) + { if ( m_pCoords ) m_pCoords->SetRotateZOnly(fHeading); else m_transform.m_heading = fHeading; } +}; + +// TODO: May not be the best place to put it? +class NOVMT CEntity : public CPlaceable +{ +public: + virtual void Add_CRect(); + virtual void Add(); + virtual void Remove(); + virtual void SetIsStatic(bool); + virtual void SetModelIndex(int nModelIndex); + virtual void SetModelIndexNoCreate(int nModelIndex); + virtual void CreateRwObject(); + virtual void DeleteRwObject(); + virtual CRect GetBoundRect(); + virtual void ProcessControl(); + virtual void ProcessCollision(); + virtual void ProcessShift(); + virtual void TestCollision(); + virtual void Teleport(); + virtual void SpecialEntityPreCollisionStuff(); + virtual void SpecialEntityCalcCollisionSteps(); + virtual void PreRender(); + virtual void Render(); + virtual void SetupLighting(); + virtual void RemoveLighting(bool bRemove=true); + virtual void FlagToDestroyWhenNextProcessed(); + +//private: + RpClump* m_pRwObject; // 0x18 + + /********** BEGIN CFLAGS (0x1C) **************/ + unsigned long bUsesCollision : 1; // does entity use collision + unsigned long bCollisionProcessed : 1; // has object been processed by a ProcessEntityCollision function + unsigned long bIsStatic : 1; // is entity static + unsigned long bHasContacted : 1; // has entity processed some contact forces + unsigned long bIsStuck : 1; // is entity stuck + unsigned long bIsInSafePosition : 1; // is entity in a collision free safe position + unsigned long bWasPostponed : 1; // was entity control processing postponed + unsigned long bIsVisible : 1; //is the entity visible + + unsigned long bIsBIGBuilding : 1; // Set if this entity is a big building + unsigned long bRenderDamaged : 1; // use damaged LOD models for objects with applicable damage + unsigned long bStreamingDontDelete : 1; // Dont let the streaming remove this + unsigned long bRemoveFromWorld : 1; // remove this entity next time it should be processed + unsigned long bHasHitWall : 1; // has collided with a building (changes subsequent collisions) + unsigned long bImBeingRendered : 1; // don't delete me because I'm being rendered + unsigned long bDrawLast :1; // draw object last + unsigned long bDistanceFade :1; // Fade entity because it is far away + + unsigned long bDontCastShadowsOn : 1; // Dont cast shadows on this object + unsigned long bOffscreen : 1; // offscreen flag. This can only be trusted when it is set to true + unsigned long bIsStaticWaitingForCollision : 1; // this is used by script created entities - they are static until the collision is loaded below them + unsigned long bDontStream : 1; // tell the streaming not to stream me + unsigned long bUnderwater : 1; // this object is underwater change drawing order + unsigned long bHasPreRenderEffects : 1; // Object has a prerender effects attached to it + unsigned long bIsTempBuilding : 1; // whether or not the building is temporary (i.e. can be created and deleted more than once) + unsigned long bDontUpdateHierarchy : 1; // Don't update the aniamtion hierarchy this frame + + unsigned long bHasRoadsignText : 1; // entity is roadsign and has some 2deffect text stuff to be rendered + unsigned long bDisplayedSuperLowLOD : 1; + unsigned long bIsProcObject : 1; // set object has been generate by procedural object generator + unsigned long bBackfaceCulled : 1; // has backface culling on + unsigned long bLightObject : 1; // light object with directional lights + unsigned long bUnimportantStream : 1; // set that this object is unimportant, if streaming is having problems + unsigned long bTunnel : 1; // Is this model part of a tunnel + unsigned long bTunnelTransition : 1; // This model should be rendered from within and outside of the tunnel + /********** END CFLAGS **************/ + + WORD RandomSeed; // 0x20 + short m_nModelIndex; // 0x22 + void* pReferences; // 0x24 + void* m_pLastRenderedLink; // 0x28 + WORD m_nScanCode; // 0x2C + BYTE m_iplIndex; // 0x2E + BYTE m_areaCode; // 0x2F + CEntity* m_pLod; // 0x30 + BYTE numLodChildren; // 0x34 + char numLodChildrenRendered; // 0x35 + + //********* BEGIN CEntityInfo **********// + BYTE nType : 3; // what type is the entity // 0x36 (2 == Vehicle) + BYTE nStatus : 5; // control status // 0x36 + //********* END CEntityInfo ************// + +public: + explicit inline CEntity(int dummy) + : CPlaceable(dummy) + { + // Dummy ctor + } + + inline short& ModelIndex() + { return m_nModelIndex; }; + inline short GetModelIndex() + { return m_nModelIndex; } + + void UpdateRW(); + void RegisterReference(CEntity** pAddress); + void CleanUpOldReference(CEntity** pAddress); +}; + +class NOVMT CPhysical : public CEntity +{ +private: + float pad1; // 56 + int __pad2; // 60 + + unsigned int b0x01 : 1; // 64 + unsigned int bApplyGravity : 1; + unsigned int bDisableFriction : 1; + unsigned int bCollidable : 1; + unsigned int b0x10 : 1; + unsigned int bDisableMovement : 1; + unsigned int b0x40 : 1; + unsigned int b0x80 : 1; + + unsigned int bSubmergedInWater : 1; // 65 + unsigned int bOnSolidSurface : 1; + unsigned int bBroken : 1; + unsigned int b0x800 : 1; // ref @ 0x6F5CF0 + unsigned int b0x1000 : 1;// + unsigned int b0x2000 : 1;// + unsigned int b0x4000 : 1;// + unsigned int b0x8000 : 1;// + + unsigned int b0x10000 : 1; // 66 + unsigned int b0x20000 : 1; // ref @ CPhysical__processCollision + unsigned int bBulletProof : 1; + unsigned int bFireProof : 1; + unsigned int bCollisionProof : 1; + unsigned int bMeeleProof : 1; + unsigned int bInvulnerable : 1; + unsigned int bExplosionProof : 1; + + unsigned int b0x1000000 : 1; // 67 + unsigned int bAttachedToEntity : 1; + unsigned int b0x4000000 : 1; + unsigned int bTouchingWater : 1; + unsigned int bEnableCollision : 1; + unsigned int bDestroyed : 1; + unsigned int b0x40000000 : 1; + unsigned int b0x80000000 : 1; + + CVector m_vecLinearVelocity; // 68 + CVector m_vecAngularVelocity; // 80 + CVector m_vecCollisionLinearVelocity; // 92 + CVector m_vecCollisionAngularVelocity; // 104 + CVector m_vForce; // 0x74 + CVector m_vTorque; // 0x80 + float fMass; // 0x8C + float fTurnMass; // 0x90 + float m_fVelocityFrequency; // 0x94 + float m_fAirResistance; // 0x98 + float m_fElasticity; // 0x9C + float m_fBuoyancyConstant; // 0xA0 + + CVector vecCenterOfMass; // 0xA4 + DWORD dwUnk1; // 0xB0 + void* unkCPtrNodeDoubleLink; // 0xB4 + BYTE byUnk: 8; // 0xB8 + BYTE byCollisionRecords: 8; // 0xB9 + BYTE byUnk2: 8; // 0xBA (Baracus) + BYTE byUnk3: 8; // 0xBB + + float pad4[6]; // 0xBC + + float fDistanceTravelled; // 0xD4 + float fDamageImpulseMagnitude; // 0xD8 + CEntity* damageEntity; // 0xDC + BYTE pad2[28]; // 0xE0 + CEntity* pAttachedEntity; // 0xFC + CVector m_vAttachedPosition; // 0x100 + CVector m_vAttachedRotation; // 0x10C + BYTE pad3[20]; // 0x118 + float fLighting; // 0x12C col lighting? CPhysical::GetLightingFromCol + float fLighting_2; // 0x130 added to col lighting in CPhysical::GetTotalLighting + BYTE pad3a[4]; // 0x134 + +public: + // Temp + CPhysical() + : CEntity(0) {} +}; + +static_assert(sizeof(CEntity) == 0x38, "Wrong size: CEntity"); +static_assert(sizeof(CPhysical) == 0x138, "Wrong size: CPhysical"); + +#endif \ No newline at end of file diff --git a/SilentPatch/LinkList.h b/SilentPatch/LinkList.h new file mode 100644 index 0000000..7e25586 --- /dev/null +++ b/SilentPatch/LinkList.h @@ -0,0 +1,134 @@ +#ifndef __LINKLIST__ +#define __LINKLIST__ + +template +class CLink +{ +public: + inline void Insert(CLink* pAttach) { + pAttach->m_pNext = m_pNext; + m_pNext->m_pPrev = pAttach; + + pAttach->m_pPrev = this; + m_pNext = pAttach; + } + + inline void Remove(void) { + m_pNext->m_pPrev = m_pPrev; + m_pPrev->m_pNext = m_pNext; + } + + inline T& V(void) { + return m_pItem; + } + + T m_pItem; // 0-4 + // an item + CLink* m_pPrev; // 4-8 + //next link in the list + CLink* m_pNext; // 8-12 + //prev link in the list +}; + +template +class CLinkList { +public: + CLinkList(void) + : m_plnLinks(nullptr) + { + } + + void Init(int nNumLinks) { + m_plnLinks = new CLink[nNumLinks]; + + m_lnListHead.m_pNext = &m_lnListTail; + m_lnListTail.m_pPrev = &m_lnListHead; + + m_lnFreeListHead.m_pNext = &m_lnFreeListTail; + m_lnFreeListTail.m_pPrev = &m_lnFreeListHead; + + for(int i = nNumLinks - 1; i >= 0; i--) { + m_lnFreeListHead.Insert(&m_plnLinks[i]); + } + } + + void Shutdown(void) { + delete[] m_plnLinks; + + m_plnLinks = nullptr; + } + + CLink* InsertSorted(const T& pItem) { + CLink* pLink = m_lnFreeListHead.m_pNext; + + if(pLink == &m_lnFreeListTail) { + return nullptr; + } + + pLink->m_pItem = pItem; + + pLink->Remove(); + + CLink* pInsertAfter = &m_lnListHead; + + while(pInsertAfter->m_pNext != &m_lnListTail && pInsertAfter->m_pNext->m_pItem < pItem) { + pInsertAfter = pInsertAfter->m_pNext; + } + + pInsertAfter->Insert(pLink); + + return pLink; + } + + CLink* Insert(const T& pItem) { + CLink* pLink = m_lnFreeListHead.m_pNext; + + if(pLink == &m_lnFreeListTail) { + return nullptr; + } + + pLink->m_pItem = pItem; + + pLink->Remove(); + m_lnListHead.Insert(pLink); + + return pLink; + } + + void Clear(void) { + while(m_lnListHead.m_pNext != &m_lnListTail) { + m_lnListHead.m_pNext->Remove(); + } + } + + void Remove(CLink* pLink) { + pLink->Remove(); + m_lnFreeListHead.Insert(pLink); + } + + CLink* Next(CLink* pCurrent) { + if(pCurrent == 0) { + pCurrent = &m_lnListHead; + } + + if(pCurrent->m_pNext == &m_lnListTail) { + return 0; + } + else { + return pCurrent->m_pNext; + } + } + + CLink m_lnListHead; // 0-12 + //head of the list of active links + CLink m_lnListTail; // 12-24 + //tail of the list of active links + CLink m_lnFreeListHead; // 24-36 + //head of the list of free links + CLink m_lnFreeListTail; // 36-48 + //tail of the list of free links + CLink* m_plnLinks; // 48-52 + //pointer to actual array of links +}; + +#endif \ No newline at end of file diff --git a/SilentPatch/Maths.h b/SilentPatch/Maths.h new file mode 100644 index 0000000..3a65800 --- /dev/null +++ b/SilentPatch/Maths.h @@ -0,0 +1,370 @@ +#ifndef __MATHS__H +#define __MATHS__H + +#define RAD_TO_DEG (180.0/M_PI) +#define DEG_TO_RAD (M_PI/180.0) + +class CVector +{ +public: + float x, y, z; + + CVector() + {} + + CVector(float fX, float fY, float fZ=0.0f) + : x(fX), y(fY), z(fZ) + {} + + CVector(const RwV3d& rwVec) + : x(rwVec.x), y(rwVec.y), z(rwVec.z) + {} + + CVector& operator+=(const CVector& vec) + { x += vec.x; y += vec.y; z += vec.z; + return *this; } + CVector& operator+=(const RwV3d& vec) + { x += vec.x; y += vec.y; z += vec.z; + return *this; } + CVector& operator-=(const CVector& vec) + { x -= vec.x; y -= vec.y; z -= vec.z; + return *this; } + CVector& operator-=(const RwV3d& vec) + { x -= vec.x; y -= vec.y; z -= vec.z; + return *this; } + + inline float Magnitude() + { return sqrt(x * x + y * y + z * z); } + inline float MagnitudeSqr() + { return x * x + y * y + z * z; } + inline CVector& Normalize() + { float fInvLen = 1.0f / Magnitude(); x *= fInvLen; y *= fInvLen; z *= fInvLen; return *this; } + + friend inline float DotProduct(const CVector& vec1, const CVector& vec2) + { return vec1.x * vec2.x + vec1.x * vec2.y + vec1.z * vec2.z; } + friend inline CVector CrossProduct(const CVector& vec1, const CVector& vec2) + { return CVector( vec1.y * vec2.z - vec1.z * vec2.y, + vec1.z * vec2.x - vec1.x * vec2.z, + vec1.x * vec2.y - vec1.y * vec2.x); } + + friend inline CVector operator*(const CVector& in, float fMul) + { return CVector(in.x * fMul, in.y * fMul, in.z * fMul); } + friend inline CVector operator+(const CVector& vec1, const CVector& vec2) + { return CVector(vec1.x + vec2.x, vec1.y + vec2.y, vec1.z + vec2.z); } + friend inline CVector operator+(const CVector& vec1, const RwV3d& vec2) + { return CVector(vec1.x + vec2.x, vec1.y + vec2.y, vec1.z + vec2.z); } + friend inline CVector operator-(const CVector& vec1, const CVector& vec2) + { return CVector(vec1.x - vec2.x, vec1.y - vec2.y, vec1.z - vec2.z); } + friend inline CVector operator-(const CVector& vec1, const RwV3d& vec2) + { return CVector(vec1.x - vec2.x, vec1.y - vec2.y, vec1.z - vec2.z); } + friend inline CVector operator-(const CVector& vec) + { return CVector(-vec.x, -vec.y, -vec.z); } +}; + +class CVector2D +{ +public: + float x, y; + + CVector2D() + {} + + CVector2D(float fX, float fY) + : x(fX), y(fY) + {} + + CVector2D& operator+=(const CVector2D& vec) + { x += vec.x; y += vec.y; + return *this; } + CVector2D& operator-=(const CVector2D& vec) + { x -= vec.x; y -= vec.y; + return *this; } + + inline float Magnitude() + { return sqrt(x * x + y * y); } + inline float MagnitudeSqr() + { return x * x + y * y; } + inline CVector2D& Normalize() + { float fInvLen = 1.0f / Magnitude(); x *= fInvLen; y *= fInvLen; return *this; } + + friend inline float DotProduct(const CVector2D& vec1, const CVector2D& vec2) + { return vec1.x * vec2.x + vec1.x * vec2.y; } + + friend inline CVector2D operator*(const CVector2D& in, float fMul) + { return CVector2D(in.x * fMul, in.y * fMul); } + friend inline CVector2D operator+(const CVector2D& vec1, const CVector2D& vec2) + { return CVector2D(vec1.x + vec2.x, vec1.y + vec2.y); } + friend inline CVector2D operator-(const CVector2D& vec1, const CVector2D& vec2) + { return CVector2D(vec1.x - vec2.x, vec1.y - vec2.y); } + friend inline CVector2D operator-(const CVector2D& vec) + { return CVector2D(-vec.x, -vec.y); } +}; + +class CMatrix +{ +public: + RwMatrix matrix; + RwMatrix* pMatrix; + BOOL haveRwMatrix; + +public: + inline CMatrix() + : pMatrix(nullptr), haveRwMatrix(FALSE) + {} + + inline CMatrix(RwMatrix* pMatrix, bool bHasMatrix=false) + : pMatrix(nullptr) + { Attach(pMatrix, bHasMatrix); } + + inline CMatrix(const CMatrix& theMatrix) + : pMatrix(nullptr), haveRwMatrix(FALSE), matrix(theMatrix.matrix) + {} + + inline CMatrix(const CVector& vecRight, const CVector& vecUp, const CVector& vecAt, const CVector& vecPos) + { + matrix.right.x = vecRight.x; + matrix.right.y = vecRight.y; + matrix.right.z = vecRight.z; + + matrix.up.x = vecUp.x; + matrix.up.y = vecUp.y; + matrix.up.z = vecUp.z; + + matrix.at.x = vecAt.x; + matrix.at.y = vecAt.y; + matrix.at.z = vecAt.z; + + matrix.pos.x = vecPos.x; + matrix.pos.y = vecPos.y; + matrix.pos.z = vecPos.z; + } + + inline ~CMatrix() + { if ( haveRwMatrix && pMatrix ) + RwMatrixDestroy(pMatrix); } + + friend inline CMatrix operator*(const CMatrix& Rot1, const CMatrix& Rot2) + { return CMatrix( CVector(Rot1.matrix.right.x * Rot2.matrix.right.x + Rot1.matrix.right.y * Rot2.matrix.up.x + Rot1.matrix.right.z * Rot2.matrix.at.x + Rot2.matrix.pos.x, + Rot1.matrix.right.x * Rot2.matrix.right.y + Rot1.matrix.right.y * Rot2.matrix.up.y + Rot1.matrix.right.z * Rot2.matrix.at.y + Rot2.matrix.pos.y, + Rot1.matrix.right.x * Rot2.matrix.right.z + Rot1.matrix.right.y * Rot2.matrix.up.z + Rot1.matrix.right.z * Rot2.matrix.at.z + Rot2.matrix.pos.z), + CVector(Rot1.matrix.up.x * Rot2.matrix.right.x + Rot1.matrix.up.y * Rot2.matrix.up.x + Rot1.matrix.up.z * Rot2.matrix.at.x + Rot2.matrix.pos.x, + Rot1.matrix.up.x * Rot2.matrix.right.y + Rot1.matrix.up.y * Rot2.matrix.up.y + Rot1.matrix.up.z * Rot2.matrix.at.y + Rot2.matrix.pos.y, + Rot1.matrix.up.x * Rot2.matrix.right.z + Rot1.matrix.up.y * Rot2.matrix.up.z + Rot1.matrix.up.z * Rot2.matrix.at.z + Rot2.matrix.pos.z), + CVector(Rot1.matrix.at.x * Rot2.matrix.right.x + Rot1.matrix.at.y * Rot2.matrix.up.x + Rot1.matrix.at.z * Rot2.matrix.at.x + Rot2.matrix.pos.x, + Rot1.matrix.at.x * Rot2.matrix.right.y + Rot1.matrix.at.y * Rot2.matrix.up.y + Rot1.matrix.at.z * Rot2.matrix.at.y + Rot2.matrix.pos.y, + Rot1.matrix.at.x * Rot2.matrix.right.z + Rot1.matrix.at.y * Rot2.matrix.up.z + Rot1.matrix.at.z * Rot2.matrix.at.z + Rot2.matrix.pos.z), + CVector(Rot1.matrix.pos.x * Rot2.matrix.right.x + Rot1.matrix.pos.y * Rot2.matrix.up.x + Rot1.matrix.pos.z * Rot2.matrix.at.x + Rot2.matrix.pos.x, + Rot1.matrix.pos.x * Rot2.matrix.right.y + Rot1.matrix.pos.y * Rot2.matrix.up.y + Rot1.matrix.pos.z * Rot2.matrix.at.y + Rot2.matrix.pos.y, + Rot1.matrix.pos.x * Rot2.matrix.right.z + Rot1.matrix.pos.y * Rot2.matrix.up.z + Rot1.matrix.pos.z * Rot2.matrix.at.z + Rot2.matrix.pos.z)); }; + + friend inline CVector operator*(const CMatrix& matrix, const CVector& vec) + { return CVector(matrix.matrix.up.x * vec.y + matrix.matrix.right.x * vec.x + matrix.matrix.at.x * vec.z + matrix.matrix.pos.x, + matrix.matrix.up.y * vec.y + matrix.matrix.right.y * vec.x + matrix.matrix.at.y * vec.z + matrix.matrix.pos.y, + matrix.matrix.up.z * vec.y + matrix.matrix.right.z * vec.x + matrix.matrix.at.z * vec.z + matrix.matrix.pos.z); }; + + inline CVector* GetRight() + { return reinterpret_cast(&matrix.right); } + inline CVector* GetUp() + { return reinterpret_cast(&matrix.up); } + inline CVector* GetAt() + { return reinterpret_cast(&matrix.at); } + inline CVector* GetPos() + { return reinterpret_cast(&matrix.pos); } + + inline void SetTranslateOnly(float fX, float fY, float fZ) + { matrix.pos.x = fX; matrix.pos.y = fY; matrix.pos.z = fZ; } + + inline void SetRotateX(float fAngle) + { SetRotateXOnly(fAngle); matrix.pos.x = 0.0f; matrix.pos.y = 0.0f; matrix.pos.z = 0.0f; } + inline void SetRotateY(float fAngle) + { SetRotateYOnly(fAngle); matrix.pos.x = 0.0f; matrix.pos.y = 0.0f; matrix.pos.z = 0.0f; } + inline void SetRotateZ(float fAngle) + { SetRotateZOnly(fAngle); matrix.pos.x = 0.0f; matrix.pos.y = 0.0f; matrix.pos.z = 0.0f; } + inline void SetRotate(float fAngleX, float fAngleY, float fAngleZ) + { SetRotateOnly(fAngleX, fAngleY, fAngleZ); matrix.pos.x = 0.0f; matrix.pos.y = 0.0f; matrix.pos.z = 0.0f; } + inline void SetTranslate(float fX, float fY, float fZ) + { matrix.right.x = 1.0f; matrix.right.y = 0.0f; matrix.right.z = 0.0f; + matrix.up.x = 0.0f; matrix.up.y = 1.0f; matrix.up.z = 0.0f; + matrix.at.x = 0.0f; matrix.at.y = 0.0f; matrix.at.z = 1.0f; + SetTranslateOnly(fX, fY, fZ); } + + inline void SetUnity() + { + matrix.right.x = 1.0f; matrix.right.y = 0.0f; matrix.right.z = 0.0f; + matrix.up.x = 0.0f; matrix.up.y = 1.0f; matrix.up.z = 0.0f; + matrix.at.x = 0.0f; matrix.at.y = 0.0f; matrix.at.z = 1.0f; + matrix.pos.x = 0.0f; matrix.pos.y = 0.0f; matrix.pos.z = 0.0f; + } + + inline void SetScale(float fScale) + { + matrix.right.x = fScale; matrix.right.y = 0.0f; matrix.right.z = 0.0f; + matrix.up.x = 0.0f; matrix.up.y = fScale; matrix.up.z = 0.0f; + matrix.at.x = 0.0f; matrix.at.y = 0.0f; matrix.at.z = fScale; + matrix.pos.x = 0.0f; matrix.pos.y = 0.0f; matrix.pos.z = 0.0f; + } + + inline void RotateX(float fAngle) + { + CMatrix RotationMatrix; + RotationMatrix.SetRotateX(fAngle); + *this = *this * RotationMatrix; + } + + inline void RotateY(float fAngle) + { + CMatrix RotationMatrix; + RotationMatrix.SetRotateY(fAngle); + *this = *this * RotationMatrix; + } + + inline void RotateZ(float fAngle) + { + CMatrix RotationMatrix; + RotationMatrix.SetRotateZ(fAngle); + *this = *this * RotationMatrix; + } + + inline void Rotate(float fAngleX, float fAngleY, float fAngleZ) + { + CMatrix RotationMatrix; + RotationMatrix.SetRotate(fAngleX, fAngleY, fAngleZ); + *this = *this * RotationMatrix; + } + + inline void SetRotateXOnly(float fAngle) + { + matrix.right.x = 1.0f; + matrix.right.y = 0.0f; + matrix.right.z = 0.0f; + + matrix.up.x = 0.0f; + matrix.up.y = cos(fAngle); + matrix.up.z = sin(fAngle); + + matrix.at.x = 0.0f; + matrix.at.y = -sin(fAngle); + matrix.at.z = cos(fAngle); + } + + inline void SetRotateYOnly(float fAngle) + { + matrix.right.x = cos(fAngle); + matrix.right.y = 0.0f; + matrix.right.z = sin(fAngle); + + matrix.up.x = 0.0f; + matrix.up.y = 1.0f; + matrix.up.z = 0.0f; + + matrix.at.x = -sin(fAngle); + matrix.at.y = 0.0f; + matrix.at.z = cos(fAngle); + } + + inline void SetRotateZOnly(float fAngle) + { + matrix.at.x = 0.0f; + matrix.at.y = 0.0f; + matrix.at.z = 1.0f; + + matrix.up.x = -sin(fAngle); + matrix.up.y = cos(fAngle); + matrix.up.z = 0.0f; + + matrix.right.x = cos(fAngle); + matrix.right.y = sin(fAngle); + matrix.right.z = 0.0f; + } + + inline void SetRotateOnly(float fAngleX, float fAngleY, float fAngleZ) + { + matrix.right.x = cos(fAngleZ) * cos(fAngleY) - sin(fAngleZ) * sin(fAngleX) * sin(fAngleY); + matrix.right.y = cos(fAngleZ) * sin(fAngleX) * sin(fAngleY) + sin(fAngleZ) * cos(fAngleY); + matrix.right.z = -cos(fAngleX) * sin(fAngleY); + + matrix.up.x = -sin(fAngleZ) * cos(fAngleX); + matrix.up.y = cos(fAngleZ) * cos(fAngleX); + matrix.up.z = sin(fAngleX); + + matrix.at.x = sin(fAngleZ) * sin(fAngleX) * cos(fAngleY) + cos(fAngleZ) * sin(fAngleY); + matrix.at.y = sin(fAngleZ) * sin(fAngleY) - cos(fAngleZ) * sin(fAngleX) * cos(fAngleY); + matrix.at.z = cos(fAngleX) * cos(fAngleY); + } + + inline void Attach(RwMatrix* pMatrix, bool bHasMatrix) + { + if ( this->pMatrix && haveRwMatrix ) + RwMatrixDestroy(this->pMatrix); + + this->pMatrix = pMatrix; + haveRwMatrix = bHasMatrix; + + Update(); + } + + inline void AttachRw(RwMatrix* pMatrix, bool bHasMatrix) + { + if ( this->pMatrix && haveRwMatrix ) + RwMatrixDestroy(this->pMatrix); + + this->pMatrix = pMatrix; + haveRwMatrix = bHasMatrix; + + UpdateRW(); + } + + inline void Detach() + { + if ( pMatrix ) + { + if ( haveRwMatrix ) + RwMatrixDestroy(pMatrix); + pMatrix = nullptr; + } + } + + inline void UpdateRW() const + { + if ( pMatrix ) + UpdateRwMatrix(pMatrix); + } + + inline void Update() + { + UpdateMatrix(pMatrix); + } + + inline void UpdateMatrix(RwMatrix* pMatrix) + { + matrix.right = pMatrix->right; + matrix.up = pMatrix->up; + matrix.at = pMatrix->at; + matrix.pos = pMatrix->pos; + } + + inline void UpdateRwMatrix(RwMatrix* pMatrix) const + { + pMatrix->right = matrix.right; + pMatrix->up = matrix.up; + pMatrix->at = matrix.at; + pMatrix->pos = matrix.pos; + RwMatrixUpdate(pMatrix); + } + + inline void CopyToRwMatrix(RwMatrix* pMatrix) const + { + pMatrix->right = this->pMatrix->right; + pMatrix->up = this->pMatrix->up; + pMatrix->at = this->pMatrix->at; + pMatrix->pos = this->pMatrix->pos; + RwMatrixUpdate(pMatrix); + } + + inline void CopyOnlyMatrix(const CMatrix& from) + { + matrix = from.matrix; + } +}; + +#endif \ No newline at end of file diff --git a/SilentPatch/MemoryMgr.h b/SilentPatch/MemoryMgr.h new file mode 100644 index 0000000..838c317 --- /dev/null +++ b/SilentPatch/MemoryMgr.h @@ -0,0 +1,118 @@ +#ifndef __MEMORYMGR +#define __MEMORYMGR + +#define WRAPPER __declspec(naked) +#define EAXJMP(a) { _asm mov eax, a _asm jmp eax } +#define WRAPARG(a) UNREFERENCED_PARAMETER(a) + +#define NOVMT __declspec(novtable) +#define SETVMT(a) *((DWORD_PTR*)this) = (DWORD_PTR)a + +// A macro used to inject method pointers +#define InjectMethod(address, hook, nType) { void* __funcPtr; { _asm mov eax, offset hook _asm mov __funcPtr, eax } \ + Memory::InjectHook(address, __funcPtr, nType); } +#define InjectMethodVP(address, hook, nType) { void* __funcPtr; { _asm mov eax, offset hook _asm mov __funcPtr, eax } \ + MemoryVP::InjectHook(address, __funcPtr, nType); } + +enum +{ + PATCH_CALL, + PATCH_JUMP, + PATCH_NOTHING, +}; + +namespace Memory +{ + template + inline void Patch(AT address, T value) + { *(T*)address = value; } + + template + inline void Nop(AT address, unsigned int nCount) + // TODO: Finish multibyte nops + { memset((void*)address, 0x90, nCount); } + + template + inline void InjectHook(AT address, HT hook, unsigned int nType=PATCH_NOTHING) + { + switch ( nType ) + { + case PATCH_JUMP: + *(BYTE*)address = 0xE9; + break; + case PATCH_CALL: + *(BYTE*)address = 0xE8; + break; + } + *(DWORD*)((DWORD)address + 1) = (DWORD)hook - (DWORD)address - 5; + } +}; + +namespace MemoryVP +{ + template + inline void Patch(AT address, T value) + { + DWORD dwProtect[2]; + VirtualProtect((void*)address, sizeof(T), PAGE_EXECUTE_READWRITE, &dwProtect[0]); + *(T*)address = value; + VirtualProtect((void*)address, sizeof(T), dwProtect[0], &dwProtect[1]); + } + + template + inline void Nop(AT address, unsigned int nCount) + // TODO: Finish multibyte nops + { + DWORD dwProtect[2]; + VirtualProtect((void*)address, nCount, PAGE_EXECUTE_READWRITE, &dwProtect[0]); + memset((void*)address, 0x90, nCount); + VirtualProtect((void*)address, nCount, dwProtect[0], &dwProtect[1]); + } + + template + inline void InjectHook(AT address, HT hook, unsigned int nType=PATCH_NOTHING) + { + DWORD dwProtect[2]; + switch ( nType ) + { + case PATCH_JUMP: + VirtualProtect((void*)address, 5, PAGE_EXECUTE_READWRITE, &dwProtect[0]); + *(BYTE*)address = 0xE9; + break; + case PATCH_CALL: + VirtualProtect((void*)address, 5, PAGE_EXECUTE_READWRITE, &dwProtect[0]); + *(BYTE*)address = 0xE8; + break; + default: + VirtualProtect((void*)((DWORD)address + 1), 4, PAGE_EXECUTE_READWRITE, &dwProtect[0]); + break; + } + *(DWORD*)((DWORD)address + 1) = (DWORD)hook - (DWORD)address - 5; + if ( nType == PATCH_NOTHING ) + VirtualProtect((void*)((DWORD)address + 1), 4, dwProtect[0], &dwProtect[1]); + else + VirtualProtect((void*)address, 5, dwProtect[0], &dwProtect[1]); + } +}; + +// Old code, remove asap +#define patch(a, v, s) _patch((void*)(a), (DWORD)(v), (s)) +#define patchf(a, v) _patch((void*)(a), (float)(v)) +#define nop(a, v) _nop((void*)(a), (v)) +#define call(a, v, bAddCall) _call((void*)(a), (DWORD)(v), (bAddCall)) +#define charptr(a, v) _charptr((void*)(a), (const char*)(v)) + +__declspec(deprecated) inline void _patch(void* pAddress, DWORD data, DWORD iSize) +{ + switch(iSize) + { + case 1: *(BYTE*)pAddress = (BYTE)data; + break; + case 2: *(WORD*)pAddress = (WORD)data; + break; + case 4: *(DWORD*)pAddress = (DWORD)data; + break; + } +} + +#endif \ No newline at end of file diff --git a/SilentPatch/ModelInfoSA.cpp b/SilentPatch/ModelInfoSA.cpp new file mode 100644 index 0000000..409d7fd --- /dev/null +++ b/SilentPatch/ModelInfoSA.cpp @@ -0,0 +1,41 @@ +#include "StdAfx.h" +#include "ModelInfoSA.h" + +void CVehicleModelInfo::FindEditableMaterialList() +{ + std::pair MatsPair = std::make_pair(this, 0); + + RpClumpForAllAtomics(reinterpret_cast(pRwObject), GetEditableMaterialListCB, &MatsPair); + + if ( m_pVehicleStruct->m_nNumExtras > 0 ) + { + for ( int i = 0; i < m_pVehicleStruct->m_nNumExtras; i++ ) + GetEditableMaterialListCB(m_pVehicleStruct->m_apExtras[i], &MatsPair); + } + + m_nPrimaryColor = -1; + m_nSecondaryColor = -1; + m_nTertiaryColor = -1; + m_nQuaternaryColor = -1; +} + +RpAtomic* CVehicleModelInfo::GetEditableMaterialListCB(RpAtomic* pAtomic, void* pData) +{ + RpGeometryForAllMaterials(RpAtomicGetGeometry(pAtomic), GetEditableMaterialListCB, pData); + return pAtomic; +} + +RpMaterial* CVehicleModelInfo::GetEditableMaterialListCB(RpMaterial* pMaterial, void* pData) +{ + if ( RpMaterialGetTexture(pMaterial) ) + { + if ( !strncmp(RwTextureGetName(RpMaterialGetTexture(pMaterial)), "vehiclegrunge256", 16) ) + { + std::pair* pMats = static_cast*>(pData); + + if ( pMats->second < 32 ) + pMats->first->m_apDirtMaterials[pMats->second++] = pMaterial; + } + } + return pMaterial; +} \ No newline at end of file diff --git a/SilentPatch/ModelInfoSA.h b/SilentPatch/ModelInfoSA.h new file mode 100644 index 0000000..e631d4f --- /dev/null +++ b/SilentPatch/ModelInfoSA.h @@ -0,0 +1,282 @@ +#ifndef __MODELINFO +#define __MODELINFO + +#include "General.h" + +// TODO: Move to a separate file? +typedef struct +{ + CVector vecMin; + CVector vecMax; + CVector vecOffset; + FLOAT fRadius; +} CBoundingBox; + + +typedef struct +{ + CVector vecCenter; + float fRadius; +} CColSphere; + + +typedef struct +{ + CVector min; + CVector max; +} CColBox; + + +/*typedef struct +{ + unsigned short v1; + unsigned short v2; + unsigned short v3; + EColSurface material; + CColLighting lighting; +} CColTriangle; + + +typedef struct +{ + BYTE pad0 [ 12 ]; +} CColTrianglePlane;*/ + + +typedef struct +{ + char version[4]; + DWORD size; + char name[0x18]; +} ColModelFileHeader; + +typedef struct +{ + WORD numColSpheres; + WORD numColBoxes; + WORD numColTriangles; + BYTE ucNumWheels; + BYTE pad3; + CColSphere* pColSpheres; + CColBox* pColBoxes; + void* pSuspensionLines; + void* pUnknown; + void* pColTriangles; + void* pColTrianglePlanes; +} CColData; + +class CColModel +{ +public: + CBoundingBox boundingBox; + BYTE level; + BYTE unknownFlags; + BYTE pad [ 2 ]; + CColData* pColData; + +public: + ~CColModel() + { + // Dirty! + ((void(__thiscall*)(CColModel*))0x40F700)(this); + } + + void operator delete(void* ptr); +}; + +class C2dEffect +{ +public: + CVector vecPos; + BYTE bType; + DWORD nCount; +}; + +class CTimeInfo +{ +public: + unsigned char bTimeOn, bTimeOff; + signed short nPairedModel; + +public: + CTimeInfo(signed short nModel) + : nPairedModel(nModel) + {} +}; + +struct UpgradePosnDesc +{ + CVector m_vPosition; + CVector m_qRotation; + float imag; + int m_dwParentComponentId; +}; + +class CAtomicModelInfo; +class CDamageAtomicModelInfo; +class CLodAtomicModelInfo; + +class CBaseModelInfo +{ +public: + unsigned int ulHashKey; // +4 Generated by CKeyGen::GetUppercaseKey(char const *) called by CBaseModelInfo::SetModelName(char const *) + unsigned short usNumberOfRefs: 16; // +8 + short usTextureDictionary: 16; // +10 + unsigned char ucAlpha: 8; // +12 + + unsigned char ucNumOf2DEffects: 8; // +13 + unsigned short usUnknown: 16; // +14 Something with 2d effects + + unsigned char ucDynamicIndex: 8; // +16 + + unsigned char dwUnknownFlag9: 1; // +17 + unsigned char dwUnknownFlag10: 1; + unsigned char dwUnknownFlag11: 1; + unsigned char dwUnknownFlag12: 1; + unsigned char dwUnknownFlag13: 1; + unsigned char dwUnknownFlag14: 1; + unsigned char dwUnknownFlag15: 1; + unsigned char dwUnknownFlag16: 1; + + // Flags used by CBaseModelInfo + unsigned char bHasBeenPreRendered: 1; // +18 + unsigned char bAlphaTransparency: 1; + unsigned char bIsLod: 1; + unsigned char bDontCastShadowsOn: 1; + unsigned char bDontWriteZBuffer: 1; + unsigned char bDrawAdditive: 1; + unsigned char bDrawLast: 1; + unsigned char bDoWeOwnTheColModel: 1; + + unsigned char dwUnknownFlag25: 1; // +19 + unsigned char dwUnknownFlag26: 1; + unsigned char dwUnknownFlag27: 1; + unsigned char bSwaysInWind: 1; + unsigned char bCollisionWasStreamedWithModel: 1; // CClumpModelInfo::SetCollisionWasStreamedWithModel(unsigned int) + unsigned char bDontCollideWithFlyer: 1; // CAtomicModelInfo::SetDontCollideWithFlyer(unsigned int) + unsigned char bHasComplexHierarchy: 1; // CClumpModelInfo::SetHasComplexHierarchy(unsigned int) + unsigned char bWetRoadReflection: 1; // CAtomicModelInfo::SetWetRoadReflection(unsigned int) + CColModel* pColModel; // +20 CColModel: public CBoundingBox + float fLodDistanceUnscaled; // +24 Scaled is this value multiplied with flt_B6F118 + RwObject* pRwObject; // +28 + +public: + virtual ~CBaseModelInfo() {} + virtual CAtomicModelInfo* AsAtomicModelInfoPtr() { return nullptr; } + virtual CDamageAtomicModelInfo* AsDamageAtomicModelInfoPtr() { return nullptr; } + virtual CLodAtomicModelInfo* AsLodAtomicModelInfoPtr() { return nullptr; } + virtual unsigned char GetModelType()=0; + virtual CTimeInfo* GetTimeInfo() { return nullptr; } + virtual void Init(); + virtual void Shutdown(); + virtual void DeleteRwObject()=0; + virtual int GetRwModelType()=0; + virtual RpAtomic* CreateInstance_(RwMatrix* pMatrix)=0; + virtual RpAtomic* CreateInstance()=0; + virtual void SetAnimFile(const char* pName) { UNREFERENCED_PARAMETER(pName); } + virtual void ConvertAnimFileIndex() {} + virtual int GetAnimFileIndex() { return -1; } + + CBaseModelInfo() + : usNumberOfRefs(0), usTextureDictionary(-1) + {} + + inline CColModel* GetColModel() { return pColModel; } + inline unsigned int GetHash() { return ulHashKey; } + inline short GetTextureDict() { return usTextureDictionary; } + + void RecalcDrawDistance(float fOldDist); + void SetTexDictionary(const char* pDict); + void AddRef(); +}; + +class CClumpModelInfo : public CBaseModelInfo +{ +public: + int nAnimIndex; + +public: + virtual unsigned char GetModelType() override { return 5; } + virtual void Init() override; + virtual void DeleteRwObject() override; + virtual int GetRwModelType() override { return rpCLUMP; } + virtual RpAtomic* CreateInstance_(RwMatrix* pMatrix) override; + virtual RpAtomic* CreateInstance() override; + virtual void SetAnimFile(const char* pName) override; + virtual void ConvertAnimFileIndex() override; + virtual int GetAnimFileIndex() override { return nAnimIndex; } + virtual CColModel* GetBoundingBox() { return pColModel; } + virtual void SetClump(RpClump* pClump); +}; + +class CVehicleModelInfo : public CClumpModelInfo +{ +public: + RpMaterial* m_pPlateMaterial; + char m_plateText[8]; + char field_30; + unsigned char m_nPlateType; + char m_nGameName[8]; + unsigned int m_dwType; + float m_fWheelSizeFront; + float m_fWheelSizeRear; + unsigned short m_wWheelModelId; + unsigned short m_wHandlingIndex; + unsigned char m_nNumDoors; + unsigned char m_nClass; + unsigned char m_nFlags; + unsigned char m_nWheelUpgradeClass; + unsigned short m_wTimesUsed; + unsigned short m_wFrq; + union{ + unsigned int m_dwCompRules; + struct{ + unsigned int m_nExtraA_comp1 : 4; + unsigned int m_nExtraA_comp2 : 4; + unsigned int m_nExtraA_comp3 : 4; + unsigned int m_nExtraA_rule : 4; + unsigned int m_nExtraB_comp1 : 4; + unsigned int m_nExtraB_comp2 : 4; + unsigned int m_nExtraB_comp3 : 4; + unsigned int m_nExtraB_rule : 4; + }; + }; + float m_fBikeSteerAngle; + + class CVehicleStructure{ + public: + CVector m_avDummyPosn[15]; + UpgradePosnDesc m_aUpgrades[18]; + RpAtomic* m_apExtras[6]; + unsigned char m_nNumExtras; + unsigned int m_dwMaskComponentsDamagable; + } *m_pVehicleStruct; + + char field_60[464]; + RpMaterial* m_apDirtMaterials[32]; + unsigned char m_anPrimaryColors[8]; + unsigned char m_anSecondaryColors[8]; + unsigned char m_anTertiaryColors[8]; + unsigned char m_anQuaternaryColors[8]; + unsigned char m_nNumColorVariations; + unsigned char m_nLastColorVariation; + signed char m_nPrimaryColor; + signed char m_nSecondaryColor; + signed char m_nTertiaryColor; + signed char m_nQuaternaryColor; + short m_awUpgrades[18]; + short m_awRemapTxds[5]; + class CAnimBlock* m_pAnimBlock; + +public: + void FindEditableMaterialList(); + + static RpAtomic* GetEditableMaterialListCB(RpAtomic* pAtomic, void* pData); + static RpMaterial* GetEditableMaterialListCB(RpMaterial* pMaterial, void* pData); +}; + +static_assert(sizeof(CBaseModelInfo) == 0x20, "Wrong size: CBaseModelInfo"); +static_assert(sizeof(CClumpModelInfo) == 0x24, "Wrong size: CClumpModelInfo"); +static_assert(sizeof(CVehicleModelInfo) == 0x308, "Wrong size: CvehicleModelInfo"); + +#endif \ No newline at end of file diff --git a/SilentPatch/StdAfx.cpp b/SilentPatch/StdAfx.cpp new file mode 100644 index 0000000..09f15b6 --- /dev/null +++ b/SilentPatch/StdAfx.cpp @@ -0,0 +1 @@ +#include "StdAfx.h" \ No newline at end of file diff --git a/SilentPatch/StdAfx.h b/SilentPatch/StdAfx.h new file mode 100644 index 0000000..5ea5cc3 --- /dev/null +++ b/SilentPatch/StdAfx.h @@ -0,0 +1,25 @@ +#pragma warning(disable:4481) // nonstandard extension used: override specifier 'override' +#pragma warning(disable:4401) // member is bit field +#pragma warning(disable:4733) // handler not registered as safe handler +#pragma warning(disable:4725) // instruction may be inaccurate on some Pentiums + +#define WIN32_LEAN_AND_MEAN +#define _CRT_SECURE_NO_WARNINGS +#define _USE_MATH_DEFINES + +#define WINVER 0x0501 +#define _WIN32_WINNT 0x0501 + +#include +#include +#include +#include + +#define RwEngineInstance (*rwengine) +#define RWFRAMESTATICPLUGINSSIZE 24 + +#include +#include + +#include "MemoryMgr.h" +#include "Maths.h" \ No newline at end of file diff --git a/SilentPatch/Timer.cpp b/SilentPatch/Timer.cpp new file mode 100644 index 0000000..863672b --- /dev/null +++ b/SilentPatch/Timer.cpp @@ -0,0 +1,185 @@ +#include "StdAfx.h" + +#include "Timer.h" + +float* CTimer::ms_fTimeScale; +float* CTimer::ms_fTimeStep; +float* CTimer::ms_fTimeStepNotClipped; +bool* CTimer::m_UserPause; +bool* CTimer::m_CodePause; +int* CTimer::m_snTimeInMilliseconds; +int* CTimer::m_snPreviousTimeInMilliseconds; +int* CTimer::m_snTimeInMillisecondsNonClipped; +int* CTimer::m_snTimeInMillisecondsPauseMode; +unsigned int* CTimer::m_FrameCounter; + +static gtaTimer timerFunction; +static unsigned int suspendDepth; +static long long timerFreq; +static long long oldTime, suspendTime; + +static long long cyclesTime, cyclesTimeNonClipped, cyclesTimePauseMode, cyclesPreviousTime; + +static long long QPC() +{ + LARGE_INTEGER Counter; + QueryPerformanceCounter(&Counter); + return Counter.QuadPart; +} + +static long long OldTimer() +{ + TIMECAPS caps; + long long nTime; + + timeGetDevCaps(&caps, sizeof(TIMECAPS)); + timeBeginPeriod(caps.wPeriodMin); + nTime = timeGetTime(); + timeEndPeriod(caps.wPeriodMin); + return nTime; +} + +static inline void InitTimerFunc() +{ + if ( timerFunction ) + return; + + LARGE_INTEGER Frequency; + if ( QueryPerformanceFrequency(&Frequency) ) + { + timerFreq = Frequency.QuadPart / 1000; + timerFunction = QPC; + } + else + { + timerFreq = 1; + timerFunction = OldTimer; + } +} + +extern void (__stdcall *AudioResetTimers)(unsigned int); +extern bool* bSnapShotActive; + +void CTimer::Initialise() +{ + suspendDepth = 0; + *ms_fTimeScale = *ms_fTimeStep = 1.0f; + *m_UserPause = false; + *m_CodePause = false; + *m_snTimeInMilliseconds = 0; + *m_snPreviousTimeInMilliseconds = 0; + *m_snTimeInMillisecondsNonClipped = 0; + *m_FrameCounter = 0; + + InitTimerFunc(); + + oldTime = timerFunction(); + AudioResetTimers(0); +} + +void CTimer::Suspend() +{ + if ( suspendDepth++ == 0 ) + { +#ifdef SILENTPATCH_VC_VER + // MVL fix + InitTimerFunc(); +#endif + suspendTime = timerFunction(); + } +} + +void CTimer::Resume() +{ + if ( --suspendDepth == 0 ) + { +#ifdef SILENTPATCH_VC_VER + // MVL fix + InitTimerFunc(); +#endif + oldTime = timerFunction() - suspendTime; + } +} + +unsigned int CTimer::GetCyclesPerFrame() +{ +#ifdef SILENTPATCH_VC_VER + // MVL fix + InitTimerFunc(); +#endif + return static_cast(timerFunction() - oldTime); +} + +unsigned int CTimer::GetCyclesPerMillisecond() +{ + return static_cast(timerFreq); +} + +void CTimer::Update() +{ +#ifdef SILENTPATCH_VC_VER + // CTimer::Initialise workaround + static bool bIntialisedIt = false; + + if ( !bIntialisedIt ) + { + Initialise(); + bIntialisedIt = true; + } +#endif + + *m_snPreviousTimeInMilliseconds = *m_snTimeInMilliseconds; + cyclesPreviousTime = cyclesTime; + + long long nCurTime; + float nDelta; + + nCurTime = timerFunction(); + nDelta = (nCurTime - oldTime) * *ms_fTimeScale; + oldTime = nCurTime; + + //*m_snTimeInMillisecondsPauseMode += nDelta; + cyclesTimePauseMode += static_cast(nDelta); + + if ( *m_UserPause || *m_CodePause ) + *ms_fTimeStep = 0.0f; + else + { + *ms_fTimeStep = (nDelta/timerFreq) * 0.05f; + cyclesTime += static_cast(nDelta); + cyclesTimeNonClipped += static_cast(nDelta); + //*m_snTimeInMilliseconds += nDelta; + //*m_snTimeInMillisecondsNonClipped += nDelta; + } + +#ifdef SILENTPATCH_III_VER + if ( *ms_fTimeStep < 0.01f && !*m_UserPause && !*m_CodePause ) +#else + if ( *ms_fTimeStep < 0.01f && !*m_UserPause && !*m_CodePause && !*bSnapShotActive ) +#endif + *ms_fTimeStep = 0.01f; + + *ms_fTimeStepNotClipped = *ms_fTimeStep; + + if ( *ms_fTimeStep > 3.0f ) + *ms_fTimeStep = 3.0f; + + /*if ( *m_snTimeInMilliseconds - *m_snPreviousTimeInMilliseconds > 60 ) + *m_snTimeInMilliseconds = *m_snPreviousTimeInMilliseconds + 60;*/ + if ( cyclesTime - cyclesPreviousTime > 60 * timerFreq ) + cyclesTime = cyclesPreviousTime + (60 * timerFreq); + + *m_snTimeInMillisecondsPauseMode = static_cast(cyclesTimePauseMode / timerFreq); + *m_snTimeInMilliseconds = static_cast(cyclesTime / timerFreq); + *m_snTimeInMillisecondsNonClipped = static_cast(cyclesTimeNonClipped / timerFreq); + + ++(*m_FrameCounter); +} + +void CTimer::RecoverFromSave() +{ + cyclesTime = *m_snTimeInMilliseconds * timerFreq; + cyclesPreviousTime = *m_snPreviousTimeInMilliseconds * timerFreq; + cyclesTimePauseMode = *m_snTimeInMillisecondsPauseMode * timerFreq; + cyclesTimeNonClipped = *m_snTimeInMillisecondsNonClipped * timerFreq; +} \ No newline at end of file diff --git a/SilentPatch/Timer.h b/SilentPatch/Timer.h new file mode 100644 index 0000000..6173e44 --- /dev/null +++ b/SilentPatch/Timer.h @@ -0,0 +1,30 @@ +#ifndef __TIMER +#define __TIMER + +typedef long long(*gtaTimer)(); + +class CTimer +{ +public: + static float* ms_fTimeScale; + static float* ms_fTimeStep; + static float* ms_fTimeStepNotClipped; + static bool* m_UserPause; + static bool* m_CodePause; + static int* m_snTimeInMilliseconds; + static int* m_snPreviousTimeInMilliseconds; + static int* m_snTimeInMillisecondsNonClipped; + static int* m_snTimeInMillisecondsPauseMode; + static unsigned int* m_FrameCounter; + +public: + static void Initialise(); + static void Suspend(); + static void Resume(); + static unsigned int GetCyclesPerFrame(); + static unsigned int GetCyclesPerMillisecond(); + static void Update(); + static void RecoverFromSave(); +}; + +#endif \ No newline at end of file diff --git a/SilentPatch/Vehicle.cpp b/SilentPatch/Vehicle.cpp new file mode 100644 index 0000000..3994bce --- /dev/null +++ b/SilentPatch/Vehicle.cpp @@ -0,0 +1,120 @@ +#include "StdAfx.h" + +#include "Vehicle.h" +#include "Timer.h" + +WRAPPER void CVehicle::SetComponentAtomicAlpha(RpAtomic* pAtomic, int nAlpha) { WRAPARG(pAtomic); WRAPARG(nAlpha); EAXJMP(0x6D2960); } +WRAPPER void CVehicle::Render() { EAXJMP(0x6D0E60); } + +static RwObject* GetCurrentAtomicObjectCB(RwObject* pObject, void* data) +{ + if ( RpAtomicGetFlags(pObject) & rpATOMICRENDER ) + *static_cast(data) = pObject; + return pObject; +} + +void CHeli::Render() +{ + double dRotorsSpeed, dMovingRotorSpeed; + + m_nTimeTillWeNeedThisCar = *CTimer::m_snTimeInMilliseconds + 3000; + + if ( m_fRotorSpeed > 0.0 ) + dRotorsSpeed = min(1.7 * (1.0/0.22) * m_fRotorSpeed, 1.5); + else + dRotorsSpeed = 0.0; + + dMovingRotorSpeed = dRotorsSpeed - 0.4; + if ( dMovingRotorSpeed < 0.0 ) + dMovingRotorSpeed = 0.0; + + int nStaticRotorAlpha = static_cast(min((1.5-dRotorsSpeed) * 255.0, 255)); + int nMovingRotorAlpha = static_cast(min(dMovingRotorSpeed * 175.0, 175)); + + if ( m_pCarNode[11] ) + { + RpAtomic* pOutAtomic = nullptr; + RwFrameForAllObjects(m_pCarNode[11], GetCurrentAtomicObjectCB, &pOutAtomic); + if ( pOutAtomic ) + SetComponentAtomicAlpha(pOutAtomic, nStaticRotorAlpha); + } + + if ( m_pCarNode[13] ) + { + RpAtomic* pOutAtomic = nullptr; + RwFrameForAllObjects(m_pCarNode[13], GetCurrentAtomicObjectCB, &pOutAtomic); + if ( pOutAtomic ) + SetComponentAtomicAlpha(pOutAtomic, nStaticRotorAlpha); + } + + if ( m_pCarNode[12] ) + { + RpAtomic* pOutAtomic = nullptr; + RwFrameForAllObjects(m_pCarNode[12], GetCurrentAtomicObjectCB, &pOutAtomic); + if ( pOutAtomic ) + SetComponentAtomicAlpha(pOutAtomic, nMovingRotorAlpha); + } + + if ( m_pCarNode[14] ) + { + RpAtomic* pOutAtomic = nullptr; + RwFrameForAllObjects(m_pCarNode[14], GetCurrentAtomicObjectCB, &pOutAtomic); + if ( pOutAtomic ) + SetComponentAtomicAlpha(pOutAtomic, nMovingRotorAlpha); + } + + CEntity::Render(); +} + +void CPlane::Render() +{ + double dRotorsSpeed, dMovingRotorSpeed; + + m_nTimeTillWeNeedThisCar = *CTimer::m_snTimeInMilliseconds + 3000; + + if ( m_fPropellerSpeed > 0.0 ) + dRotorsSpeed = min(1.7 * (1.0/0.31) * m_fPropellerSpeed, 1.5); + else + dRotorsSpeed = 0.0; + + dMovingRotorSpeed = dRotorsSpeed - 0.4; + if ( dMovingRotorSpeed < 0.0 ) + dMovingRotorSpeed = 0.0; + + int nStaticRotorAlpha = static_cast(min((1.5-dRotorsSpeed) * 255.0, 255)); + int nMovingRotorAlpha = static_cast(min(dMovingRotorSpeed * 175.0, 175)); + + if ( m_pCarNode[11] ) + { + RpAtomic* pOutAtomic = nullptr; + RwFrameForAllObjects(m_pCarNode[11], GetCurrentAtomicObjectCB, &pOutAtomic); + if ( pOutAtomic ) + SetComponentAtomicAlpha(pOutAtomic, nStaticRotorAlpha); + } + + if ( m_pCarNode[13] ) + { + RpAtomic* pOutAtomic = nullptr; + RwFrameForAllObjects(m_pCarNode[13], GetCurrentAtomicObjectCB, &pOutAtomic); + if ( pOutAtomic ) + SetComponentAtomicAlpha(pOutAtomic, nStaticRotorAlpha); + } + + if ( m_pCarNode[12] ) + { + RpAtomic* pOutAtomic = nullptr; + RwFrameForAllObjects(m_pCarNode[12], GetCurrentAtomicObjectCB, &pOutAtomic); + if ( pOutAtomic ) + SetComponentAtomicAlpha(pOutAtomic, nMovingRotorAlpha); + } + + if ( m_pCarNode[14] ) + { + RpAtomic* pOutAtomic = nullptr; + RwFrameForAllObjects(m_pCarNode[14], GetCurrentAtomicObjectCB, &pOutAtomic); + if ( pOutAtomic ) + SetComponentAtomicAlpha(pOutAtomic, nMovingRotorAlpha); + } + + CVehicle::Render(); +} \ No newline at end of file diff --git a/SilentPatch/Vehicle.h b/SilentPatch/Vehicle.h new file mode 100644 index 0000000..756657a --- /dev/null +++ b/SilentPatch/Vehicle.h @@ -0,0 +1,141 @@ +#ifndef __VEHICLE +#define __VEHICLE + +#include "General.h" + +struct CVehicleFlags +{ + //0x428 + unsigned char bIsLawEnforcer: 1; // Is this guy chasing the player at the moment + unsigned char bIsAmbulanceOnDuty: 1; // Ambulance trying to get to an accident + unsigned char bIsFireTruckOnDuty: 1; // Firetruck trying to get to a fire + unsigned char bIsLocked: 1; // Is this guy locked by the script (cannot be removed) + unsigned char bEngineOn: 1; // For sound purposes. Parked cars have their engines switched off (so do destroyed cars) + unsigned char bIsHandbrakeOn: 1; // How's the handbrake doing ? + unsigned char bLightsOn: 1; // Are the lights switched on ? + unsigned char bFreebies: 1; // Any freebies left in this vehicle ? + + //0x429 + unsigned char bIsVan: 1; // Is this vehicle a van (doors at back of vehicle) + unsigned char bIsBus: 1; // Is this vehicle a bus + unsigned char bIsBig: 1; // Is this vehicle big + unsigned char bLowVehicle: 1; // Need this for sporty type cars to use low getting-in/out anims + unsigned char bComedyControls: 1; // Will make the car hard to control (hopefully in a funny way) + unsigned char bWarnedPeds: 1; // Has scan and warn peds of danger been processed? + unsigned char bCraneMessageDone: 1; // A crane message has been printed for this car allready + // unsigned char bExtendedRange: 1; // This vehicle needs to be a bit further away to get deleted + unsigned char bTakeLessDamage: 1; // This vehicle is stronger (takes about 1/4 of damage) + + //0x42A + unsigned char bIsDamaged: 1; // This vehicle has been damaged and is displaying all its components + unsigned char bHasBeenOwnedByPlayer : 1;// To work out whether stealing it is a crime + unsigned char bFadeOut: 1; // Fade vehicle out + unsigned char bIsBeingCarJacked: 1; + unsigned char bCreateRoadBlockPeds : 1;// If this vehicle gets close enough we will create peds (coppers or gang members) round it + unsigned char bCanBeDamaged: 1; // Set to FALSE during cut scenes to avoid explosions + // unsigned char bUsingSpecialColModel : 1; + // Is player vehicle using special collision model, stored in player strucure + unsigned char bOccupantsHaveBeenGenerated : 1; // Is true if the occupants have already been generated. (Shouldn't happen again) + unsigned char bGunSwitchedOff: 1; // Level designers can use this to switch off guns on boats + + //0x42B + unsigned char bVehicleColProcessed : 1;// Has ProcessEntityCollision been processed for this car? + unsigned char bIsCarParkVehicle: 1; // Car has been created using the special CAR_PARK script command + unsigned char bHasAlreadyBeenRecorded : 1; // Used for replays + unsigned char bPartOfConvoy: 1; + unsigned char bHeliMinimumTilt: 1; // This heli should have almost no tilt really + unsigned char bAudioChangingGear: 1; // sounds like vehicle is changing gear + unsigned char bIsDrowning: 1; // is vehicle occupants taking damage in water (i.e. vehicle is dead in water) + unsigned char bTyresDontBurst: 1; // If this is set the tyres are invincible + + //0x42C + unsigned char bCreatedAsPoliceVehicle : 1;// True if this guy was created as a police vehicle (enforcer, policecar, miamivice car etc) + unsigned char bRestingOnPhysical: 1; // Dont go static cause car is sitting on a physical object that might get removed + unsigned char bParking : 1; + unsigned char bCanPark : 1; + unsigned char bFireGun: 1; // Does the ai of this vehicle want to fire it's gun? + unsigned char bDriverLastFrame: 1; // Was there a driver present last frame ? + unsigned char bNeverUseSmallerRemovalRange: 1;// Some vehicles (like planes) we don't want to remove just behind the camera. + unsigned char bIsRCVehicle: 1; // Is this a remote controlled (small) vehicle. True whether the player or AI controls it. + + //0x42D + unsigned char bAlwaysSkidMarks: 1; // This vehicle leaves skidmarks regardless of the wheels' states. + unsigned char bEngineBroken: 1; // Engine doesn't work. Player can get in but the vehicle won't drive + unsigned char bVehicleCanBeTargetted : 1;// The ped driving this vehicle can be targetted, (for Torenos plane mission) + unsigned char bPartOfAttackWave: 1; // This car is used in an attack during a gang war + unsigned char bWinchCanPickMeUp: 1; // This car cannot be picked up by any ropes. + unsigned char bImpounded: 1; // Has this vehicle been in a police impounding garage + unsigned char bVehicleCanBeTargettedByHS : 1;// Heat seeking missiles will not target this vehicle. + unsigned char bSirenOrAlarm: 1; // Set to TRUE if siren or alarm active, else FALSE + + //0x42E + unsigned char bHasGangLeaningOn: 1; + unsigned char bGangMembersForRoadBlock : 1;// Will generate gang members if NumPedsForRoadBlock > 0 + unsigned char bDoesProvideCover: 1; // If this is false this particular vehicle can not be used to take cover behind. + unsigned char bMadDriver: 1; // This vehicle is driving like a lunatic + unsigned char bUpgradedStereo: 1; // This vehicle has an upgraded stereo + unsigned char bConsideredByPlayer: 1; // This vehicle is considered by the player to enter + unsigned char bPetrolTankIsWeakPoint : 1;// If false shootong the petrol tank will NOT Blow up the car + unsigned char bDisableParticles: 1; // Disable particles from this car. Used in garage. + + //0x42F + unsigned char bHasBeenResprayed: 1; // Has been resprayed in a respray garage. Reset after it has been checked. + unsigned char bUseCarCheats: 1; // If this is true will set the car cheat stuff up in ProcessControl() + unsigned char bDontSetColourWhenRemapping : 1;// If the texture gets remapped we don't want to change the colour with it. + unsigned char bUsedForReplay: 1; // This car is controlled by replay and should be removed when replay is done. +}; + +class NOVMT CVehicle : public CPhysical +{ +protected: + BYTE __pad1[752]; + CVehicleFlags m_nVehicleFlags; + BYTE __pad2[160]; + signed int m_nTimeTillWeNeedThisCar; + BYTE __pad4[56]; + CEntity* pDamagingEntity; + BYTE __pad3[144]; + +public: + CVehicleFlags& GetVehicleFlags() + { return m_nVehicleFlags; } + CEntity* GetDamagingEntity() + { return pDamagingEntity; } + + virtual void Render() override; + + static void SetComponentAtomicAlpha(RpAtomic* pAtomic, int nAlpha); +}; + +class NOVMT CAutomobile : public CVehicle +{ +public: + BYTE paddd[172]; + RwFrame* m_pCarNode[20]; // May be wrong? + BYTE padding[432]; + float m_fRotorSpeed; + BYTE __moarpad[312]; + +public: +}; + +class NOVMT CHeli : public CAutomobile +{ +public: + virtual void Render() override; +}; + +class NOVMT CPlane : public CAutomobile +{ +public: + BYTE __pad[60]; + float m_fPropellerSpeed; + +public: + virtual void Render() override; +}; + +static_assert(sizeof(CVehicle) == 0x5A0, "Wrong size: CVehicle"); +static_assert(sizeof(CAutomobile) == 0x988, "Wrong size: CAutomobile"); + +#endif \ No newline at end of file diff --git a/SilentPatch/dllmain.cpp b/SilentPatch/dllmain.cpp new file mode 100644 index 0000000..65ba324 --- /dev/null +++ b/SilentPatch/dllmain.cpp @@ -0,0 +1,1207 @@ +#include "StdAfx.h" + +#include "Timer.h" +#include "General.h" +#include "Vehicle.h" +#include "LinkList.h" +#include "ModelInfoSA.h" + +struct RsGlobalType +{ + const char* AppName; + unsigned int unkWidth, unkHeight; + unsigned int MaximumWidth; + unsigned int MaximumHeight; + unsigned int frameLimit; + BOOL quit; + void* ps; + void* keyboard; + void* mouse; + void* pad; +}; + +struct AlphaObjectInfo +{ + RpAtomic* pAtomic; + RpAtomic* (*callback)(RpAtomic*, float); + float fCompareValue; + + friend bool operator < (const AlphaObjectInfo &a, const AlphaObjectInfo &b) + { return a.fCompareValue < b.fCompareValue; } +}; + +// RW wrappers +// TODO: Multiple EXEs +WRAPPER RwFrame* RwFrameForAllObjects(RwFrame* frame, RwObjectCallBack callBack, void* data) { WRAPARG(frame); WRAPARG(callBack); WRAPARG(data); EAXJMP(0x7F1200); } +WRAPPER RpClump* RpClumpForAllAtomics(RpClump* clump, RpAtomicCallBack callback, void* pData) { WRAPARG(clump); WRAPARG(callback); WRAPARG(pData); EAXJMP(0x749B70); } +WRAPPER RpGeometry* RpGeometryForAllMaterials(RpGeometry* geometry, RpMaterialCallBack fpCallBack, void* pData) { WRAPARG(geometry); WRAPARG(fpCallBack); WRAPARG(pData); EAXJMP(0x74C790); } +WRAPPER RpAtomic* AtomicDefaultRenderCallBack(RpAtomic* atomic) { WRAPARG(atomic); EAXJMP(0x7491C0); } +WRAPPER void RwD3D9SetRenderState(RwUInt32 state, RwUInt32 value) { WRAPARG(state); WRAPARG(value); EAXJMP(0x7FC2D0); } + +WRAPPER void RenderOneXLUSprite(float x, float y, float z, float width, float height, int r, int g, int b, int a, float w, char, char, char) { EAXJMP(0x70D000); } + +#if defined SILENTPATCH_VC_VER + +bool* bSnapShotActive; +static const void* RosieAudioFix_JumpBack; + +#elif defined SILENTPATCH_III_VER + +static void (*DrawRect)(const CRect&,const CRGBA&); +static void (*SetScale)(float,float); +static int* InstantHitsFiredByPlayer; +static signed char* pGangModelOverrides; +static const void* HeadlightsFix_JumpBack; + +#elif defined SILENTPATCH_SA_VER + +bool* bSnapShotActive; + +#endif + +void (__stdcall *AudioResetTimers)(unsigned int); +static void (*PrintString)(float,float,const wchar_t*); + +static bool* bWantsToDrawHud; +static bool* bCamCheck; +static RsGlobalType* RsGlobal; +static const float* ResolutionWidthMult; +static const float* ResolutionHeightMult; +static const void* SubtitlesShadowFix_JumpBack; + +#if defined SILENTPATCH_III_VER + +void ShowRadarTrace(float fX, float fY, unsigned int nScale, BYTE r, BYTE g, BYTE b, BYTE a) +{ + if ( *bWantsToDrawHud == true && !*bCamCheck ) + { + DrawRect(CRect( fX - ((nScale+1.0f) * *ResolutionWidthMult * RsGlobal->MaximumWidth), + fY + ((nScale+1.0f) * *ResolutionHeightMult * RsGlobal->MaximumHeight), + fX + ((nScale+1.0f) * *ResolutionWidthMult * RsGlobal->MaximumWidth), + fY - ((nScale+1.0f) * *ResolutionHeightMult * RsGlobal->MaximumHeight)), + CRGBA(0, 0, 0, a)); + + DrawRect(CRect( fX - (nScale * *ResolutionWidthMult * RsGlobal->MaximumWidth), + fY + (nScale * *ResolutionHeightMult * RsGlobal->MaximumHeight), + fX + (nScale * *ResolutionWidthMult * RsGlobal->MaximumWidth), + fY - (nScale * *ResolutionHeightMult * RsGlobal->MaximumHeight)), + CRGBA(r, g, b, a)); + } +} + +void SetScaleProperly(float fX, float fY) +{ + SetScale(fX * *ResolutionWidthMult * RsGlobal->MaximumWidth, fY * *ResolutionHeightMult * RsGlobal->MaximumHeight); +} + +void PurpleNinesGlitchFix() +{ + for ( int i = 0; i < 9; ++i ) + pGangModelOverrides[i * 16] = -1; +} + +void __declspec(naked) M16StatsFix() +{ + _asm + { + add eax, 34h + add ebx, 34h + mov ecx, [InstantHitsFiredByPlayer] + inc [ecx] + retn + } +} + +void __declspec(naked) HeadlightsFix() +{ + static const float fMinusOne = -1.0f; + _asm + { + fld [esp+708h-690h] + fcomp fMinusOne + fnstsw ax + and ah, 5 + cmp ah, 1 + jnz HeadlightsFix_DontLimit + fld fMinusOne + fstp [esp+708h-690h] + +HeadlightsFix_DontLimit: + fld [esp+708h-690h] + fabs + fld st + jmp [HeadlightsFix_JumpBack] + } +} + +static float fShadowXSize, fShadowYSize; + +void __stdcall Recalculate(signed int nShadow) +{ + fShadowXSize = nShadow * *ResolutionWidthMult * RsGlobal->MaximumWidth; + fShadowYSize = nShadow * *ResolutionHeightMult * RsGlobal->MaximumHeight; +} + +#elif defined SILENTPATCH_VC_VER + +void __declspec(naked) RosiesAudioFix() +{ + _asm + { + mov byte ptr [ebx+0CCh], 0 + mov byte ptr [ebx+148h], 0 + jmp [RosieAudioFix_JumpBack] + } +} + +void __stdcall Recalculate(float& fX, float& fY, signed int nShadow) +{ + fX = nShadow * *ResolutionWidthMult * RsGlobal->MaximumWidth; + fY = nShadow * *ResolutionHeightMult * RsGlobal->MaximumHeight; +} + +#elif defined SILENTPATCH_SA_VER + +static CLinkList& m_alphaList = **(CLinkList**)0x733A4D; +static CLinkList& ms_weaponPedsForPC = **(CLinkList**)0x53EACA; + + +void** rwengine = *(void***)0x58FFC0; + +static inline void RenderOrderedList(CLinkList& list) +{ + for ( auto i = list.m_lnListTail.m_pPrev; i != &list.m_lnListHead; i = i->m_pPrev ) + i->V().callback(i->V().pAtomic, i->V().fCompareValue); +} + +void RenderAlphaAtomics() +{ + int nPushedAlpha; + + RwRenderStateGet(rwRENDERSTATEALPHATESTFUNCTIONREF, &nPushedAlpha); + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, 0); + //RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE); + RenderOrderedList(m_alphaList); + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, reinterpret_cast(nPushedAlpha)); + //RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, reinterpret_cast(TRUE)); +} + +RpAtomic* RenderAtomic(RpAtomic* pAtomic, float fComp) +{ + UNREFERENCED_PARAMETER(fComp); + return AtomicDefaultRenderCallBack(pAtomic); +} + +RpMaterial* AlphaTest(RpMaterial* pMaterial, void* pData) +{ + if ( RpMaterialGetTexture(pMaterial) ) + { + BOOL bHasAlpha = ((BOOL(*)(RwTexture*))0x4C9EA0)(RpMaterialGetTexture(pMaterial)); + if ( bHasAlpha ) + { + *static_cast(pData) = TRUE; + return nullptr; + } + } + else if ( RpMaterialGetColor(pMaterial)->alpha < 255 ) + { + *static_cast(pData) = TRUE; + return nullptr; + } + + return pMaterial; +} + +RpAtomic* TwoPassAlphaRender(RpAtomic* atomic) +{ + int nPushedAlpha, nAlphaFunction; + int nZWrite; + int nAlphaBlending; + + RwRenderStateGet(rwRENDERSTATEALPHATESTFUNCTIONREF, &nPushedAlpha); + RwRenderStateGet(rwRENDERSTATEZWRITEENABLE, &nZWrite); + RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &nAlphaBlending); + RwRenderStateGet(rwRENDERSTATEALPHATESTFUNCTION, &nAlphaFunction); + + // 1st pass + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, FALSE); + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, reinterpret_cast(255)); + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTION, reinterpret_cast(rwALPHATESTFUNCTIONEQUAL)); + + auto* pAtomic = AtomicDefaultRenderCallBack(atomic); + + // 2nd pass + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast(TRUE)); + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, reinterpret_cast(0)); + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTION, reinterpret_cast(rwALPHATESTFUNCTIONLESS)); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE); + + AtomicDefaultRenderCallBack(atomic); + + /*RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, 0); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE); + auto* pAtomic = AtomicDefaultRenderCallBack(atomic);*/ + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, reinterpret_cast(nPushedAlpha)); + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTION, reinterpret_cast(nAlphaFunction)); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, reinterpret_cast(nZWrite)); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast(nAlphaBlending)); + + return pAtomic; +} + +void RenderWeapon(CEntity* pEntity) +{ + int nPushedAlpha, nAlphaFunction; + + RwRenderStateGet(rwRENDERSTATEALPHATESTFUNCTIONREF, &nPushedAlpha); + RwRenderStateGet(rwRENDERSTATEALPHATESTFUNCTION, &nAlphaFunction); + + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, reinterpret_cast(255)); + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTION, reinterpret_cast(rwALPHATESTFUNCTIONEQUAL)); + + ((void(*)(CEntity*))0x732F95)(pEntity); + + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, reinterpret_cast(nPushedAlpha)); + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTION, reinterpret_cast(nAlphaFunction)); + + ms_weaponPedsForPC.Insert(pEntity); +} + +void RenderWeaponsList() +{ + int nPushedAlpha, nAlphaFunction; + int nZWrite; + int nAlphaBlending; + + RwRenderStateGet(rwRENDERSTATEALPHATESTFUNCTIONREF, &nPushedAlpha); + RwRenderStateGet(rwRENDERSTATEZWRITEENABLE, &nZWrite); + RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &nAlphaBlending); + RwRenderStateGet(rwRENDERSTATEALPHATESTFUNCTION, &nAlphaFunction); + + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, reinterpret_cast(255)); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast(TRUE)); + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTION, reinterpret_cast(rwALPHATESTFUNCTIONLESS)); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE); + + for ( auto i = ms_weaponPedsForPC.m_lnListHead.m_pNext; i != &ms_weaponPedsForPC.m_lnListTail; i = i->m_pNext ) + { + i->V()->SetupLighting(); + ((void(*)(CEntity*))0x732F95)(i->V()); + i->V()->RemoveLighting(); + } + + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, reinterpret_cast(nPushedAlpha)); + RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTION, reinterpret_cast(nAlphaFunction)); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, reinterpret_cast(nZWrite)); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, reinterpret_cast(nAlphaBlending)); +} + +#endif + +template +void AlteredPrintString(float fX, float fY, const wchar_t* pText) +{ + float fMarginX = **reinterpret_cast(pFltX); + float fMarginY = **reinterpret_cast(pFltY); + PrintString(fX - fMarginX + (fMarginX * *ResolutionWidthMult * RsGlobal->MaximumWidth), fY - fMarginY + (fMarginY * *ResolutionHeightMult * RsGlobal->MaximumHeight), pText); +} + +template +void AlteredPrintStringMinus(float fX, float fY, const wchar_t* pText) +{ + float fMarginX = **reinterpret_cast(pFltX); + float fMarginY = **reinterpret_cast(pFltY); + PrintString(fX + fMarginX - (fMarginX * *ResolutionWidthMult * RsGlobal->MaximumWidth), fY + fMarginY - (fMarginY * *ResolutionHeightMult * RsGlobal->MaximumHeight), pText); +} + +template +void AlteredPrintStringXOnly(float fX, float fY, const wchar_t* pText) +{ + float fMarginX = **reinterpret_cast(pFltX); + PrintString(fX - fMarginX + (fMarginX * *ResolutionWidthMult * RsGlobal->MaximumWidth), fY, pText); +} + +template +void AlteredPrintStringYOnly(float fX, float fY, const wchar_t* pText) +{ + float fMarginY = **reinterpret_cast(pFltY); + PrintString(fX, fY - fMarginY + (fMarginY * *ResolutionHeightMult * RsGlobal->MaximumHeight), pText); +} + +float FixedRefValue() +{ + return 1.0f; +} + +void __declspec(naked) SubtitlesShadowFix() +{ + _asm + { +#if defined SILENTPATCH_III_VER + push eax + call Recalculate + fadd [esp+50h+8] + fadd [fShadowYSize] +#elif defined SILENTPATCH_VC_VER + mov [esp], eax + fild [esp] + push eax + lea eax, [esp+20h-18h] + push eax + lea eax, [esp+24h-14h] + push eax + call Recalculate +#endif + jmp SubtitlesShadowFix_JumpBack + } +} + +#if defined SILENTPATCH_III_VER + +__forceinline void Patch_III_10() +{ + using namespace MemoryVP; + + DrawRect = (void(*)(const CRect&,const CRGBA&))0x51F970; + SetScale = (void(*)(float,float))0x501B80; + AudioResetTimers = (void(__stdcall*)(unsigned int))0x57CCD0; + PrintString = (void(*)(float,float,const wchar_t*))0x500F50; + + InstantHitsFiredByPlayer = *(int**)0x482C8F; + pGangModelOverrides = *(signed char**)0x4C405E; + bWantsToDrawHud = *(bool**)0x4A5877; + bCamCheck = *(bool**)0x4A588C; + RsGlobal = *(RsGlobalType**)0x584C42; + ResolutionWidthMult = *(float**)0x57E956; + ResolutionHeightMult = *(float**)0x57E940; + HeadlightsFix_JumpBack = (void*)0x5382F2; + SubtitlesShadowFix_JumpBack = (void*)0x500D32; + + CTimer::ms_fTimeScale = *(float**)0x43F73F; + CTimer::ms_fTimeStep = *(float**)0x41428E; + CTimer::ms_fTimeStepNotClipped = *(float**)0x404F9B; + CTimer::m_UserPause = *(bool**)0x4076E9; + CTimer::m_CodePause = *(bool**)0x4076F2; + CTimer::m_snTimeInMilliseconds = *(int**)0x40B3B8; + CTimer::m_snPreviousTimeInMilliseconds = *(int**)0x41543D; + CTimer::m_snTimeInMillisecondsNonClipped = *(int**)0x4ACEA2; + CTimer::m_snTimeInMillisecondsPauseMode = *(int**)0x47A780; + CTimer::m_FrameCounter = *(unsigned int**)0x4AD2F3; + + Patch(0x490F83, 1); + + Patch(0x43177D, 16); + Patch(0x431DBB, 16); + Patch(0x432083, 16); + Patch(0x432303, 16); + Patch(0x479C9A, 16); + Patch(0x4FAD35, 16); + + Patch(0x544AA4, 127); + + Patch(0x5382BF, 0x0EEB); + InjectHook(0x5382EC, HeadlightsFix, PATCH_JUMP); + + InjectHook(0x4C4004, PurpleNinesGlitchFix, PATCH_JUMP); + + InjectHook(0x4ACE60, CTimer::Initialise, PATCH_JUMP); + InjectHook(0x4AD310, CTimer::Suspend, PATCH_JUMP); + InjectHook(0x4AD370, CTimer::Resume, PATCH_JUMP); + InjectHook(0x4AD410, CTimer::GetCyclesPerFrame, PATCH_JUMP); + InjectHook(0x4AD3F0, CTimer::GetCyclesPerMillisecond, PATCH_JUMP); + InjectHook(0x4ACF70, CTimer::Update, PATCH_JUMP); + InjectHook(0x590D9F, CTimer::RecoverFromSave); + + InjectHook(0x4A5870, ShowRadarTrace, PATCH_JUMP); + InjectHook(0x4209A7, SetScaleProperly); + InjectHook(0x420A1F, SetScaleProperly); + InjectHook(0x420AC1, SetScaleProperly); + InjectHook(0x420D9E, SetScaleProperly); + InjectHook(0x426342, SetScaleProperly); + InjectHook(0x4326B8, SetScaleProperly); + + InjectHook(0x4F9E4D, FixedRefValue); + + InjectHook(0x500D27, SubtitlesShadowFix, PATCH_JUMP); + Patch(0x500D4C, 0x05D8); + Patch(0x500D5F, 0x05D9); + Patch(0x500D6E, 0x05D9); + Patch(0x500D4E, &fShadowXSize); + Patch(0x500D70, &fShadowXSize); + Patch(0x500D61, &fShadowYSize); + Patch(0x500D53, 0x0000441F); + Patch(0x500D52, 0x0F); + Patch(0x500D65, 0x90); + Patch(0x500D6D, 0x50); + Patch(0x500D74, 0x9066); + + Patch(0x5623B5, 0x90); + InjectHook(0x5623B6, M16StatsFix, PATCH_CALL); + + InjectHook(0x505F82, AlteredPrintString<0x505F7B,0x505F50>); + InjectHook(0x5065DA, AlteredPrintString<0x5065D3,0x5065A8>); + InjectHook(0x50669B, AlteredPrintString<0x50668E,0x506670>); + InjectHook(0x50694B, AlteredPrintString<0x506944,0x506919>); + InjectHook(0x506A0C, AlteredPrintString<0x5069FF,0x5069E1>); + InjectHook(0x506C37, AlteredPrintString<0x506C2B,0x506C22>); + InjectHook(0x5070FA, AlteredPrintString<0x5070F3,0x5070C8>); + InjectHook(0x507598, AlteredPrintString<0x507591,0x507566>); + InjectHook(0x507754, AlteredPrintString<0x50774D,0x507722>); + InjectHook(0x507944, AlteredPrintString<0x50793D,0x507912>); + InjectHook(0x507AC8, AlteredPrintStringYOnly<0x507A8B>); + InjectHook(0x507CF0, AlteredPrintString<0x507CE9,0x507CBE>); + InjectHook(0x507FF1, AlteredPrintStringYOnly<0x507FB4>); + InjectHook(0x508C6E, AlteredPrintString<0x508C67,0x508C46>); + InjectHook(0x508F09, AlteredPrintStringXOnly<0x508F02>); + InjectHook(0x426446, AlteredPrintString<0x42643F,0x426418>); + InjectHook(0x426584, AlteredPrintString<0x42657D,0x426556>); + InjectHook(0x42665F, AlteredPrintStringMinus<0x426658,0x426637>); + InjectHook(0x5098D6, AlteredPrintString<0x509A5E,0x509A3D>); + InjectHook(0x509A65, AlteredPrintStringMinus<0x509A5E,0x509A3D>); + InjectHook(0x50A142, AlteredPrintStringXOnly<0x50A139>); + InjectHook(0x57E9F5, AlteredPrintString<0x57E9EE,0x57E9CD>); +} + +__forceinline void Patch_III_11() +{ + using namespace MemoryVP; + + DrawRect = (void(*)(const CRect&,const CRGBA&))0x51FBA0; + SetScale = (void(*)(float,float))0x501C60; + AudioResetTimers = (void(__stdcall*)(unsigned int))0x57CCC0; + PrintString = (void(*)(float,float,const wchar_t*))0x501030; + + InstantHitsFiredByPlayer = *(int**)0x482D5F; + pGangModelOverrides = *(signed char**)0x4C40FE; + bWantsToDrawHud = *(bool**)0x4A5967; + bCamCheck = *(bool**)0x4A597C; + RsGlobal = *(RsGlobalType**)0x584F82; + ResolutionWidthMult = *(float**)0x57ECA6; + ResolutionHeightMult = *(float**)0x57EC90; + HeadlightsFix_JumpBack = (void*)0x538532; + SubtitlesShadowFix_JumpBack = (void*)0x500E12; + + CTimer::ms_fTimeScale = *(float**)0x43F73F; + CTimer::ms_fTimeStep = *(float**)0x41428E; + CTimer::ms_fTimeStepNotClipped = *(float**)0x404F9B; + CTimer::m_UserPause = *(bool**)0x4076E9; + CTimer::m_CodePause = *(bool**)0x4076F2; + CTimer::m_snTimeInMilliseconds = *(int**)0x40B3B8; + CTimer::m_snPreviousTimeInMilliseconds = *(int**)0x41543D; + CTimer::m_snTimeInMillisecondsNonClipped = *(int**)0x4ACF92; + CTimer::m_snTimeInMillisecondsPauseMode = *(int**)0x47A770; + CTimer::m_FrameCounter = *(unsigned int**)0x4AD3E3; + + Patch(0x491043, 1); + + Patch(0x43177D, 16); + Patch(0x431DBB, 16); + Patch(0x432083, 16); + Patch(0x432303, 16); + Patch(0x479C9A, 16); + Patch(0x4FAE15, 16); + + Patch(0x544CE4, 127); + + Patch(0x5384FF, 0x0EEB); + InjectHook(0x53852C, HeadlightsFix, PATCH_JUMP); + + InjectHook(0x4C40A4, PurpleNinesGlitchFix, PATCH_JUMP); + + InjectHook(0x4ACF50, CTimer::Initialise, PATCH_JUMP); + InjectHook(0x4AD400, CTimer::Suspend, PATCH_JUMP); + InjectHook(0x4AD460, CTimer::Resume, PATCH_JUMP); + InjectHook(0x4AD500, CTimer::GetCyclesPerFrame, PATCH_JUMP); + InjectHook(0x4AD4E0, CTimer::GetCyclesPerMillisecond, PATCH_JUMP); + InjectHook(0x4AD060, CTimer::Update, PATCH_JUMP); + InjectHook(0x59105F, CTimer::RecoverFromSave); + + InjectHook(0x4A5960, ShowRadarTrace, PATCH_JUMP); + InjectHook(0x4209A7, SetScaleProperly); + InjectHook(0x420A1F, SetScaleProperly); + InjectHook(0x420AC1, SetScaleProperly); + InjectHook(0x420D9E, SetScaleProperly); + InjectHook(0x426342, SetScaleProperly); + InjectHook(0x4326B8, SetScaleProperly); + + InjectHook(0x4F9F2D, FixedRefValue); + + InjectHook(0x500E07, SubtitlesShadowFix, PATCH_JUMP); + Patch(0x500E2C, 0x05D8); + Patch(0x500E3F, 0x05D9); + Patch(0x500E4E, 0x05D9); + Patch(0x500E2E, &fShadowXSize); + Patch(0x500E50, &fShadowXSize); + Patch(0x500E41, &fShadowYSize); + Patch(0x500E33, 0x0000441F); + Patch(0x500E32, 0x0F); + Patch(0x500E45, 0x90); + Patch(0x500E4D, 0x50); + Patch(0x500E54, 0x9066); + + Patch(0x5624E5, 0x90); + InjectHook(0x5624E6, M16StatsFix, PATCH_CALL); + + InjectHook(0x506062, AlteredPrintString<0x50605B,0x506030>); + InjectHook(0x5066BA, AlteredPrintString<0x5066B3,0x506688>); + InjectHook(0x50677B, AlteredPrintString<0x50676E,0x506750>); + InjectHook(0x506A2B, AlteredPrintString<0x506A24,0x5069F9>); + InjectHook(0x506AEC, AlteredPrintString<0x506ADF,0x506AC1>); + InjectHook(0x506D17, AlteredPrintString<0x506D0B,0x506D02>); + InjectHook(0x5071DA, AlteredPrintString<0x5071D3,0x5071A8>); + InjectHook(0x507678, AlteredPrintString<0x507671,0x507646>); + InjectHook(0x507834, AlteredPrintString<0x50782D,0x507802>); + InjectHook(0x507A24, AlteredPrintString<0x507A1D,0x5079F2>); + InjectHook(0x507BA8, AlteredPrintStringYOnly<0x507B6B>); + InjectHook(0x507DD0, AlteredPrintString<0x507DC9,0x507D9E>); + InjectHook(0x5080D1, AlteredPrintStringYOnly<0x508094>); + InjectHook(0x508D4E, AlteredPrintString<0x508D47,0x508D26>); + InjectHook(0x508FE9, AlteredPrintStringXOnly<0x508FE2>); + InjectHook(0x426446, AlteredPrintString<0x42643F,0x426418>); + InjectHook(0x426584, AlteredPrintString<0x42657D,0x426556>); + InjectHook(0x42665F, AlteredPrintStringMinus<0x426658,0x426637>); + InjectHook(0x5099B6, AlteredPrintString<0x509B3E,0x509B1D>); + InjectHook(0x509B45, AlteredPrintStringMinus<0x509B3E,0x509B1D>); + InjectHook(0x50A222, AlteredPrintStringXOnly<0x50A219>); + InjectHook(0x57ED45, AlteredPrintString<0x57ED3E,0x57ED1D>); +} + +__forceinline void Patch_III_Steam() +{ + using namespace MemoryVP; + + DrawRect = (void(*)(const CRect&,const CRGBA&))0x51FB30; + SetScale = (void(*)(float,float))0x501BF0; + AudioResetTimers = (void(__stdcall*)(unsigned int))0x57CF20; + PrintString = (void(*)(float,float,const wchar_t*))0x500FC0; + + InstantHitsFiredByPlayer = *(int**)0x482D5F; + pGangModelOverrides = *(signed char**)0x4C408E; + bWantsToDrawHud = *(bool**)0x4A58F7; + bCamCheck = *(bool**)0x4A590C; + RsGlobal = *(RsGlobalType**)0x584E72; + ResolutionWidthMult = *(float**)0x57EBA6; + ResolutionHeightMult = *(float**)0x57EB90; + SubtitlesShadowFix_JumpBack = (void*)0x500DA2; + + CTimer::ms_fTimeScale = *(float**)0x43F73F; + CTimer::ms_fTimeStep = *(float**)0x41428E; + CTimer::ms_fTimeStepNotClipped = *(float**)0x404F9B; + CTimer::m_UserPause = *(bool**)0x4076E9; + CTimer::m_CodePause = *(bool**)0x4076F2; + CTimer::m_snTimeInMilliseconds = *(int**)0x40B3B8; + CTimer::m_snPreviousTimeInMilliseconds = *(int**)0x41543D; + CTimer::m_snTimeInMillisecondsNonClipped = *(int**)0x4ACF22; + CTimer::m_snTimeInMillisecondsPauseMode = *(int**)0x47A770; + CTimer::m_FrameCounter = *(unsigned int**)0x4AD373; + + Patch(0x490FD3, 1); + + Patch(0x43177D, 16); + Patch(0x431DBB, 16); + Patch(0x432083, 16); + Patch(0x432303, 16); + Patch(0x479C9A, 16); + Patch(0x4FADA5, 16); + + Patch(0x544C94, 127); + + InjectHook(0x4C4034, PurpleNinesGlitchFix, PATCH_JUMP); + + InjectHook(0x4ACEE0, CTimer::Initialise, PATCH_JUMP); + InjectHook(0x4AD390, CTimer::Suspend, PATCH_JUMP); + InjectHook(0x4AD3F0, CTimer::Resume, PATCH_JUMP); + InjectHook(0x4AD490, CTimer::GetCyclesPerFrame, PATCH_JUMP); + InjectHook(0x4AD470, CTimer::GetCyclesPerMillisecond, PATCH_JUMP); + InjectHook(0x4ACFF0, CTimer::Update, PATCH_JUMP); + InjectHook(0x590F4F, CTimer::RecoverFromSave); + + InjectHook(0x4A58F0, ShowRadarTrace, PATCH_JUMP); + InjectHook(0x4209A7, SetScaleProperly); + InjectHook(0x420A1F, SetScaleProperly); + InjectHook(0x420AC1, SetScaleProperly); + InjectHook(0x420D9E, SetScaleProperly); + InjectHook(0x426342, SetScaleProperly); + InjectHook(0x4326B8, SetScaleProperly); + + InjectHook(0x4F9EBD, FixedRefValue); + + InjectHook(0x500D97, SubtitlesShadowFix, PATCH_JUMP); + Patch(0x500DBC, 0x05D8); + Patch(0x500DCF, 0x05D9); + Patch(0x500DDE, 0x05D9); + Patch(0x500DBE, &fShadowXSize); + Patch(0x500DE0, &fShadowXSize); + Patch(0x500DD1, &fShadowYSize); + Patch(0x500DC3, 0x0000441F); + Patch(0x500DC2, 0x0F); + Patch(0x500DD5, 0x90); + Patch(0x500DDD, 0x50); + Patch(0x500DE4, 0x9066); + + Patch(0x562495, 0x90); + InjectHook(0x562496, M16StatsFix, PATCH_CALL); + + InjectHook(0x505FF2, AlteredPrintString<0x505FEB,0x505FC0>); + InjectHook(0x50664A, AlteredPrintString<0x506643,0x506618>); + InjectHook(0x50670B, AlteredPrintString<0x5066FE,0x5066E0>); + InjectHook(0x5069BB, AlteredPrintString<0x5069B4,0x506989>); + InjectHook(0x506A7C, AlteredPrintString<0x506A6F,0x506A51>); + InjectHook(0x506CA7, AlteredPrintString<0x506C9B,0x506C92>); + InjectHook(0x50716A, AlteredPrintString<0x507163,0x507138>); + InjectHook(0x507608, AlteredPrintString<0x507601,0x5075D6>); + InjectHook(0x5077C4, AlteredPrintString<0x5077BD,0x507792>); + InjectHook(0x5079B4, AlteredPrintString<0x5079AD,0x507982>); + InjectHook(0x507B38, AlteredPrintStringYOnly<0x507AFB>); + InjectHook(0x507D60, AlteredPrintString<0x507D59,0x507D2E>); + InjectHook(0x508061, AlteredPrintStringYOnly<0x508024>); + InjectHook(0x508CDE, AlteredPrintString<0x508CD7,0x508CB6>); + InjectHook(0x508F7B, AlteredPrintStringXOnly<0x508F72>); + InjectHook(0x426446, AlteredPrintString<0x42643F,0x426418>); + InjectHook(0x426584, AlteredPrintString<0x42657D,0x426556>); + InjectHook(0x42665F, AlteredPrintStringMinus<0x426658,0x426637>); + InjectHook(0x509946, AlteredPrintString<0x509ACE,0x509AAD>); + InjectHook(0x509AD5, AlteredPrintStringMinus<0x509ACE,0x509AAD>); + InjectHook(0x50A1B2, AlteredPrintStringXOnly<0x50A1A9>); + InjectHook(0x57EC45, AlteredPrintString<0x57EC3E,0x57EC1D>); +} + +#elif defined SILENTPATCH_VC_VER + +__forceinline void Patch_VC_10() +{ + using namespace MemoryVP; + + AudioResetTimers = (void(__stdcall*)(unsigned int))0x5F98D0; + PrintString = (void(*)(float,float,const wchar_t*))0x551040; + + bSnapShotActive = *(bool**)0x4D1239; + RsGlobal = *(RsGlobalType**)0x602D32; + ResolutionWidthMult = *(float**)0x5FA15E; + ResolutionHeightMult = *(float**)0x5FA148; + RosieAudioFix_JumpBack = (void*)0x42BFFE; + SubtitlesShadowFix_JumpBack = (void*)0x551701; + + CTimer::ms_fTimeScale = *(float**)0x453D38; + CTimer::ms_fTimeStep = *(float**)0x41A318; + CTimer::ms_fTimeStepNotClipped = *(float**)0x40605B; + CTimer::m_UserPause = *(bool**)0x4D0F91; + CTimer::m_CodePause = *(bool**)0x4D0FAE; + CTimer::m_snTimeInMilliseconds = *(int**)0x418CFC; + CTimer::m_snPreviousTimeInMilliseconds = *(int**)0x41BB3A; + CTimer::m_snTimeInMillisecondsNonClipped = *(int**)0x4D1081; + CTimer::m_snTimeInMillisecondsPauseMode = *(int**)0x4D0FE2; + CTimer::m_FrameCounter = *(unsigned int**)0x4D12CF; + + Patch(0x43E983, 16); + Patch(0x43EC03, 16); + Patch(0x43EECB, 16); + Patch(0x43F52B, 16); + Patch(0x43F842, 16); + Patch(0x48EB27, 16); + Patch(0x541E7E, 16); + + InjectHook(0x4D1300, CTimer::Initialise, PATCH_JUMP); + InjectHook(0x4D0ED0, CTimer::Suspend, PATCH_JUMP); + InjectHook(0x4D0E50, CTimer::Resume, PATCH_JUMP); + InjectHook(0x4D0DF0, CTimer::GetCyclesPerFrame, PATCH_JUMP); + InjectHook(0x4D0E30, CTimer::GetCyclesPerMillisecond, PATCH_JUMP); + InjectHook(0x4D0F30, CTimer::Update, PATCH_JUMP); + InjectHook(0x61AA7D, CTimer::RecoverFromSave); + + InjectHook(0x5433BD, FixedRefValue); + + InjectHook(0x42BFF7, RosiesAudioFix, PATCH_JUMP); + + InjectHook(0x5516FC, SubtitlesShadowFix, PATCH_JUMP); + Patch(0x5517C4, 0xD9); + Patch(0x5517DF, 0xD9); + Patch(0x551832, 0xD9); + Patch(0x551848, 0xD9); + Patch(0x5517E2, 0x34-0x14); + Patch(0x55184B, 0x34-0x14); + Patch(0x5517C7, 0x28-0x18); + Patch(0x551835, 0x24-0x18); + Patch(0x5516FB, 0x90); + + InjectHook(0x5FA1FD, AlteredPrintString<0x5FA1F6,0x5FA1D5>); + InjectHook(0x54474D, AlteredPrintStringMinus<0x544727,0x544727>); +} + +__forceinline void Patch_VC_11() +{ + using namespace MemoryVP; + + AudioResetTimers = (void(__stdcall*)(unsigned int))0x5F98F0; + PrintString = (void(*)(float,float,const wchar_t*))0x551060; + + bSnapShotActive = *(bool**)0x4D1259; + RsGlobal = *(RsGlobalType**)0x602D12; + ResolutionWidthMult = *(float**)0x5FA17E; + ResolutionHeightMult = *(float**)0x5FA168; + RosieAudioFix_JumpBack = (void*)0x42BFFE; + SubtitlesShadowFix_JumpBack = (void*)0x551721; + + CTimer::ms_fTimeScale = *(float**)0x453D38; + CTimer::ms_fTimeStep = *(float**)0x41A318; + CTimer::ms_fTimeStepNotClipped = *(float**)0x40605B; + CTimer::m_UserPause = *(bool**)0x4D0FB1; + CTimer::m_CodePause = *(bool**)0x4D0FCE; + CTimer::m_snTimeInMilliseconds = *(int**)0x418CFC; + CTimer::m_snPreviousTimeInMilliseconds = *(int**)0x41BB3A; + CTimer::m_snTimeInMillisecondsNonClipped = *(int**)0x4D10A1; + CTimer::m_snTimeInMillisecondsPauseMode = *(int**)0x4D1002; + CTimer::m_FrameCounter = *(unsigned int**)0x4D12EF; + + Patch(0x43E983, 16); + Patch(0x43EC03, 16); + Patch(0x43EECB, 16); + Patch(0x43F52B, 16); + Patch(0x43F842, 16); + Patch(0x48EB37, 16); + Patch(0x541E9E, 16); + + InjectHook(0x4D1320, CTimer::Initialise, PATCH_JUMP); + InjectHook(0x4D0EF0, CTimer::Suspend, PATCH_JUMP); + InjectHook(0x4D0E70, CTimer::Resume, PATCH_JUMP); + InjectHook(0x4D0E10, CTimer::GetCyclesPerFrame, PATCH_JUMP); + InjectHook(0x4D0E50, CTimer::GetCyclesPerMillisecond, PATCH_JUMP); + InjectHook(0x4D0F50, CTimer::Update, PATCH_JUMP); + InjectHook(0x61AA5D, CTimer::RecoverFromSave); + + InjectHook(0x5433DD, FixedRefValue); + + InjectHook(0x42BFF7, RosiesAudioFix, PATCH_JUMP); + + InjectHook(0x55171C, SubtitlesShadowFix, PATCH_JUMP); + Patch(0x5517E4, 0xD9); + Patch(0x5517FF, 0xD9); + Patch(0x551852, 0xD9); + Patch(0x551868, 0xD9); + Patch(0x551802, 0x34-0x14); + Patch(0x55186B, 0x34-0x14); + Patch(0x5517E7, 0x28-0x18); + Patch(0x551855, 0x24-0x18); + Patch(0x55171B, 0x90); + + InjectHook(0x5FA21D, AlteredPrintString<0x5FA216,0x5FA1F5>); + InjectHook(0x54476D, AlteredPrintStringMinus<0x544747,0x544747>); +} + +__forceinline void Patch_VC_Steam() +{ + using namespace MemoryVP; + + AudioResetTimers = (void(__stdcall*)(unsigned int))0x5F9530; + PrintString = (void(*)(float,float,const wchar_t*))0x550F30; + + bSnapShotActive = *(bool**)0x4D10F9; + RsGlobal = *(RsGlobalType**)0x602952; + ResolutionWidthMult = *(float**)0x5F9DBE; + ResolutionHeightMult = *(float**)0x5F9DA8; + RosieAudioFix_JumpBack = (void*)0x42BFCE; + SubtitlesShadowFix_JumpBack = (void*)0x5515F1; + + CTimer::ms_fTimeScale = *(float**)0x453C18; + CTimer::ms_fTimeStep = *(float**)0x41A318; + CTimer::ms_fTimeStepNotClipped = *(float**)0x40605B; + CTimer::m_UserPause = *(bool**)0x4D0E51; + CTimer::m_CodePause = *(bool**)0x4D0E6E; + CTimer::m_snTimeInMilliseconds = *(int**)0x418CFC; + CTimer::m_snPreviousTimeInMilliseconds = *(int**)0x41BB3A; + CTimer::m_snTimeInMillisecondsNonClipped = *(int**)0x4D0F41; + CTimer::m_snTimeInMillisecondsPauseMode = *(int**)0x4D0EA2; + CTimer::m_FrameCounter = *(unsigned int**)0x4D118F; + + Patch(0x43E8F3, 16); + Patch(0x43EB73, 16); + Patch(0x43EE3B, 16); + Patch(0x43F49B, 16); + Patch(0x43F7B2, 16); + Patch(0x48EA37, 16); + Patch(0x541D6E, 16); + + InjectHook(0x4D11C0, CTimer::Initialise, PATCH_JUMP); + InjectHook(0x4D0D90, CTimer::Suspend, PATCH_JUMP); + InjectHook(0x4D0D10, CTimer::Resume, PATCH_JUMP); + InjectHook(0x4D0CB0, CTimer::GetCyclesPerFrame, PATCH_JUMP); + InjectHook(0x4D0CF0, CTimer::GetCyclesPerMillisecond, PATCH_JUMP); + InjectHook(0x4D0DF0, CTimer::Update, PATCH_JUMP); + InjectHook(0x61A6A6, CTimer::RecoverFromSave); + + InjectHook(0x5432AD, FixedRefValue); + + InjectHook(0x42BFC7, RosiesAudioFix, PATCH_JUMP); + + InjectHook(0x5515EC, SubtitlesShadowFix, PATCH_JUMP); + Patch(0x5516B4, 0xD9); + Patch(0x5516CF, 0xD9); + Patch(0x551722, 0xD9); + Patch(0x551738, 0xD9); + Patch(0x5516D2, 0x34-0x14); + Patch(0x55173B, 0x34-0x14); + Patch(0x5516B7, 0x28-0x18); + Patch(0x551725, 0x24-0x18); + Patch(0x5515EB, 0x90); + + InjectHook(0x5F9E5D, AlteredPrintString<0x5F9E56,0x5F9E35>); + InjectHook(0x54463D, AlteredPrintStringMinus<0x544617,0x544617>); +} + +#elif defined SILENTPATCH_SA_VER + +void RenderVehicleHiDetailAlphaCB_HunterDoor(RpAtomic* pAtomic) +{ + AlphaObjectInfo NewObject; + + NewObject.callback = RenderAtomic; + NewObject.fCompareValue = -std::numeric_limits::infinity(); + NewObject.pAtomic = pAtomic; + + m_alphaList.InsertSorted(NewObject); +} + +#include + +// TODO: EXEs +static unsigned char& nGameClockDays = **(unsigned char**)0x4E841D; +static float& fFarClipZ = **(float**)0x70D21F; +static RwTexture** const gpCoronaTexture = *(RwTexture***)0x6FAA8C; +static int& MoonSize = **(int**)0x713B0C; + +// TODO: Load it from an embedded PNG +static RwTexture*& gpMoonMask = *(RwTexture**)0xC6AA74; + +// By NTAuthority +void DrawMoonWithPhases(int moonColor, float* screenPos, float sizeX, float sizeY) +{ + //D3DPERF_BeginEvent(D3DCOLOR_ARGB(0,0,0,0), L"render moon"); + + float currentDayFraction = nGameClockDays / 31.0f; + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nullptr); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + + float a10 = 1.0 / fFarClipZ; + float size = (MoonSize * 2) + 4.0f; + + RwD3D9SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA); + + RenderOneXLUSprite(screenPos[0], screenPos[1], fFarClipZ, sizeX * size, sizeY * size, 0, 0, 0, 0, a10, -1, 0, 0); + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpMoonMask)); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDINVSRCCOLOR); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCCOLOR); + + float maskX = (sizeX * size) * 5.40 * (currentDayFraction - 0.5) + screenPos[0]; + float maskY = screenPos[1] + ((sizeY * size) * 0.7); + + RenderOneXLUSprite(maskX, maskY, fFarClipZ, sizeX * size * 1.7, sizeY * size * 1.7, 0, 0, 0, 255, a10, -1, 0, 0); + + RwD3D9SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[2])); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDDESTALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, 0); + + RenderOneXLUSprite(screenPos[0], screenPos[1], fFarClipZ, sizeX * size, sizeY * size, moonColor, moonColor, moonColor * 0.85f, 255, a10, -1, 0, 0); + + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + + //D3DPERF_EndEvent(); +} + +void __declspec(naked) HandleMoonStuffStub() +{ + __asm + { + mov eax, [esp + 78h - 64h] // screen x size + mov ecx, [esp + 78h - 68h] // screen y size + + push ecx + push eax + + lea ecx, [esp + 80h - 54h] // screen coord vector + + push ecx + + push esi + + call DrawMoonWithPhases + + add esp, 10h + + push 713D24h // TODO: EXEs + retn + } +} + +void __declspec(naked) HandleMoonStuffStub_Steam() +{ + __asm + { + mov eax, [esp + 70h - 58h] // screen x size + mov ecx, [esp + 70h - 5Ch] // screen y size + + push ecx + push eax + + lea ecx, [esp + 78h - 48h] // screen coord vector + + push ecx + + push esi + + call DrawMoonWithPhases + + add esp, 10h + + push 72F17Fh + retn + } +} + +static unsigned int nCachedCRC; + +void __declspec(naked) HunterTest() +{ + static const char aDoorDummy[] = "door_lf_ok"; + _asm + { + cmp nCachedCRC, 0x45D0B41C + jnz HunterTest_RegularAlpha + push 10 + push offset aDoorDummy + push ebp + call strncmp + add esp, 0Ch + test eax, eax + jnz HunterTest_RegularAlpha + push RenderVehicleHiDetailAlphaCB_HunterDoor + mov eax, 4C7914h + jmp eax + +HunterTest_RegularAlpha: + push 733F80h + mov eax, 4C7914h + jmp eax + } +} + +void __declspec(naked) CacheCRC32() +{ + _asm + { + mov eax, [ecx+4] + mov nCachedCRC, eax + mov eax, 4C7B10h + jmp eax + } +} + +// 1.0 only +static bool bDarkVehicleThing; +static RpLight*& pDirect = **(RpLight***)0x5BA573; + +void __declspec(naked) DarkVehiclesFix1() +{ + _asm + { + shr eax, 0Eh + test al, 1 + jz DarkVehiclesFix1_DontAppply + mov ecx, [pDirect] + mov ecx, [ecx] + mov al, [ecx+2] + test al, 1 + jnz DarkVehiclesFix1_DontAppply + mov bDarkVehicleThing, 1 + jmp DarkVehiclesFix1_Return + +DarkVehiclesFix1_DontAppply: + mov bDarkVehicleThing, 0 + +DarkVehiclesFix1_Return: + mov eax, 756D90h + jmp eax + } +} + +void __declspec(naked) DarkVehiclesFix2() +{ + _asm + { + jz DarkVehiclesFix2_MakeItDark + mov al, bDarkVehicleThing + test al, al + jnz DarkVehiclesFix2_MakeItDark + mov eax, 5D9A7Ah + jmp eax + +DarkVehiclesFix2_MakeItDark: + mov eax, 5D9B09h + jmp eax + } +} + +void __declspec(naked) DarkVehiclesFix3() +{ + _asm + { + jz DarkVehiclesFix3_MakeItDark + mov al, bDarkVehicleThing + test al, al + jnz DarkVehiclesFix3_MakeItDark + mov eax, 5D9B4Ah + jmp eax + +DarkVehiclesFix3_MakeItDark: + mov eax, 5D9CACh + jmp eax + } +} + +void __declspec(naked) DarkVehiclesFix4() +{ + _asm + { + jz DarkVehiclesFix4_MakeItDark + mov al, bDarkVehicleThing + test al, al + jnz DarkVehiclesFix4_MakeItDark + mov eax, 5D9CB8h + jmp eax + +DarkVehiclesFix4_MakeItDark: + mov eax, 5D9E0Dh + jmp eax + } +} + +void SetRendererForAtomic(RpAtomic* pAtomic) +{ + BOOL bHasAlpha = FALSE; + + RpGeometryForAllMaterials(RpAtomicGetGeometry(pAtomic), AlphaTest, &bHasAlpha); + if ( bHasAlpha ) + RpAtomicSetRenderCallBack(pAtomic, TwoPassAlphaRender); +} + +__forceinline void Patch_SA_10() +{ + using namespace MemoryVP; + + // Temp + CTimer::m_snTimeInMilliseconds = *(int**)0x4242D1; + + // Heli rotors + InjectMethodVP(0x6CAB70, CPlane::Render, PATCH_JUMP); + InjectMethodVP(0x6C4400, CHeli::Render, PATCH_JUMP); + //InjectHook(0x553318, RenderAlphaAtomics); + Patch(0x7341D9, TwoPassAlphaRender); + Patch(0x734127, TwoPassAlphaRender); + //Patch(0x73406E, TwoPassAlphaRender); + + // DOUBLE_RWHEELS + Patch(0x4C9290, 0xE281); + Patch(0x4C9292, ~(rwMATRIXTYPEMASK|rwMATRIXINTERNALIDENTITY)); + + // No framedelay + Patch(0x53E923, 0x42EB56); + + // Coloured zone names + Patch(0x58ADBE, 0x0E75); + Patch(0x58ADC5, 0x0775); + + // Disable re-initialization of DirectInput mouse device by the game + Patch(0x576CCC, 0xEB); + Patch(0x576EBA, 0xEB); + Patch(0x576F8A, 0xEB); + + // Make sure DirectInput mouse device is set non-exclusive (may not be needed?) + Patch(0x7469A0, 0x909000B0); + + // Weapons rendering + InjectHook(0x5E7859, RenderWeapon); + InjectHook(0x732F30, RenderWeaponsList, PATCH_JUMP); + //Patch(0x53EAC4, 0x0DEB); + //Patch(0x705322, 0x0DEB); + //Patch(0x7271E3, 0x0DEB); + //Patch(0x73314E, 0xC3); + Patch(0x732F95, 0x560CEC83); + Patch(0x732FA2, 0x20245C8B); + Patch(0x733128, 0x20EB); + Patch(0x733135, 0x13EB); + Nop(0x732FBC, 5); + //Nop(0x732F93, 6); + //Nop(0x733144, 6); + Nop(0x732FA6, 6); + //Nop(0x5E46DA, 2); + + // Hunter interior + InjectHook(0x4C7908, HunterTest, PATCH_JUMP); + InjectHook(0x4C9618, CacheCRC32); + + // Fixed blown up car rendering + // ONLY 1.0 + InjectHook(0x5D993F, DarkVehiclesFix1); + InjectHook(0x5D9A74, DarkVehiclesFix2, PATCH_JUMP); + InjectHook(0x5D9B44, DarkVehiclesFix3, PATCH_JUMP); + InjectHook(0x5D9CB2, DarkVehiclesFix4, PATCH_JUMP); + + // Cars getting dirty + // Only 1.0 and Steam + InjectMethod(0x4C9648, CVehicleModelInfo::FindEditableMaterialList, PATCH_CALL); + Patch(0x4C964D, 0x0FEBCE8B); + Patch(0x5D5DC2, 32); // 1.0 ONLY + + // Bindable NUM5 + // Only 1.0 and Steam + Nop(0x57DC55, 2); + + // Moonphases + InjectHook(0x713ACB, HandleMoonStuffStub, PATCH_JUMP); + + // TEMP + //Patch(0x733B05, 40); + //Patch(0x733B55, 40); + //Patch(0x5B3ADD, 4); + + // Twopass rendering (experimental) + /*Patch(0x4C441E, 0x47C7); + Patch(0x4C4420, 0x48); + Patch(0x4C4421, TwoPassAlphaRender); + Patch(0x4C4425, 0x04C25E5F); + Patch(0x4C4429, 0x00);*/ + Patch(0x4C441E, 0x57); + InjectHook(0x4C441F, SetRendererForAtomic, PATCH_CALL); + Patch(0x4C4424, 0x5F04C483); + Patch(0x4C4428, 0x0004C25E); +} + +#endif + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + UNREFERENCED_PARAMETER(hinstDLL); + UNREFERENCED_PARAMETER(lpvReserved); + + if ( fdwReason == DLL_PROCESS_ATTACH ) + { +#if defined SILENTPATCH_III_VER + if (*(DWORD*)0x5C1E70 == 0x53E58955) Patch_III_10(); + else if (*(DWORD*)0x5C2130 == 0x53E58955) Patch_III_11(); + else if (*(DWORD*)0x5C6FD0 == 0x53E58955) Patch_III_Steam(); +#elif defined SILENTPATCH_VC_VER + if(*(DWORD*)0x667BF0 == 0x53E58955) Patch_VC_10(); + else if(*(DWORD*)0x667C40 == 0x53E58955) Patch_VC_11(); + else if (*(DWORD*)0x666BA0 == 0x53E58955) Patch_VC_Steam(); +#elif defined SILENTPATCH_SA_VER + Patch_SA_10(); +#endif + } + return TRUE; +} \ No newline at end of file diff --git a/SilentPatch/win2000.asm b/SilentPatch/win2000.asm new file mode 100644 index 0000000..7645e55 --- /dev/null +++ b/SilentPatch/win2000.asm @@ -0,0 +1,12 @@ +.model flat +.data +__imp__EncodePointer@4 dd dummy +__imp__DecodePointer@4 dd dummy +EXTERNDEF __imp__EncodePointer@4 : DWORD +EXTERNDEF __imp__DecodePointer@4 : DWORD +.code +dummy proc +mov eax, [esp+4] +ret 4 +dummy endp +end \ No newline at end of file diff --git a/VCFix/VCFix.vcxproj b/VCFix/VCFix.vcxproj new file mode 100644 index 0000000..09b5505 --- /dev/null +++ b/VCFix/VCFix.vcxproj @@ -0,0 +1,108 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {374D4CB4-548A-4DA0-AB68-8EA356424626} + VCFix + + + + DynamicLibrary + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + + .asi + + + .asi + + + + Level4 + Disabled + SILENTPATCH_VC_VER;%(PreprocessorDefinitions) + MultiThreadedDebug + D:\RWSDK\Graphics\rwsdk\include\d3d9 + + + true + Windows + 5.0 + Winmm.lib;%(AdditionalDependencies) + + + copy /y "$(TargetPath)" "D:\gry\Steam\steamapps\common\Grand Theft Auto Vice City\SilentPatchVC.asi" + + + + + Level4 + MaxSpeed + true + true + SILENTPATCH_VC_VER;%(PreprocessorDefinitions) + true + MultiThreaded + false + AnySuitable + Speed + true + D:\RWSDK\Graphics\rwsdk\include\d3d9 + + + true + true + true + Windows + 5.0 + Winmm.lib;%(AdditionalDependencies) + + + copy /y "$(TargetPath)" "D:\gry\Steam\steamapps\common\Grand Theft Auto Vice City\SilentPatchVC.asi" + + + + + + + + + + + + + Document + + + + + + + \ No newline at end of file diff --git a/VCFix/VCFix.vcxproj.filters b/VCFix/VCFix.vcxproj.filters new file mode 100644 index 0000000..689f5aa --- /dev/null +++ b/VCFix/VCFix.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + + + Source Files + + + \ No newline at end of file