core/GameConfigs.cpp
changeset 2901 f5a1cf24f505
parent 2863 d740d9cdf53a
child 2906 33cc9854bd97
     1.1 --- a/core/GameConfigs.cpp	Mon Jan 11 20:09:34 2010 -0800
     1.2 +++ b/core/GameConfigs.cpp	Mon Jan 11 22:46:44 2010 -0800
     1.3 @@ -63,6 +63,9 @@
     1.4  #define PSTATE_GAMEDEFS_CRC				9
     1.5  #define PSTATE_GAMEDEFS_CRC_BINARY		10
     1.6  #define PSTATE_GAMEDEFS_CUSTOM			11
     1.7 +#define PSTATE_GAMEDEFS_ADDRESSES		12
     1.8 +#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS	13
     1.9 +#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ	14
    1.10  
    1.11  #if defined PLATFORM_WINDOWS
    1.12  #define PLATFORM_NAME				"windows"
    1.13 @@ -132,6 +135,7 @@
    1.14  	m_pOffsets = sm_trie_create();
    1.15  	m_pProps = sm_trie_create();
    1.16  	m_pKeys = sm_trie_create();
    1.17 +	m_pAddresses = new KTrie<AddressConf>();
    1.18  	m_pSigs = sm_trie_create();
    1.19  	m_pStrings = new BaseStringTable(512);
    1.20  	m_RefCount = 0;
    1.21 @@ -145,6 +149,7 @@
    1.22  	sm_trie_destroy(m_pOffsets);
    1.23  	sm_trie_destroy(m_pProps);
    1.24  	sm_trie_destroy(m_pKeys);
    1.25 +	delete m_pAddresses;
    1.26  	sm_trie_destroy(m_pSigs);
    1.27  	delete m_pStrings;
    1.28  }
    1.29 @@ -212,6 +217,10 @@
    1.30  				m_ParseState = PSTATE_GAMEDEFS_CRC;
    1.31  				bShouldBeReadingDefault = false;
    1.32  			}
    1.33 +			else if (strcmp(name, "Addresses") == 0)
    1.34 +			{
    1.35 +				m_ParseState = PSTATE_GAMEDEFS_ADDRESSES;
    1.36 +			}
    1.37  			else
    1.38  			{
    1.39  				ITextListener_SMC **pListen = g_GameConfigs.m_customHandlers.retrieve(name);
    1.40 @@ -293,12 +302,41 @@
    1.41  			return m_CustomHandler->ReadSMC_NewSection(states, name);
    1.42  			break;
    1.43  		}
    1.44 +	case PSTATE_GAMEDEFS_ADDRESSES:
    1.45 +		{
    1.46 +			m_Address[0] = '\0';
    1.47 +			m_AddressSignature[0] = '\0';
    1.48 +			m_AddressReadCount = 0;
    1.49 +
    1.50 +			strncopy(m_Address, name, sizeof(m_Address));
    1.51 +			m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS;
    1.52 +
    1.53 +			break;
    1.54 +		}
    1.55 +	case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS:
    1.56 +		{
    1.57 +			if (strcmp(name, PLATFORM_NAME) == 0)
    1.58 +			{
    1.59 +				m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ;
    1.60 +			}
    1.61 +			else
    1.62 +			{
    1.63 +				if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0)
    1.64 +				{
    1.65 +					g_Logger.LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
    1.66 +					g_Logger.LogError("[SM] Unrecognized platform \"%s\"", name);
    1.67 +				}
    1.68 +				m_IgnoreLevel = 1;
    1.69 +			}
    1.70 +			break;
    1.71 +		}
    1.72  	/* No sub-sections allowed:
    1.73  	 case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
    1.74  	 case PSTATE_GAMEDEFS_KEYS:
    1.75  	 case PSTATE_GAMEDEFS_SUPPORTED:
    1.76  	 case PSTATE_GAMEDEFS_SIGNATURES_SIG:
    1.77  	 case PSTATE_GAMEDEFS_CRC_BINARY:
    1.78 +	 case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ:
    1.79  	 */
    1.80  	default:
    1.81  		{
    1.82 @@ -376,6 +414,21 @@
    1.83  				bShouldBeReadingDefault = true;
    1.84  			}
    1.85  		}
    1.86 +	} else if (m_ParseState == PSTATE_GAMEDEFS_ADDRESSES_ADDRESS || m_ParseState == PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ) {
    1.87 +		if (strcmp(key, "read") == 0) {
    1.88 +			int limit = sizeof(m_AddressRead)/sizeof(m_AddressRead[0]);
    1.89 +			if (m_AddressReadCount < limit)
    1.90 +			{
    1.91 +				m_AddressRead[m_AddressReadCount] = atoi(value);
    1.92 +				m_AddressReadCount++;
    1.93 +			}
    1.94 +			else
    1.95 +			{
    1.96 +				g_Logger.LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurFile);
    1.97 +			}
    1.98 +		} else if (strcmp(key, "signature") == 0) {
    1.99 +			strncopy(m_AddressSignature, value, sizeof(m_AddressSignature));
   1.100 +		}
   1.101  	} else if (m_ParseState == PSTATE_GAMEDEFS_CUSTOM) {
   1.102  		return m_CustomHandler->ReadSMC_KeyValue(states, key, value);
   1.103  	}
   1.104 @@ -550,6 +603,36 @@
   1.105  
   1.106  			break;
   1.107  		}
   1.108 +	case PSTATE_GAMEDEFS_ADDRESSES:
   1.109 +		{
   1.110 +			m_ParseState = PSTATE_GAMEDEFS;
   1.111 +			break;
   1.112 +		}
   1.113 +	case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS:
   1.114 +		{
   1.115 +			m_ParseState = PSTATE_GAMEDEFS_ADDRESSES;
   1.116 +
   1.117 +			if (m_Address[0] == '\0')
   1.118 +			{
   1.119 +				g_Logger.LogError("[SM] Address sections must have names (gameconf \"%s\")", m_CurFile);
   1.120 +				break;
   1.121 +			}
   1.122 +			if (m_AddressSignature[0] == '\0')
   1.123 +			{
   1.124 +				g_Logger.LogError("[SM] Address section for \"%s\" did not specify a signature (gameconf \"%s\")", m_Address, m_CurFile);
   1.125 +				break;
   1.126 +			}
   1.127 +
   1.128 +			AddressConf addrConf(m_AddressSignature, sizeof(m_AddressSignature), m_AddressReadCount, m_AddressRead);
   1.129 +			m_pAddresses->replace(m_Address, addrConf);
   1.130 +
   1.131 +			break;
   1.132 +		}
   1.133 +	case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ:
   1.134 +		{
   1.135 +			m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS;
   1.136 +			break;
   1.137 +		}
   1.138  	}
   1.139  
   1.140  	return SMCResult_Continue;
   1.141 @@ -689,6 +772,7 @@
   1.142  	sm_trie_clear(m_pOffsets);
   1.143  	sm_trie_clear(m_pProps);
   1.144  	sm_trie_clear(m_pKeys);
   1.145 +	m_pAddresses->clear();
   1.146  
   1.147  	char path[PLATFORM_MAX_PATH];
   1.148  
   1.149 @@ -837,6 +921,53 @@
   1.150  	return m_pStrings->GetString((int)obj);
   1.151  }
   1.152  
   1.153 +//memory addresses below 0x10000 are automatically considered invalid for dereferencing
   1.154 +#define VALID_MINIMUM_MEMORY_ADDRESS 0x10000
   1.155 +
   1.156 +bool CGameConfig::GetAddress(const char *key, void **retaddr)
   1.157 +{
   1.158 +	AddressConf *addrConf;
   1.159 +
   1.160 +	addrConf = m_pAddresses->retrieve(key);
   1.161 +	if (!addrConf)
   1.162 +	{
   1.163 +		*retaddr = NULL;
   1.164 +		return false;
   1.165 +	}
   1.166 +
   1.167 +	void *addr;
   1.168 +	if (!GetMemSig(addrConf->signatureName, &addr))
   1.169 +	{
   1.170 +		*retaddr = NULL;
   1.171 +		return false;
   1.172 +	}
   1.173 +
   1.174 +	for (int i = 0; i < addrConf->readCount; ++i)
   1.175 +	{
   1.176 +		int offset = addrConf->read[i];
   1.177 +
   1.178 +		//NULLs in the middle of an indirection chain are bad, end NULL is ok
   1.179 +		if (addr ==  NULL || reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
   1.180 +		{
   1.181 +			*retaddr = NULL;
   1.182 +			return false;
   1.183 +		}
   1.184 +		addr = *(reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(addr) + offset));
   1.185 +	}
   1.186 +
   1.187 +	*retaddr = addr;
   1.188 +	return true;
   1.189 +}
   1.190 +
   1.191 +CGameConfig::AddressConf::AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read)
   1.192 +{
   1.193 +	unsigned readLimit = min(readCount, sizeof(this->read) / sizeof(this->read[0]));
   1.194 +
   1.195 +	strncopy(signatureName, sigName, sizeof(signatureName) / sizeof(signatureName[0]));
   1.196 +	this->readCount = readLimit;
   1.197 +	memcpy(&this->read[0], read, sizeof(this->read[0])*readLimit);
   1.198 +}
   1.199 +
   1.200  SendProp *CGameConfig::GetSendProp(const char *key)
   1.201  {
   1.202  	SendProp *pProp;