- moved gamedata out of "configs"
- added signature scanning to gameconfs - renamed "*" to "#default" in gameconfs - added new inheritance feature to gameconfs --HG-- rename : configs/gamedata/core.games.txt => gamedata/core.games.txt rename : configs/gamedata/sdktools.games.txt => gamedata/sdktools.games.txt extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40953
This commit is contained in:
		
							parent
							
								
									fa92af4907
								
							
						
					
					
						commit
						b706a6990c
					
				| @ -22,6 +22,12 @@ | |||||||
| #include "HalfLife2.h" | #include "HalfLife2.h" | ||||||
| #include "Logger.h" | #include "Logger.h" | ||||||
| #include "ShareSys.h" | #include "ShareSys.h" | ||||||
|  | #include "MemoryUtils.h" | ||||||
|  | #include "LibrarySys.h" | ||||||
|  | 
 | ||||||
|  | #if defined PLATFORM_LINUX | ||||||
|  | #include <dlfcn.h> | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| GameConfigManager g_GameConfigs; | GameConfigManager g_GameConfigs; | ||||||
| IGameConfig *g_pGameConf = NULL; | IGameConfig *g_pGameConf = NULL; | ||||||
| @ -33,6 +39,9 @@ char g_mod[255]; | |||||||
| #define PSTATE_GAMEDEFS_OFFSETS			3 | #define PSTATE_GAMEDEFS_OFFSETS			3 | ||||||
| #define PSTATE_GAMEDEFS_OFFSETS_OFFSET	4 | #define PSTATE_GAMEDEFS_OFFSETS_OFFSET	4 | ||||||
| #define PSTATE_GAMEDEFS_KEYS			5 | #define PSTATE_GAMEDEFS_KEYS			5 | ||||||
|  | #define PSTATE_GAMEDEFS_SUPPORTED		6 | ||||||
|  | #define PSTATE_GAMEDEFS_SIGNATURES		7 | ||||||
|  | #define PSTATE_GAMEDEFS_SIGNATURES_SIG	8 | ||||||
| 
 | 
 | ||||||
| #if defined PLATFORM_WINDOWS | #if defined PLATFORM_WINDOWS | ||||||
| #define PLATFORM_NAME	"windows" | #define PLATFORM_NAME	"windows" | ||||||
| @ -40,12 +49,24 @@ char g_mod[255]; | |||||||
| #define PLATFORM_NAME	"linux" | #define PLATFORM_NAME	"linux" | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | struct TempSigInfo | ||||||
|  | { | ||||||
|  | 	void Reset() | ||||||
|  | 	{ | ||||||
|  | 		library[0] = '\0'; | ||||||
|  | 		sig[0] = '\0'; | ||||||
|  | 	} | ||||||
|  | 	char sig[512]; | ||||||
|  | 	char library[64]; | ||||||
|  | } s_TempSig; | ||||||
|  | 
 | ||||||
