- moved gamedata out of "configs"
authorDavid Anderson <dvander@alliedmods.net>
Sat Jun 16 05:42:16 2007 +0000 (2007-06-16)
changeset 94704dcaa8312e7
parent 946 91f294513439
child 948 8d0eff1ab907
- moved gamedata out of "configs"
- added signature scanning to gameconfs
- renamed "*" to "#default" in gameconfs
- added new inheritance feature to gameconfs
configs/gamedata/core.games.txt
configs/gamedata/sdktools.games.txt
core/GameConfigs.cpp
core/GameConfigs.h
gamedata/core.games.txt
gamedata/sdktools.games.txt
public/IGameConfigs.h
     1.1 --- a/configs/gamedata/core.games.txt	Sat Jun 16 05:40:18 2007 +0000
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,40 +0,0 @@
     1.4 -"Games"
     1.5 -{
     1.6 -	"#default"
     1.7 -	{
     1.8 -		"Offsets"
     1.9 -		{
    1.10 -			"GetDataDescMap"
    1.11 -			{
    1.12 -				"windows"		"13"
    1.13 -				"linux"			"14"
    1.14 -			}
    1.15 -		}
    1.16 -
    1.17 -	}
    1.18 -
    1.19 -	"cstrike"
    1.20 -	{
    1.21 -		"Keys"
    1.22 -		{
    1.23 -			"HudRadioMenuMsg"		"ShowMenu"
    1.24 -		}
    1.25 -	}
    1.26 -
    1.27 -	"dod"
    1.28 -	{
    1.29 -		"Keys"
    1.30 -		{
    1.31 -			"HudRadioMenuMsg"		"ShowMenu"
    1.32 -		}
    1.33 -	}
    1.34 -
    1.35 -
    1.36 -	"sourceforts"
    1.37 -	{
    1.38 -		"Keys"
    1.39 -		{
    1.40 -			"HudRadioMenuMsg"		"ShowMenu"
    1.41 -		}
    1.42 -	}
    1.43 -}
     2.1 --- a/configs/gamedata/sdktools.games.txt	Sat Jun 16 05:40:18 2007 +0000
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,19 +0,0 @@
     2.4 -"Games"
     2.5 -{
     2.6 -	"#default"
     2.7 -	{
     2.8 -		"#supported"
     2.9 -		{
    2.10 -			"game"		"cstrike"
    2.11 -		}
    2.12 -		
    2.13 -		"Offsets"
    2.14 -		{
    2.15 -			"GiveNamedItem"
    2.16 -			{
    2.17 -				"windows"	"329"
    2.18 -				"linux"		"330"
    2.19 -			}
    2.20 -		}
    2.21 -	}
    2.22 -}
     3.1 --- a/core/GameConfigs.cpp	Sat Jun 16 05:40:18 2007 +0000
     3.2 +++ b/core/GameConfigs.cpp	Sat Jun 16 05:42:16 2007 +0000
     3.3 @@ -22,6 +22,12 @@
     3.4  #include "HalfLife2.h"
     3.5  #include "Logger.h"
     3.6  #include "ShareSys.h"
     3.7 +#include "MemoryUtils.h"
     3.8 +#include "LibrarySys.h"
     3.9 +
    3.10 +#if defined PLATFORM_LINUX
    3.11 +#include <dlfcn.h>
    3.12 +#endif
    3.13  
    3.14  GameConfigManager g_GameConfigs;
    3.15  IGameConfig *g_pGameConf = NULL;
    3.16 @@ -33,6 +39,9 @@
    3.17  #define PSTATE_GAMEDEFS_OFFSETS			3
    3.18  #define PSTATE_GAMEDEFS_OFFSETS_OFFSET	4
    3.19  #define PSTATE_GAMEDEFS_KEYS			5
    3.20 +#define PSTATE_GAMEDEFS_SUPPORTED		6
    3.21 +#define PSTATE_GAMEDEFS_SIGNATURES		7
    3.22 +#define PSTATE_GAMEDEFS_SIGNATURES_SIG	8
    3.23  
    3.24  #if defined PLATFORM_WINDOWS
    3.25  #define PLATFORM_NAME	"windows"
    3.26 @@ -40,12 +49,24 @@
    3.27  #define PLATFORM_NAME	"linux"
    3.28  #endif
    3.29  
    3.30 +struct TempSigInfo
    3.31 +{
    3.32 +	void Reset()
    3.33 +	{
    3.34 +		library[0] = '\0';
    3.35 +		sig[0] = '\0';
    3.36 +	}
    3.37 +	char sig[512];
    3.38 +	char library[64];
    3.39 +} s_TempSig;
    3.40 +
    3.41  CGameConfig::CGameConfig(const char *file)
    3.42  {
    3.43  	m_pFile = sm_strdup(file);
    3.44  	m_pOffsets = sm_trie_create();
    3.45  	m_pProps = sm_trie_create();
    3.46  	m_pKeys = sm_trie_create();
    3.47 +	m_pSigs = sm_trie_create();
    3.48  	m_pStrings = new BaseStringTable(512);
    3.49  	m_RefCount = 0;
    3.50  }
    3.51 @@ -55,6 +76,7 @@
    3.52  	sm_trie_destroy(m_pOffsets);
    3.53  	sm_trie_destroy(m_pProps);
    3.54  	sm_trie_destroy(m_pKeys);
    3.55 +	sm_trie_destroy(m_pSigs);
    3.56  	delete [] m_pFile;
    3.57  	delete m_pStrings;
    3.58  }
    3.59 @@ -66,6 +88,7 @@
    3.60  		m_IgnoreLevel++;
    3.61  		return SMCParse_Continue;
    3.62  	}
    3.63 +
    3.64  	switch (m_ParseState)
    3.65  	{
    3.66  	case PSTATE_NONE:
    3.67 @@ -81,6 +104,7 @@
    3.68  	case PSTATE_GAMES:
    3.69  		{
    3.70  			if ((strcmp(name, "*") == 0)
    3.71 +				|| (strcmp(name, "#default") == 0)
    3.72  				|| (strcmp(name, g_mod) == 0))
    3.73  			{
    3.74  				m_ParseState = PSTATE_GAMEDEFS;
    3.75 @@ -95,9 +119,24 @@
    3.76  			if (strcmp(name, "Offsets") == 0)
    3.77  			{
    3.78  				m_ParseState = PSTATE_GAMEDEFS_OFFSETS;
    3.79 -			} else if (strcmp(name, "Keys") == 0) {
    3.80 +			}
    3.81 +			else if (strcmp(name, "Keys") == 0)
    3.82 +			{
    3.83  				m_ParseState = PSTATE_GAMEDEFS_KEYS;
    3.84 -			} else {
    3.85 +			}
    3.86 +			else if ((strcmp(name, "#supported") == 0)
    3.87 +					 && (strcmp(m_mod, "#default") == 0))
    3.88 +			{
    3.89 +				m_ParseState = PSTATE_GAMEDEFS_SUPPORTED;
    3.90 +				/* Ignore this section unless we get a game. */
    3.91 +				bShouldBeReadingDefault = false;
    3.92 +			}
    3.93 +			else if (strcmp(name, "Signatures") == 0)
    3.94 +			{
    3.95 +				m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
    3.96 +			}
    3.97 +			else
    3.98 +			{
    3.99  				m_IgnoreLevel++;
   3.100  			}
   3.101  			break;
   3.102 @@ -110,9 +149,18 @@
   3.103  			m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET;
   3.104  			break;
   3.105  		}
   3.106 +	case PSTATE_GAMEDEFS_SIGNATURES:
   3.107 +		{
   3.108 +			strncopy(m_offset, name, sizeof(m_offset));
   3.109 +			s_TempSig.Reset();
   3.110 +			m_ParseState = PSTATE_GAMEDEFS_SIGNATURES_SIG;
   3.111 +			break;
   3.112 +		}
   3.113  	/* No sub-sections allowed:
   3.114  	 case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
   3.115  	 case PSTATE_GAMEDEFS_KEYS:
   3.116 +	 case PSTATE_GAMEDEFS_SUPPORTED:
   3.117 +	 case PSTATE_GAMEDEFS_SIGNATURES_SIG:
   3.118  	 */
   3.119  	default:
   3.120  		{
   3.121 @@ -146,6 +194,19 @@
   3.122  	} else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) {
   3.123  		int id = m_pStrings->AddString(value);
   3.124  		sm_trie_insert(m_pKeys, key, (void *)id);
   3.125 +	} else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) {
   3.126 +		if (strcmp(key, "game") == 0
   3.127 +			&& strcmp(value, g_mod) == 0)
   3.128 +		{
   3.129 +			bShouldBeReadingDefault = true;
   3.130 +		}
   3.131 +	} else if (m_ParseState == PSTATE_GAMEDEFS_SIGNATURES_SIG) {
   3.132 +		if (strcmp(key, PLATFORM_NAME) == 0)
   3.133 +		{
   3.134 +			strncopy(s_TempSig.sig, value, sizeof(s_TempSig.sig));
   3.135 +		} else if (strcmp(key, "library") == 0) {
   3.136 +			strncopy(s_TempSig.library, value, sizeof(s_TempSig.library));
   3.137 +		}
   3.138  	}
   3.139  
   3.140  	return SMCParse_Continue;
   3.141 @@ -191,7 +252,7 @@
   3.142  					sm_trie_insert(m_pProps, m_offset, pProp);
   3.143  				} else {
   3.144  					/* Check if it's a non-default game and no offsets exist */
   3.145 -					if ((strcmp(m_mod, "*") != 0)
   3.146 +					if (((strcmp(m_mod, "*") != 0) && strcmp(m_mod, "#default") != 0)
   3.147  						&& (!sm_trie_retrieve(m_pOffsets, m_offset, NULL)))
   3.148  					{
   3.149  						g_Logger.LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")", 
   3.150 @@ -205,6 +266,132 @@
   3.151  			m_ParseState = PSTATE_GAMEDEFS_OFFSETS;
   3.152  			break;
   3.153  		}
   3.154 +	case PSTATE_GAMEDEFS_SUPPORTED:
   3.155 +		{
   3.156 +			if (!bShouldBeReadingDefault)
   3.157 +			{
   3.158 +				/* If we shouldn't read the rest of this section, set the ignore level. */
   3.159 +				m_IgnoreLevel = 1;
   3.160 +			}
   3.161 +			m_ParseState = PSTATE_GAMEDEFS;
   3.162 +			break;
   3.163 +		}
   3.164 +	case PSTATE_GAMEDEFS_SIGNATURES_SIG:
   3.165 +		{
   3.166 +			if (s_TempSig.library[0] == '\0')
   3.167 +			{
   3.168 +				/* assume server */
   3.169 +				strncopy(s_TempSig.library, "server", sizeof(s_TempSig.library));
   3.170 +			}
   3.171 +			void *addrInBase = NULL;
   3.172 +			if (strcmp(s_TempSig.library, "server") == 0)
   3.173 +			{
   3.174 +				addrInBase = g_SMAPI->serverFactory(false);
   3.175 +			} else if (strcmp(s_TempSig.library, "engine") == 0) {
   3.176 +				addrInBase = g_SMAPI->engineFactory(false);
   3.177 +			}
   3.178 +			void *final_addr = NULL;
   3.179 +			if (addrInBase == NULL)
   3.180 +			{
   3.181 +				g_Logger.LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")", 
   3.182 +					s_TempSig.library, 
   3.183 +					m_pFile);
   3.184 +			} else {
   3.185 +#if defined PLATFORM_LINUX
   3.186 +				if (s_TempSig.sig_lin[0] == '@')
   3.187 +				{
   3.188 +					Dl_info info;
   3.189 +					/* GNU only: returns 0 on error, inconsistent! >:[ */
   3.190 +					if (dladdr(addrInBase, &info) == 0)
   3.191 +					{
   3.192 +						void *handle = dlopen(info.dli_fname, RTLD_NOW);
   3.193 +						if (handle)
   3.194 +						{
   3.195 +							final_addr = dlsym(handle, &s_TempSig.sig_lin[1]);
   3.196 +							dlclose(handle);
   3.197 +						} else {
   3.198 +							g_Logger.LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
   3.199 +								s_TempSig.library,
   3.200 +								m_pFile);
   3.201 +						}
   3.202 +					} else {
   3.203 +						g_Logger.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")",
   3.204 +							s_TempSig.library,
   3.205 +							m_pFile);
   3.206 +					}
   3.207 +					if (!final_addr)
   3.208 +					{
   3.209 +						g_Logger.LogError("[SM] Unable to find named symbol (symbol \"%s\") (library \"%s\") (gameconf \"%s\")",
   3.210 +							&s_TempSig.sig_lin[1],
   3.211 +							s_TempSig.library,
   3.212 +							m_pFile);
   3.213 +					}
   3.214 +				}
   3.215 +				if (final_addr)
   3.216 +				{
   3.217 +					goto skip_find;
   3.218 +				}
   3.219 +#endif
   3.220 +				/* First, preprocess the signature */
   3.221 +				char real_sig[255];
   3.222 +				size_t real_bytes;
   3.223 +				size_t length;
   3.224 +
   3.225 +				real_bytes = 0;
   3.226 +				length = strlen(s_TempSig.sig);
   3.227 +
   3.228 +				for (size_t i=0; i<length; i++)
   3.229 +				{
   3.230 +					if (real_bytes >= sizeof(real_sig))
   3.231 +					{
   3.232 +						break;
   3.233 +					}
   3.234 +					real_sig[real_bytes++] = s_TempSig.sig[i];
   3.235 +					if (s_TempSig.sig[i] == '\\'
   3.236 +						&& s_TempSig.sig[i+1] == 'x')
   3.237 +					{
   3.238 +						if (i + 3 >= length)
   3.239 +						{
   3.240 +							continue;
   3.241 +						}
   3.242 +						/* Get the hex part */
   3.243 +						char s_byte[3];
   3.244 +						int r_byte;
   3.245 +						s_byte[0] = s_TempSig.sig[i+2];
   3.246 +						s_byte[1] = s_TempSig.sig[i+3];
   3.247 +						s_byte[2] = '\0';
   3.248 +						/* Read it as an integer */
   3.249 +						sscanf(s_byte, "%x", &r_byte);
   3.250 +						/* Save the value */
   3.251 +						real_sig[real_bytes-1] = r_byte;
   3.252 +						/* Adjust index */
   3.253 +						i += 3;
   3.254 +					}
   3.255 +				}
   3.256 +
   3.257 +				if (real_bytes < 1)
   3.258 +				{
   3.259 +					g_Logger.LogError("[SM] Invalid signature length of 1 (name \"%s\") (gameconf \"%s\")",
   3.260 +						m_offset,
   3.261 +						m_pFile);
   3.262 +				} else {
   3.263 +					final_addr = g_MemUtils.FindPattern(addrInBase, real_sig, real_bytes);
   3.264 +					if (!final_addr)
   3.265 +					{
   3.266 +						g_Logger.LogError("[SM] Unable to find signature (name \"%s\") (gameconf \"%s\")", 
   3.267 +							m_offset,
   3.268 +							m_pFile);
   3.269 +					}
   3.270 +				}
   3.271 +			}
   3.272 +
   3.273 +#if defined PLATFORM_LINUX
   3.274 +skip_find:
   3.275 +#endif
   3.276 +			sm_trie_insert(m_pSigs, m_offset, final_addr);
   3.277 +
   3.278 +			break;
   3.279 +		}
   3.280  	}
   3.281  
   3.282  	return SMCParse_Continue;
   3.283 @@ -215,10 +402,16 @@
   3.284  	SMCParseError err;
   3.285  
   3.286  	char path[PLATFORM_MAX_PATH];
   3.287 -	g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "configs/gamedata/%s.txt", m_pFile);
   3.288 +	g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "gamedata/%s.txt", m_pFile);
   3.289 +	/* Backwards compatibility */
   3.290 +	if (!g_LibSys.PathExists(path))
   3.291 +	{
   3.292 +		g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "configs/gamedata/%s.txt", m_pFile);
   3.293 +	}
   3.294  
   3.295  	/* Initialize parse states */
   3.296  	m_IgnoreLevel = 0;
   3.297 +	bShouldBeReadingDefault = true;
   3.298  	m_ParseState = PSTATE_NONE;
   3.299  	/* Reset cached data */
   3.300  	m_pStrings->Reset();
   3.301 @@ -276,6 +469,11 @@
   3.302  	return pProp;
   3.303  }
   3.304  
   3.305 +bool CGameConfig::GetMemSig(const char *key, void **addr)
   3.306 +{
   3.307 +	return sm_trie_retrieve(m_pSigs, key, addr);
   3.308 +}
   3.309 +
   3.310  void CGameConfig::IncRefCount()
   3.311  {
   3.312  	m_RefCount++;
     4.1 --- a/core/GameConfigs.h	Sat Jun 16 05:40:18 2007 +0000
     4.2 +++ b/core/GameConfigs.h	Sat Jun 16 05:42:16 2007 +0000
     4.3 @@ -44,6 +44,7 @@
     4.4  	const char *GetKeyValue(const char *key);
     4.5  	bool GetOffset(const char *key, int *value);
     4.6  	SendProp *GetSendProp(const char *key);
     4.7 +	bool GetMemSig(const char *key, void **addr);
     4.8  public:
     4.9  	void IncRefCount();
    4.10  	unsigned int DecRefCount();
    4.11 @@ -53,6 +54,7 @@
    4.12  	Trie *m_pOffsets;
    4.13  	Trie *m_pProps;
    4.14  	Trie *m_pKeys;
    4.15 +	Trie *m_pSigs;
    4.16  	unsigned int m_RefCount;
    4.17  	/* Parse states */
    4.18  	int m_ParseState;
    4.19 @@ -61,6 +63,7 @@
    4.20  	char m_prop[64];
    4.21  	char m_offset[64];
    4.22  	char m_mod[255];
    4.23 +	bool bShouldBeReadingDefault;
    4.24  };
    4.25  
    4.26  class GameConfigManager : 
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/gamedata/core.games.txt	Sat Jun 16 05:42:16 2007 +0000
     5.3 @@ -0,0 +1,40 @@
     5.4 +"Games"
     5.5 +{
     5.6 +	"#default"
     5.7 +	{
     5.8 +		"Offsets"
     5.9 +		{
    5.10 +			"GetDataDescMap"
    5.11 +			{
    5.12 +				"windows"		"13"
    5.13 +				"linux"			"14"
    5.14 +			}
    5.15 +		}
    5.16 +
    5.17 +	}
    5.18 +
    5.19 +	"cstrike"
    5.20 +	{
    5.21 +		"Keys"
    5.22 +		{
    5.23 +			"HudRadioMenuMsg"		"ShowMenu"
    5.24 +		}
    5.25 +	}
    5.26 +
    5.27 +	"dod"
    5.28 +	{
    5.29 +		"Keys"
    5.30 +		{
    5.31 +			"HudRadioMenuMsg"		"ShowMenu"
    5.32 +		}
    5.33 +	}
    5.34 +
    5.35 +
    5.36 +	"sourceforts"
    5.37 +	{
    5.38 +		"Keys"
    5.39 +		{
    5.40 +			"HudRadioMenuMsg"		"ShowMenu"
    5.41 +		}
    5.42 +	}
    5.43 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/gamedata/sdktools.games.txt	Sat Jun 16 05:42:16 2007 +0000
     6.3 @@ -0,0 +1,19 @@
     6.4 +"Games"
     6.5 +{
     6.6 +	"#default"
     6.7 +	{
     6.8 +		"#supported"
     6.9 +		{
    6.10 +			"game"		"cstrike"
    6.11 +		}
    6.12 +		
    6.13 +		"Offsets"
    6.14 +		{
    6.15 +			"GiveNamedItem"
    6.16 +			{
    6.17 +				"windows"	"329"
    6.18 +				"linux"		"330"
    6.19 +			}
    6.20 +		}
    6.21 +	}
    6.22 +}
     7.1 --- a/public/IGameConfigs.h	Sat Jun 16 05:40:18 2007 +0000
     7.2 +++ b/public/IGameConfigs.h	Sat Jun 16 05:42:16 2007 +0000
     7.3 @@ -27,7 +27,7 @@
     7.4   */
     7.5  
     7.6  #define SMINTERFACE_GAMECONFIG_NAME			"IGameConfigManager"
     7.7 -#define SMINTERFACE_GAMECONFIG_VERSION		1
     7.8 +#define SMINTERFACE_GAMECONFIG_VERSION		2
     7.9  
    7.10  class SendProp;
    7.11  
    7.12 @@ -63,6 +63,16 @@
    7.13  		 * @return				String containing the value, or NULL if not found.
    7.14  		 */
    7.15  		virtual const char *GetKeyValue(const char *key) =0;
    7.16 +
    7.17 +		/**
    7.18 +		 * @brief Retrieves a cached memory signature.
    7.19 +		 *
    7.20 +		 * @param key			Name of the signature.
    7.21 +		 * @param addr			Pointer to store the memory address in.
    7.22 +		 * @return				A MemorySignature pointer on success, or NULL 
    7.23 +		 *						if the key was not found.
    7.24 +		 */
    7.25 +		virtual bool GetMemSig(const char *key, void **addr) =0;
    7.26  	};
    7.27  
    7.28  	/**