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;