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 /**