| CGameConfig::CGameConfig(const char *file) | CGameConfig::CGameConfig(const char *file) | ||||||
| { | { | ||||||
| 	m_pFile = sm_strdup(file); | 	m_pFile = sm_strdup(file); | ||||||
| 	m_pOffsets = sm_trie_create(); | 	m_pOffsets = sm_trie_create(); | ||||||
| 	m_pProps = sm_trie_create(); | 	m_pProps = sm_trie_create(); | ||||||
| 	m_pKeys = sm_trie_create(); | 	m_pKeys = sm_trie_create(); | ||||||
|  | 	m_pSigs = sm_trie_create(); | ||||||
| 	m_pStrings = new BaseStringTable(512); | 	m_pStrings = new BaseStringTable(512); | ||||||
| 	m_RefCount = 0; | 	m_RefCount = 0; | ||||||
| } | } | ||||||
| @ -55,6 +76,7 @@ CGameConfig::~CGameConfig() | |||||||
| 	sm_trie_destroy(m_pOffsets); | 	sm_trie_destroy(m_pOffsets); | ||||||
| 	sm_trie_destroy(m_pProps); | 	sm_trie_destroy(m_pProps); | ||||||
| 	sm_trie_destroy(m_pKeys); | 	sm_trie_destroy(m_pKeys); | ||||||
|  | 	sm_trie_destroy(m_pSigs); | ||||||
| 	delete [] m_pFile; | 	delete [] m_pFile; | ||||||
| 	delete m_pStrings; | 	delete m_pStrings; | ||||||
| } | } | ||||||
| @ -66,6 +88,7 @@ SMCParseResult CGameConfig::ReadSMC_NewSection(const char *name, bool opt_quotes | |||||||
| 		m_IgnoreLevel++; | 		m_IgnoreLevel++; | ||||||
| 		return SMCParse_Continue; | 		return SMCParse_Continue; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	switch (m_ParseState) | 	switch (m_ParseState) | ||||||
| 	{ | 	{ | ||||||
| 	case PSTATE_NONE: | 	case PSTATE_NONE: | ||||||
| @ -81,6 +104,7 @@ SMCParseResult CGameConfig::ReadSMC_NewSection(const char *name, bool opt_quotes | |||||||
| 	case PSTATE_GAMES: | 	case PSTATE_GAMES: | ||||||
| 		{ | 		{ | ||||||
| 			if ((strcmp(name, "*") == 0) | 			if ((strcmp(name, "*") == 0) | ||||||
|  | 				|| (strcmp(name, "#default") == 0) | ||||||
| 				|| (strcmp(name, g_mod) == 0)) | 				|| (strcmp(name, g_mod) == 0)) | ||||||
| 			{ | 			{ | ||||||
| 				m_ParseState = PSTATE_GAMEDEFS; | 				m_ParseState = PSTATE_GAMEDEFS; | ||||||
| @ -95,9 +119,24 @@ SMCParseResult CGameConfig::ReadSMC_NewSection(const char *name, bool opt_quotes | |||||||
| 			if (strcmp(name, "Offsets") == 0) | 			if (strcmp(name, "Offsets") == 0) | ||||||
| 			{ | 			{ | ||||||
| 				m_ParseState = PSTATE_GAMEDEFS_OFFSETS; | 				m_ParseState = PSTATE_GAMEDEFS_OFFSETS; | ||||||
| 			} else if (strcmp(name, "Keys") == 0) { | 			} | ||||||
|  | 			else if (strcmp(name, "Keys") == 0) | ||||||
|  | 			{ | ||||||
| 				m_ParseState = PSTATE_GAMEDEFS_KEYS; | 				m_ParseState = PSTATE_GAMEDEFS_KEYS; | ||||||
| 			} else { | 			} | ||||||
|  | 			else if ((strcmp(name, "#supported") == 0) | ||||||
|  | 					 && (strcmp(m_mod, "#default") == 0)) | ||||||
|  | 			{ | ||||||
|  | 				m_ParseState = PSTATE_GAMEDEFS_SUPPORTED; | ||||||
|  | 				/* Ignore this section unless we get a game. */ | ||||||
|  | 				bShouldBeReadingDefault = false; | ||||||
|  | 			} | ||||||
|  | 			else if (strcmp(name, "Signatures") == 0) | ||||||
|  | 			{ | ||||||
|  | 				m_ParseState = PSTATE_GAMEDEFS_SIGNATURES; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
| 				m_IgnoreLevel++; | 				m_IgnoreLevel++; | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
| @ -110,9 +149,18 @@ SMCParseResult CGameConfig::ReadSMC_NewSection(const char *name, bool opt_quotes | |||||||
| 			m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET; | 			m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  | 	case PSTATE_GAMEDEFS_SIGNATURES: | ||||||
|  | 		{ | ||||||
|  | 			strncopy(m_offset, name, sizeof(m_offset)); | ||||||
|  | 			s_TempSig.Reset(); | ||||||
|  | 			m_ParseState = PSTATE_GAMEDEFS_SIGNATURES_SIG; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
| 	/* No sub-sections allowed:
 | 	/* No sub-sections allowed:
 | ||||||
| 	 case PSTATE_GAMEDEFS_OFFSETS_OFFSET: | 	 case PSTATE_GAMEDEFS_OFFSETS_OFFSET: | ||||||
| 	 case PSTATE_GAMEDEFS_KEYS: | 	 case PSTATE_GAMEDEFS_KEYS: | ||||||
|  | 	 case PSTATE_GAMEDEFS_SUPPORTED: | ||||||
|  | 	 case PSTATE_GAMEDEFS_SIGNATURES_SIG: | ||||||
| 	 */ | 	 */ | ||||||
| 	default: | 	default: | ||||||
| 		{ | 		{ | ||||||
| @ -146,6 +194,19 @@ SMCParseResult CGameConfig::ReadSMC_KeyValue(const char *key, const char *value, | |||||||
| 	} else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) { | 	} else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) { | ||||||
| 		int id = m_pStrings->AddString(value); | 		int id = m_pStrings->AddString(value); | ||||||
| 		sm_trie_insert(m_pKeys, key, (void *)id); | 		sm_trie_insert(m_pKeys, key, (void *)id); | ||||||
|  | 	} else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) { | ||||||
|  | 		if (strcmp(key, "game") == 0 | ||||||
|  | 			&& strcmp(value, g_mod) == 0) | ||||||
|  | 		{ | ||||||
|  | 			bShouldBeReadingDefault = true; | ||||||
|  | 		} | ||||||
|  | 	} else if (m_ParseState == PSTATE_GAMEDEFS_SIGNATURES_SIG) { | ||||||
|  | 		if (strcmp(key, PLATFORM_NAME) == 0) | ||||||
|  | 		{ | ||||||
|  | 			strncopy(s_TempSig.sig, value, sizeof(s_TempSig.sig)); | ||||||
|  | 		} else if (strcmp(key, "library") == 0) { | ||||||
|  | 			strncopy(s_TempSig.library, value, sizeof(s_TempSig.library)); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return SMCParse_Continue; | 	return SMCParse_Continue; | ||||||
| @ -191,7 +252,7 @@ SMCParseResult CGameConfig::ReadSMC_LeavingSection() | |||||||
| 					sm_trie_insert(m_pProps, m_offset, pProp); | 					sm_trie_insert(m_pProps, m_offset, pProp); | ||||||
| 				} else { | 				} else { | ||||||
| 					/* Check if it's a non-default game and no offsets exist */ | 					/* Check if it's a non-default game and no offsets exist */ | ||||||
| 					if ((strcmp(m_mod, "*") != 0) | 					if (((strcmp(m_mod, "*") != 0) && strcmp(m_mod, "#default") != 0) | ||||||
| 						&& (!sm_trie_retrieve(m_pOffsets, m_offset, NULL))) | 						&& (!sm_trie_retrieve(m_pOffsets, m_offset, NULL))) | ||||||
| 					{ | 					{ | ||||||
| 						g_Logger.LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")",  | 						g_Logger.LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")",  | ||||||
| @ -203,6 +264,132 @@ SMCParseResult CGameConfig::ReadSMC_LeavingSection() | |||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			m_ParseState = PSTATE_GAMEDEFS_OFFSETS; | 			m_ParseState = PSTATE_GAMEDEFS_OFFSETS; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	case PSTATE_GAMEDEFS_SUPPORTED: | ||||||
|  | 		{ | ||||||
|  | 			if (!bShouldBeReadingDefault) | ||||||
|  | 			{ | ||||||
|  | 				/* If we shouldn't read the rest of this section, set the ignore level. */ | ||||||
|  | 				m_IgnoreLevel = 1; | ||||||
|  | 			} | ||||||
|  | 			m_ParseState = PSTATE_GAMEDEFS; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	case PSTATE_GAMEDEFS_SIGNATURES_SIG: | ||||||
|  | 		{ | ||||||
|  | 			if (s_TempSig.library[0] == '\0') | ||||||
|  | 			{ | ||||||
|  | 				/* assume server */ | ||||||
|  | 				strncopy(s_TempSig.library, "server", sizeof(s_TempSig.library)); | ||||||
|  | 			} | ||||||
|  | 			void *addrInBase = NULL; | ||||||
|  | 			if (strcmp(s_TempSig.library, "server") == 0) | ||||||
|  | 			{ | ||||||
|  | 				addrInBase = g_SMAPI->serverFactory(false); | ||||||
|  | 			} else if (strcmp(s_TempSig.library, "engine") == 0) { | ||||||
|  | 				addrInBase = g_SMAPI->engineFactory(false); | ||||||
|  | 			} | ||||||
|  | 			void *final_addr = NULL; | ||||||
|  | 			if (addrInBase == NULL) | ||||||
|  | 			{ | ||||||
|  | 				g_Logger.LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")",  | ||||||
|  | 					s_TempSig.library,  | ||||||
|  | 					m_pFile); | ||||||
|  | 			} else { | ||||||
|  | #if defined PLATFORM_LINUX | ||||||
|  | 				if (s_TempSig.sig_lin[0] == '@') | ||||||
|  | 				{ | ||||||
|  | 					Dl_info info; | ||||||
|  | 					/* GNU only: returns 0 on error, inconsistent! >:[ */ | ||||||
|  | 					if (dladdr(addrInBase, &info) == 0) | ||||||
|  | 					{ | ||||||
|  | 						void *handle = dlopen(info.dli_fname, RTLD_NOW); | ||||||
|  | 						if (handle) | ||||||
|  | 						{ | ||||||
|  | 							final_addr = dlsym(handle, &s_TempSig.sig_lin[1]); | ||||||
|  | 							dlclose(handle); | ||||||
|  | 						} else { | ||||||
|  | 							g_Logger.LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")", | ||||||
|  | 								s_TempSig.library, | ||||||
|  | 								m_pFile); | ||||||
|  | 						} | ||||||
|  | 					} else { | ||||||
|  | 						g_Logger.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", | ||||||
|  | 							s_TempSig.library, | ||||||
|  | 							m_pFile); | ||||||
|  | 					} | ||||||
|  | 					if (!final_addr) | ||||||
|  | 					{ | ||||||
|  | 						g_Logger.LogError("[SM] Unable to find named symbol (symbol \"%s\") (library \"%s\") (gameconf \"%s\")", | ||||||
|  | 							&s_TempSig.sig_lin[1], | ||||||
|  | 							s_TempSig.library, | ||||||
|  | 							m_pFile); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				if (final_addr) | ||||||
|  | 				{ | ||||||
|  | 					goto skip_find; | ||||||
|  | 				} | ||||||
|  | #endif | ||||||
|  | 				/* First, preprocess the signature */ | ||||||
|  | 				char real_sig[255]; | ||||||
|  | 				size_t real_bytes; | ||||||
|  | 				size_t length; | ||||||
|  | 
 | ||||||
|  | 				real_bytes = 0; | ||||||
|  | 				length = strlen(s_TempSig.sig); | ||||||
|  | 
 | ||||||
|  | 				for (size_t i=0; i<length; i++) | ||||||
|  | 				{ | ||||||
|  | 					if (real_bytes >= sizeof(real_sig)) | ||||||
|  | 					{ | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  | 					real_sig[real_bytes++] = s_TempSig.sig[i]; | ||||||
|  | 					if (s_TempSig.sig[i] == '\\' | ||||||
|  | 						&& s_TempSig.sig[i+1] == 'x') | ||||||
|  | 					{ | ||||||
|  | 						if (i + 3 >= length) | ||||||
|  | 						{ | ||||||
|  | 							continue; | ||||||
|  | 						} | ||||||
|  | 						/* Get the hex part */ | ||||||
|  | 						char s_byte[3]; | ||||||
|  | 						int r_byte; | ||||||
|  | 						s_byte[0] = s_TempSig.sig[i+2]; | ||||||
|  | 						s_byte[1] = s_TempSig.sig[i+3]; | ||||||
|  | 						s_byte[2] = '\0'; | ||||||
|  | 						/* Read it as an integer */ | ||||||
|  | 						sscanf(s_byte, "%x", &r_byte); | ||||||
|  | 						/* Save the value */ | ||||||
|  | 						real_sig[real_bytes-1] = r_byte; | ||||||
|  | 						/* Adjust index */ | ||||||
|  | 						i += 3; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if (real_bytes < 1) | ||||||
|  | 				{ | ||||||
|  | 					g_Logger.LogError("[SM] Invalid signature length of 1 (name \"%s\") (gameconf \"%s\")", | ||||||
|  | 						m_offset, | ||||||
|  | 						m_pFile); | ||||||
|  | 				} else { | ||||||
|  | 					final_addr = g_MemUtils.FindPattern(addrInBase, real_sig, real_bytes); | ||||||
|  | 					if (!final_addr) | ||||||
|  | 					{ | ||||||
|  | 						g_Logger.LogError("[SM] Unable to find signature (name \"%s\") (gameconf \"%s\")",  | ||||||
|  | 							m_offset, | ||||||
|  | 							m_pFile); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | #if defined PLATFORM_LINUX | ||||||
|  | skip_find: | ||||||
|  | #endif | ||||||
|  | 			sm_trie_insert(m_pSigs, m_offset, final_addr); | ||||||
|  | 
 | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @ -215,10 +402,16 @@ bool CGameConfig::Reparse(char *error, size_t maxlength) | |||||||
| 	SMCParseError err; | 	SMCParseError err; | ||||||
| 
 | 
 | ||||||
| 	char path[PLATFORM_MAX_PATH]; | 	char path[PLATFORM_MAX_PATH]; | ||||||
| 	g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "configs/gamedata/%s.txt", m_pFile); | 	g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "gamedata/%s.txt", m_pFile); | ||||||
|  | 	/* Backwards compatibility */ | ||||||
|  | 	if (!g_LibSys.PathExists(path)) | ||||||
|  | 	{ | ||||||
|  | 		g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "configs/gamedata/%s.txt", m_pFile); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Initialize parse states */ | 	/* Initialize parse states */ | ||||||
| 	m_IgnoreLevel = 0; | 	m_IgnoreLevel = 0; | ||||||
|  | 	bShouldBeReadingDefault = true; | ||||||
| 	m_ParseState = PSTATE_NONE; | 	m_ParseState = PSTATE_NONE; | ||||||
| 	/* Reset cached data */ | 	/* Reset cached data */ | ||||||
| 	m_pStrings->Reset(); | 	m_pStrings->Reset(); | ||||||
| @ -276,6 +469,11 @@ SendProp *CGameConfig::GetSendProp(const char *key) | |||||||
| 	return pProp; | 	return pProp; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool CGameConfig::GetMemSig(const char *key, void **addr) | ||||||
|  | { | ||||||
|  | 	return sm_trie_retrieve(m_pSigs, key, addr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void CGameConfig::IncRefCount() | void CGameConfig::IncRefCount() | ||||||
| { | { | ||||||
| 	m_RefCount++; | 	m_RefCount++; | ||||||
|  | |||||||
| @ -44,6 +44,7 @@ public: //IGameConfig | |||||||
| 	const char *GetKeyValue(const char *key); | 	const char *GetKeyValue(const char *key); | ||||||
| 	bool GetOffset(const char *key, int *value); | 	bool GetOffset(const char *key, int *value); | ||||||
| 	SendProp *GetSendProp(const char *key); | 	SendProp *GetSendProp(const char *key); | ||||||
|  | 	bool GetMemSig(const char *key, void **addr); | ||||||
| public: | public: | ||||||
| 	void IncRefCount(); | 	void IncRefCount(); | ||||||
| 	unsigned int DecRefCount(); | 	unsigned int DecRefCount(); | ||||||
| @ -53,6 +54,7 @@ private: | |||||||
| 	Trie *m_pOffsets; | 	Trie *m_pOffsets; | ||||||
| 	Trie *m_pProps; | 	Trie *m_pProps; | ||||||
| 	Trie *m_pKeys; | 	Trie *m_pKeys; | ||||||
|  | 	Trie *m_pSigs; | ||||||
| 	unsigned int m_RefCount; | 	unsigned int m_RefCount; | ||||||
| 	/* Parse states */ | 	/* Parse states */ | ||||||
| 	int m_ParseState; | 	int m_ParseState; | ||||||
| @ -61,6 +63,7 @@ private: | |||||||
| 	char m_prop[64]; | 	char m_prop[64]; | ||||||
| 	char m_offset[64]; | 	char m_offset[64]; | ||||||
| 	char m_mod[255]; | 	char m_mod[255]; | ||||||
|  | 	bool bShouldBeReadingDefault; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class GameConfigManager :  | class GameConfigManager :  | ||||||
|  | |||||||
| @ -27,7 +27,7 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #define SMINTERFACE_GAMECONFIG_NAME			"IGameConfigManager" | #define SMINTERFACE_GAMECONFIG_NAME			"IGameConfigManager" | ||||||
| #define SMINTERFACE_GAMECONFIG_VERSION		1 | #define SMINTERFACE_GAMECONFIG_VERSION		2 | ||||||
| 
 | 
 | ||||||
| class SendProp; | class SendProp; | ||||||
| 
 | 
 | ||||||
| @ -63,6 +63,16 @@ namespace SourceMod | |||||||
| 		 * @return				String containing the value, or NULL if not found. | 		 * @return				String containing the value, or NULL if not found. | ||||||
| 		 */ | 		 */ | ||||||
| 		virtual const char *GetKeyValue(const char *key) =0; | 		virtual const char *GetKeyValue(const char *key) =0; | ||||||
|  | 
 | ||||||
|  | 		/**
 | ||||||
|  | 		 * @brief Retrieves a cached memory signature. | ||||||
|  | 		 * | ||||||
|  | 		 * @param key			Name of the signature. | ||||||
|  | 		 * @param addr			Pointer to store the memory address in. | ||||||
|  | 		 * @return				A MemorySignature pointer on success, or NULL  | ||||||
|  | 		 *						if the key was not found. | ||||||
|  | 		 */ | ||||||
|  | 		virtual bool GetMemSig(const char *key, void **addr) =0; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	/**
 | 	/**
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user