Skip to content

Commit

Permalink
Merge pull request #1 from jensewe/updaterate_patch
Browse files Browse the repository at this point in the history
Patch `SetUpdateRate` to allow tickrate > 100
  • Loading branch information
accelerator74 authored Sep 12, 2024
2 parents 3de09b9 + c989e4f commit ee4e00d
Show file tree
Hide file tree
Showing 6 changed files with 253 additions and 2 deletions.
1 change: 1 addition & 0 deletions AMBuilder
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ sourceFiles = [
'memutils.cpp',
'maxrate_patches.cpp',
'boomervomitpatch.cpp',
'updaterate_patches.cpp',

os.path.join(Extension.mms_root, 'core', 'sourcehook', 'sourcehook.cpp'),
os.path.join(Extension.mms_root, 'core', 'sourcehook', 'sourcehook_impl_chookidman.cpp'),
Expand Down
3 changes: 3 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ and removes the (30k) limits on rate control cvars:

### Changelog / TODO

1.6:
- Patch SetUpdateRate to allow tickrate > 100 (Thanks to jensewe)

1.5: Contributed by Accelerator
- Fixed CVomit::UpdateAbility offsets.
- Some code optimization
Expand Down
49 changes: 49 additions & 0 deletions sigs.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,53 @@ const int g_FrameTimeReadOffsets[] =
#endif
#endif

#if defined (_WIN32)
#if defined (_L4D)
//53 8B 5C 24 0C 84 DB 75 ? A1
#define SIG_CGAMECLIENT_SETUPDATERATE "\x53\x8B\x5C\x24\x0C\x84\xDB\x75\x2A\xA1"
#define SIG_CGAMECLIENT_SETUPDATERATE_LEN 10
#define CGAMECLIENT_SETUPDATERATE_PATCH_CHECK_BYTE 0x7E
#define CGAMECLIENT_SETUPDATERATE_PATCH_OFFSET 0x3F
//8B 44 24 04 83 F8 ? 7E ? B8 ? ? ? ? EB
#define SIG_CBASECLIENT_SETUPDATERATE "\x8B\x44\x24\x04\x83\xF8\x2A\x7E\x2A\xB8\x2A\x2A\x2A\x2A\xEB"
#define SIG_CBASECLIENT_SETUPDATERATE_LEN 15
#define CBASECLIENT_SETUPDATERATE_PATCH_CHECK_BYTE 0x7E
#define CBASECLIENT_SETUPDATERATE_PATCH_OFFSET 0x7
#elif defined (_L4D2)
//55 8B EC 53 8B 5D 0C 84 DB 75 ? A1
#define SIG_CGAMECLIENT_SETUPDATERATE "\x55\x8B\xEC\x53\x8B\x5D\x0C\x84\xDB\x75\x2A\xA1"
#define SIG_CGAMECLIENT_SETUPDATERATE_LEN 12
#define CGAMECLIENT_SETUPDATERATE_PATCH_CHECK_BYTE 0x7E
#define CGAMECLIENT_SETUPDATERATE_PATCH_OFFSET 0x3F
//55 8B EC 8B 45 08 83 F8 ? 7E ? B8 ? ? ? ? EB
#define SIG_CBASECLIENT_SETUPDATERATE "\x55\x8B\xEC\x8B\x45\x08\x83\xF8\x2A\x7E\x2A\xB8\x2A\x2A\x2A\x2A\xEB"
#define SIG_CBASECLIENT_SETUPDATERATE_LEN 17
#define CBASECLIENT_SETUPDATERATE_PATCH_CHECK_BYTE 0x7E
#define CBASECLIENT_SETUPDATERATE_PATCH_OFFSET 0x9
#endif
#elif defined (_LINUX)
#define SIG_CGAMECLIENT_SETUPDATERATE "_ZN11CGameClient13SetUpdateRateEib"
#define SIG_CBASECLIENT_SETUPDATERATE "_ZN11CBaseClient13SetUpdateRateEib"

/*
83 FA 64 cmp edx, 64h
B8 64 00 00 00 mov eax, 64h
7F 07 jg short loc_1DA32A
*/
#define CGAMECLIENT_SETUPDATERATE_PATCH_CHECK_BYTE 0x7F
/*
BA 64 00 00 00 mov edx, 64h
83 F8 64 cmp eax, 64h
0F 4E D0 cmovle edx, eax
*/
#define CBASECLIENT_SETUPDATERATE_PATCH_CHECK_BYTE 0x4E
#if defined (_L4D)
#define CGAMECLIENT_SETUPDATERATE_PATCH_OFFSET 0x4C
#define CBASECLIENT_SETUPDATERATE_PATCH_OFFSET 0x17
#elif defined (_L4D2)
#define CGAMECLIENT_SETUPDATERATE_PATCH_OFFSET 0x41
#define CBASECLIENT_SETUPDATERATE_PATCH_OFFSET 0x21
#endif
#endif

#endif // _SIGS_H_
7 changes: 5 additions & 2 deletions tickrate_enabler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

#include "boomervomitpatch.h"
#include "maxrate_patches.h"
#include "updaterate_patches.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
Expand All @@ -53,8 +54,8 @@
#else
#define VDEBUG ""
#endif
#define VERSION_L4D "1.5"
#define VERSION_L4D2 "1.5"
#define VERSION_L4D "1.6"
#define VERSION_L4D2 "1.6"
#if defined (_L4D)
#define VERSION VERSION_L4D VDEBUG
#elif defined (_L4D2)
Expand Down Expand Up @@ -118,6 +119,8 @@ bool L4DTickRate::Load( CreateInterfaceFn interfaceFactory, CreateInterfaceFn ga
#if defined (CLAMPCLIENTRATE_PATCH)
m_patchManager.Register(new ClampClientRatePatch((BYTE *)engine));
#endif
m_patchManager.Register(new CGameClientUpdateRatePatch((BYTE *)engine));
m_patchManager.Register(new CBaseClientUpdateRatePatch((BYTE *)engine));

m_patchManager.PatchAll();
}
Expand Down
132 changes: 132 additions & 0 deletions updaterate_patches.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/**
* vim: set ts=4 :
* =============================================================================
* MaxRate Patches
* Copyright (C) 2012 Michael "ProdigySim" Busby
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, the author(s) give you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, the author(s) grant
* this exception to all derivative works. The author(s) define further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/


#include "updaterate_patches.h"
#include "memutils.h"
#include "patchexceptions.h"
#include "basicbinpatch.h"
#include "sigs.h"

CGameClientUpdateRatePatch::CGameClientUpdateRatePatch(BYTE * engine) : m_patch(NULL)
{
m_patch = GeneratePatch(FindCGameClientSetUpdateRate(engine));
}

CGameClientUpdateRatePatch::~CGameClientUpdateRatePatch()
{
if(m_patch != NULL) delete m_patch;
}

void CGameClientUpdateRatePatch::Patch()
{
m_patch->Patch();
}

void CGameClientUpdateRatePatch::Unpatch()
{
m_patch->Unpatch();
}

BYTE * CGameClientUpdateRatePatch::FindCGameClientSetUpdateRate(BYTE * engine)
{
#if defined (_LINUX)
return (BYTE *)g_MemUtils.SimpleResolve(engine, SIG_CGAMECLIENT_SETUPDATERATE);
#elif defined (_WIN32)
return (BYTE*)g_MemUtils.FindLibPattern(engine, SIG_CGAMECLIENT_SETUPDATERATE, SIG_CGAMECLIENT_SETUPDATERATE_LEN);
#endif
}

ICodePatch * CGameClientUpdateRatePatch::GeneratePatch(BYTE * pCGameClientUpdateRate)
{
if(!pCGameClientUpdateRate)
{
throw PatchException("Unable to find CGameClient::SetUpdateRate!");
}
if(pCGameClientUpdateRate[CGAMECLIENT_SETUPDATERATE_PATCH_OFFSET] != CGAMECLIENT_SETUPDATERATE_PATCH_CHECK_BYTE)
{
throw PatchException("CGameClient::SetUpdateRate patch offset incorrect!");
}
#if defined _WIN32
const BYTE replacement[] = {JMP_8_OPCODE};
return new BasicStaticBinPatch<sizeof(replacement)>(pCGameClientUpdateRate+CGAMECLIENT_SETUPDATERATE_PATCH_OFFSET, replacement);
#elif defined _LINUX
return new BasicStaticBinPatch<sizeof(NOP_2)>(pCGameClientUpdateRate+CGAMECLIENT_SETUPDATERATE_PATCH_OFFSET, NOP_2);
#endif
}

CBaseClientUpdateRatePatch::CBaseClientUpdateRatePatch(BYTE * engine) : m_patch(NULL)
{
m_patch = GeneratePatch(FindCBaseClientSetUpdateRate(engine));
}

CBaseClientUpdateRatePatch::~CBaseClientUpdateRatePatch()
{
if(m_patch != NULL) delete m_patch;
}

void CBaseClientUpdateRatePatch::Patch()
{
m_patch->Patch();
}

void CBaseClientUpdateRatePatch::Unpatch()
{
m_patch->Unpatch();
}

BYTE * CBaseClientUpdateRatePatch::FindCBaseClientSetUpdateRate(BYTE * engine)
{
#if defined (_LINUX)
return (BYTE *)g_MemUtils.SimpleResolve(engine, SIG_CBASECLIENT_SETUPDATERATE);
#elif defined (_WIN32)
return (BYTE*)g_MemUtils.FindLibPattern(engine, SIG_CBASECLIENT_SETUPDATERATE, SIG_CBASECLIENT_SETUPDATERATE_LEN);
#endif
}

ICodePatch * CBaseClientUpdateRatePatch::GeneratePatch(BYTE * pCBaseClientUpdateRate)
{
if(!pCBaseClientUpdateRate)
{
throw PatchException("Unable to find CBaseClient::SetUpdateRate!");
}
if(pCBaseClientUpdateRate[CBASECLIENT_SETUPDATERATE_PATCH_OFFSET] != CBASECLIENT_SETUPDATERATE_PATCH_CHECK_BYTE)
{
throw PatchException("CBaseClient::SetUpdateRate patch offset incorrect!");
}
#if defined _WIN32
const BYTE replacement[] = {JMP_8_OPCODE};
return new BasicStaticBinPatch<sizeof(replacement)>(pCBaseClientUpdateRate+CBASECLIENT_SETUPDATERATE_PATCH_OFFSET, replacement);
#elif defined _LINUX
const BYTE replacement[] = {0x89, 0xC2, NOP_1[0]};
return new BasicStaticBinPatch<sizeof(replacement)>(pCBaseClientUpdateRate+CBASECLIENT_SETUPDATERATE_PATCH_OFFSET-1, replacement);
#endif
}
63 changes: 63 additions & 0 deletions updaterate_patches.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* vim: set ts=4 :
* =============================================================================
* MaxRate Patches
* Copyright (C) 2012 Michael "ProdigySim" Busby
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, the author(s) give you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, the author(s) grant
* this exception to all derivative works. The author(s) define further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef __UPDATERATE_PATCHES_H__
#define __UPDATERATE_PATCHES_H__

#include "codepatch/icodepatch.h"
#include "misc_asm.h"

class CGameClientUpdateRatePatch : public ICodePatch
{
public:
CGameClientUpdateRatePatch(BYTE * engine);
~CGameClientUpdateRatePatch();
void Patch();
void Unpatch();
private:
BYTE * FindCGameClientSetUpdateRate(BYTE * engine);
ICodePatch * GeneratePatch(BYTE * pCGameClientUpdateRate);
ICodePatch * m_patch;
};

class CBaseClientUpdateRatePatch : public ICodePatch
{
public:
CBaseClientUpdateRatePatch(BYTE * engine);
~CBaseClientUpdateRatePatch();
void Patch();
void Unpatch();
private:
BYTE * FindCBaseClientSetUpdateRate(BYTE * engine);
ICodePatch * GeneratePatch(BYTE * pCBaseClientUpdateRate);
ICodePatch * m_patch;
};

#endif

0 comments on commit ee4e00d

Please sign in to comment.