Skip to content

Commit

Permalink
Introduce mempatching
Browse files Browse the repository at this point in the history
- Include SourceScramble extension for sane memory patching
- Proper solution for CAI_ScriptConditions::EvaluationThink with patched AI_GetSinglePlayer call
- This will, for example, make the guard in bm_c1a1b wait before calling for help, until enemies are dead.
- Made gamedata ascii more concrete
- Added more memory and player stocks
- Update and reformat readme credits, include libraries
  • Loading branch information
Alienmario committed May 8, 2024
1 parent d59ca04 commit 9c9bf54
Show file tree
Hide file tree
Showing 11 changed files with 520 additions and 73 deletions.
1 change: 1 addition & 0 deletions .github/workflows/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ jobs:
EDT_DEST="${SM}/data/srccoop"
mkdir -p $SM
mkdir -p $EDT_DEST
cp -R extensions $SM
cp -R plugins $SM
cp -R configs $SM
cp -R gamedata $SM
Expand Down
42 changes: 22 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,28 +43,30 @@ __If you are looking to help with the development of the project__, we are alway

If you are interested in helping us, contact us on [Discord](https://discord.gg/Fh77rxQaEB) or create a pull request.

### Credits
- __ampreeT__ | programming, reverse engineering, map editing
## Credits
- __ampreeT__ :: programming, reverse engineering, map editing
- [Steam](https://steamcommunity.com/id/ampreeT) | [GitHub](https://github.com/ampreeT)
- __kasull__ | programming, reverse engineering, trailer production
- __kasull__ :: programming, reverse engineering, trailer production
- [Steam](https://steamcommunity.com/id/kasull/) | [GitHub](https://github.com/kasullian)
- __Alienmario__ | programming, reverse engineering, map editing
- __Alienmario__ :: programming, reverse engineering, map editing
- [Steam](https://steamcommunity.com/id/4oM0/) | [GitHub](https://github.com/Alienmario)
- __Rock__ | miscellaneous plugin features, map editing
- __Balimbanana__ :: programming, reverse engineering
- [Steam](https://steamcommunity.com/id/Balimbanana/) | [GitHub](https://github.com/Balimbanana)
- __Rock__ :: programming, map editing
- [Steam](https://steamcommunity.com/id/Rock48/) | [GitHub](https://github.com/Rock48)
- __Krozis Kane__ | map editing
- __Krozis Kane__ :: map editing
- [Steam](https://steamcommunity.com/id/Krozis_Kane/) | [GitHub](https://github.com/KrozisKane)
- __Balimbanana__ | programming, reverse engineering
- [Steam](https://steamcommunity.com/id/Balimbanana/) | [GitHub](https://github.com/Balimbanana)
- __raicovx__ | programming
- [GitHub](https://github.com/raicovx)
- __Jimmy-Baby__ | programming
- [GitHub](https://github.com/Jimmy-Baby)
#### Playtesters
- [Lear](https://steamcommunity.com/id/SKGNick)
- [bddu](https://steamcommunity.com/id/bddu/)
- [Foo-Fighter](https://steamcommunity.com/id/GumpForest/)
- [Diego003](https://steamcommunity.com/id/Diego63212/)
- [Googolplex23](https://steamcommunity.com/id/pandlfisher/)
- [WindedCone](https://steamcommunity.com/id/AceOak57/)
- [Antonio115](https://steamcommunity.com/profiles/76561198880559068/)
- __ReservedRegister__ :: reverse engineering
- [GitHub](https://github.com/ReservedRegister)

[__raicovx__](https://github.com/raicovx) :: Equipment persistence
| [__Jimmy-Baby__](https://github.com/Jimmy-Baby) :: Damage effects addon
| [__Removiekeen__](https://steamcommunity.com/profiles/76561198804614641/) :: logo design
| [__yarik2720__](https://github.com/yarik2720) :: CI, Russian translation

#### Third-party libraries
[SourceMod](https://github.com/alliedmodders/sourcemod)
| [SourceScramble](https://github.com/nosoop/SMExt-SourceScramble)
| [stocksoup](https://github.com/nosoop/stocksoup)
| [sm-logdebug](https://github.com/Alienmario/sm-logdebug)
| [smlib](https://github.com/bcserv/smlib/tree/transitional_syntax)
Binary file added extensions/sourcescramble.ext.dll
Binary file not shown.
Binary file added extensions/sourcescramble.ext.so
Binary file not shown.
126 changes: 96 additions & 30 deletions gamedata/srccoop.games.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Ascii made with https://patorjk.com/software/taag/ Font: Big

"Games"
{
"#default"
Expand Down Expand Up @@ -51,12 +53,12 @@
"Functions"
{

// __ _______ _____ _______ _ _ _
// \ \ / /_ _| __ \__ __| | | | /\ | |
// \ \ / / | | | |__) | | | | | | | / \ | |
// \ \/ / | | | _ / | | | | | |/ /\ \ | |
// \ / _| |_| | \ \ | | | |__| / ____ \| |____
// \/ |_____|_| \_\ |_| \____/_/ \_\______|
// __ _______ _____ _______ _ _ _
// \ \ / /_ _| __ \__ __| | | | /\ | |
// \ \ / / | | | |__) | | | | | | | / \ | |
// \ \/ / | | | _ / | | | | | |/ /\ \ | |
// \ / _| |_| | \ \ | | | |__| / ____ \| |____
// \/ |_____|_| \_\ |_| \____/_/ \_\______|

"CMultiplayRules::FAllowFlashlight"
{
Expand Down Expand Up @@ -626,12 +628,12 @@
"bms"
{

// _____ _____ _____ _ _ _______ _ _ _____ ______ _____
// / ____|_ _/ ____| \ | | /\|__ __| | | | __ \| ____|/ ____|
// | (___ | || | __| \| | / \ | | | | | | |__) | |__ | (___
// \___ \ | || | |_ | . ` | / /\ \ | | | | | | _ /| __| \___ \
// ____) |_| || |__| | |\ |/ ____ \| | | |__| | | \ \| |____ ____) |
// |_____/|_____\_____|_| \_/_/ \_\_| \____/|_| \_\______|_____/
// ____ __ __ _____ _____ _____ _____ _ _ _______ _ _ _____ ______ _____
// | _ \| \/ |/ ____| / ____|_ _/ ____| \ | | /\|__ __| | | | __ \| ____|/ ____|
// | |_) | \ / | (___ | (___ | || | __| \| | / \ | | | | | | |__) | |__ | (___
// | _ <| |\/| |\___ \ \___ \ | || | |_ | . ` | / /\ \ | | | | | | _ /| __| \___ \
// | |_) | | | |____) | ____) |_| || |__| | |\ |/ ____ \| | | |__| | | \ \| |____ ____) |
// |____/|_| |_|_____/ |_____/|_____\_____|_| \_/_/ \_\_| \____/|_| \_\______|_____/

"Signatures"
{
Expand Down Expand Up @@ -728,14 +730,46 @@
{
"linux" "@_ZNK13CAI_MoveProbe14TestGroundMoveERK6VectorS2_jfjP13AIMoveTrace_t"
}
"CAI_ScriptConditions::EvaluationThink" // void CAI_ScriptConditions::EvaluationThink()
{
"windows" "\x55\x8B\xEC\x83\xEC\x1C\x56\x8B\xF1\x80\xBE\x94\x03\x00\x00\x01" // str: "%s WARNING: Player is NOTARGET"
"linux" "@_ZN20CAI_ScriptConditions15EvaluationThinkEv"
}
}

// ____ __ __ _____ __ __ ______ __ __ _____ _______ _____ _ _ ______ _____
// | _ \| \/ |/ ____| | \/ | ____| \/ | __ \ /\|__ __/ ____| | | | ____|/ ____|
// | |_) | \ / | (___ | \ / | |__ | \ / | |__) / \ | | | | | |__| | |__ | (___
// | _ <| |\/| |\___ \ | |\/| | __| | |\/| | ___/ /\ \ | | | | | __ | __| \___ \
// | |_) | | | |____) | | | | | |____| | | | | / ____ \| | | |____| | | | |____ ____) |
// |____/|_| |_|_____/ |_| |_|______|_| |_|_| /_/ \_\_| \_____|_| |_|______|_____/

"MemPatches"
{
"CAI_ScriptConditions::EvaluationThink::GetSinglePlayer"
{
"signature" "CAI_ScriptConditions::EvaluationThink"
"linux" // JLE to JGE
{
"offset" "32h"
"verify" "0F 8E"
"patch" "0F 8D"
}
"windows" // (short) JLE to JGE
{
"offset" "26h"
"verify" "7E"
"patch" "7D"
}
}
}

// ____ ______ ______ _____ ______ _______ _____
// / __ \| ____| ____/ ____| ____|__ __/ ____|
// | | | | |__ | |__ | (___ | |__ | | | (___
// | | | | __| | __| \___ \| __| | | \___ \
// | |__| | | | | ____) | |____ | | ____) |
// \____/|_| |_| |_____/|______| |_| |_____/
// ____ __ __ _____ ____ ______ ______ _____ ______ _______ _____
// | _ \| \/ |/ ____| / __ \| ____| ____/ ____| ____|__ __/ ____|
// | |_) | \ / | (___ | | | | |__ | |__ | (___ | |__ | | | (___
// | _ <| |\/| |\___ \ | | | | __| | __| \___ \| __| | | \___ \
// | |_) | | | |____) | | |__| | | | | ____) | |____ | | ____) |
// |____/|_| |_|_____/ \____/|_| |_| |_____/|______| |_| |_____/

"Offsets"
{
Expand Down Expand Up @@ -930,12 +964,12 @@
"hl2mp"
{

// _____ _____ _____ _ _ _______ _ _ _____ ______ _____
// / ____|_ _/ ____| \ | | /\|__ __| | | | __ \| ____|/ ____|
// | (___ | || | __| \| | / \ | | | | | | |__) | |__ | (___
// \___ \ | || | |_ | . ` | / /\ \ | | | | | | _ /| __| \___ \
// ____) |_| || |__| | |\ |/ ____ \| | | |__| | | \ \| |____ ____) |
// |_____/|_____\_____|_| \_/_/ \_\_| \____/|_| \_\______|_____/
// _ _ _ ___ __ __ _____ _____ _____ _____ _ _ _______ _ _ _____ ______ _____
// | | | | | |__ \| \/ | __ \ / ____|_ _/ ____| \ | | /\|__ __| | | | __ \| ____|/ ____|
// | |__| | | ) | \ / | |__) | | (___ | || | __| \| | / \ | | | | | | |__) | |__ | (___
// | __ | | / /| |\/| | ___/ \___ \ | || | |_ | . ` | / /\ \ | | | | | | _ /| __| \___ \
// | | | | |____ / /_| | | | | ____) |_| || |__| | |\ |/ ____ \| | | |__| | | \ \| |____ ____) |
// |_| |_|______|____|_| |_|_| |_____/|_____\_____|_| \_/_/ \_\_| \____/|_| \_\______|_____/

"Signatures"
{
Expand Down Expand Up @@ -1025,14 +1059,46 @@
"windows" "\x55\x8B\xEC\xFF\x75\x10\xB9\x2A\x2A\x2A\x2A\xFF\x75\x0C\xFF\x75\x08\xE8\x2A\x2A\x2A\x2A\x5D\xC3"
"linux" "@_Z16GlobalEntity_AddPKcS0_12GLOBALESTATE"
}
"CAI_ScriptConditions::EvaluationThink" // void CAI_ScriptConditions::EvaluationThink()
{
"windows" "\x55\x8B\xEC\x83\xEC\x1C\x56\x8B\xF1\x80\xBE\x88\x03\x00\x00\x01" // str: "%s WARNING: Player is NOTARGET"
"linux" "@_ZN20CAI_ScriptConditions15EvaluationThinkEv"
}
}

// _ _ _ ___ __ __ _____ __ __ ______ __ __ _____ _______ _____ _ _ ______ _____
// | | | | | |__ \| \/ | __ \ | \/ | ____| \/ | __ \ /\|__ __/ ____| | | | ____|/ ____|
// | |__| | | ) | \ / | |__) | | \ / | |__ | \ / | |__) / \ | | | | | |__| | |__ | (___
// | __ | | / /| |\/| | ___/ | |\/| | __| | |\/| | ___/ /\ \ | | | | | __ | __| \___ \
// | | | | |____ / /_| | | | | | | | | |____| | | | | / ____ \| | | |____| | | | |____ ____) |
// |_| |_|______|____|_| |_|_| |_| |_|______|_| |_|_| /_/ \_\_| \_____|_| |_|______|_____/

"MemPatches"
{
"CAI_ScriptConditions::EvaluationThink::GetSinglePlayer"
{
"signature" "CAI_ScriptConditions::EvaluationThink"
"linux" // JLE to JGE
{
"offset" "25h"
"verify" "0F 8E"
"patch" "0F 8D"
}
"windows" // (short) JLE to JGE
{
"offset" "26h"
"verify" "7E"
"patch" "7D"
}
}
}

// ____ ______ ______ _____ ______ _______ _____
// / __ \| ____| ____/ ____| ____|__ __/ ____|
// | | | | |__ | |__ | (___ | |__ | | | (___
// | | | | __| | __| \___ \| __| | | \___ \
// | |__| | | | | ____) | |____ | | ____) |
// \____/|_| |_| |_____/|______| |_| |_____/
// _ _ _ ___ __ __ _____ ____ ______ ______ _____ ______ _______ _____
// | | | | | |__ \| \/ | __ \ / __ \| ____| ____/ ____| ____|__ __/ ____|
// | |__| | | ) | \ / | |__) | | | | | |__ | |__ | (___ | |__ | | | (___
// | __ | | / /| |\/| | ___/ | | | | __| | __| \___ \| __| | | \___ \
// | | | | |____ / /_| | | | | | |__| | | | | ____) | |____ | | ____) |
// |_| |_|______|____|_| |_|_| \____/|_| |_| |_____/|______| |_| |_____/

"Offsets"
{
Expand Down
137 changes: 137 additions & 0 deletions scripting/include/sourcescramble.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/**
* Memory patching utilities.
*/

#if defined __sourcescramble_ext_included
#endinput
#endif

#define __sourcescramble_ext_included

methodmap MemoryPatch < Handle {
/**
* Loads a memory patch from a game config handle.
*/
public static native MemoryPatch CreateFromConf(Handle gameconf, const char[] name);

/**
* Returns true if the contents at the memory location for the patch matches the contents
* specified in the game config. If the game config does not specify any verify section,
* this always returns true.
*/
public native bool Validate();

/**
* Enables the memory patch. Returns false if the validation check fails or the patch has
* already been applied.
*/
public native bool Enable();

/**
* Disables a memory patch.
*/
public native void Disable();

/**
* Returns the starting address of the patch, equivalent to the address of the patch's
* dependent signature plus the patch offset.
*/
property Address Address {
public native get();
}
};

methodmap MemoryBlock < Handle {
/**
* Allocates a fixed amount of memory, initializing the contents to zero.
* Size is in bytes.
*/
public native MemoryBlock(int size);

/**
* Disowns the associated memory block, allowing it to remain allocated even when the handle
* is deleted. Disowning the memory does not invalidate the handle.
*
* Only use this if you are certain that something else will free (or has freed) the memory
* block.
*/
public native void Disown();

/**
* Returns the address of the allocated memory block.
*/
property Address Address {
public native get();
}

/**
* Returns the size of the allocated memory block.
*/
property int Size {
public native get();
}

/**
* Load up to 4 bytes from an offset to the memory block, performing bounds checks to ensure
* reads are contained within the block.
*/
public int LoadFromOffset(int offset, NumberType size) {
if (offset < 0 || offset + GetNumberTypeByteSize(size) > this.Size) {
ThrowError("Cannot perform MemoryBlock access of %d bytes at offset %d (limit %d)",
GetNumberTypeByteSize(size), offset, this.Size);
}
return LoadFromAddress(this.Address + view_as<Address>(offset), size);
}

/**
* Store up to 4 bytes to an offset to the memory block, performing bounds checks to ensure
* writes are contained within the block.
*/
public void StoreToOffset(int offset, int data, NumberType size) {
if (offset < 0 || offset + GetNumberTypeByteSize(size) > this.Size) {
ThrowError("Cannot perform MemoryBlock access of %d bytes at offset %d (limit %d)",
GetNumberTypeByteSize(size), offset, this.Size);
}
StoreToAddress(this.Address + view_as<Address>(offset), data, size);
}
};

static stock int GetNumberTypeByteSize(NumberType size) {
switch (size) {
case NumberType_Int8: return 1;
case NumberType_Int16: return 2;
case NumberType_Int32: return 4;
}
ThrowError("Unknown NumberType %d. Did the SourceMod developers add some new ones?", size);
return 1; // maybe `return (1 << size);` ?
}

/**
* Returns the physical memory address of a given SourcePawn cell reference.
*/
native Address GetAddressOfCell(any& cell);

/**
* Returns the physical memory address of a given string.
*/
native Address GetAddressOfString(char[] array);

public Extension __ext_sourcescramble = {
name = "Source Scramble",
file = "sourcescramble.ext",
#if defined AUTOLOAD_EXTENSIONS
autoload = 1,
#else
autoload = 0,
#endif
#if defined REQUIRE_EXTENSIONS
required = 1,
#else
required = 0,
#endif
};

#if !defined REQUIRE_EXTENSIONS
public void __ext_sourcescramble_SetNTVOptional() {
}
#endif
1 change: 1 addition & 0 deletions scripting/include/srccoop.inc
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
#include <regex>
#include <dhooks>
#include <topmenus>
#include <sourcescramble>

#pragma newdecls required
#pragma semicolon 1
Expand Down
8 changes: 8 additions & 0 deletions scripting/include/srccoop/classdef.inc
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,14 @@ methodmap CAI_ScriptConditions < CBaseEntity
{
SetEntProp(this.GetEntIndex(), Prop_Data, "m_fDisabled", disabled);
}
public CBaseEntity GetTargetEnt()
{
return CBaseEntity(GetEntPropEnt(this.entindex, Prop_Data, "m_hTarget"));
}
public void SetTargetEnt(CBaseEntity pTarget)
{
SetEntPropEnt(this.entindex, Prop_Data, "m_hTarget", pTarget.entindex);
}
}

methodmap CBaseCombatWeapon < CBaseAnimating
Expand Down
Loading

0 comments on commit 9c9bf54

Please sign in to comment.