Seemingly working VersionInfo loading parts. The offset names are now all wrong in the modules. DO NOT USE

develop
Petr Mrázek 2010-08-28 03:57:56 +02:00
parent b33d56354f
commit f2dea86819
11 changed files with 412 additions and 182 deletions

@ -813,6 +813,9 @@
<class name="buildingst"/> <class name="buildingst"/>
</VTable> </VTable>
<Offsets> <Offsets>
<Address name="WORLD" description="A huge object that many things in DF are part of. Contains the whole game and can be used as a base
for many of the addresses." />
<HexValue name="sdasdasdizeof" description="The total size in bytes." />
<Group name="vector" description="An STL vector."> <Group name="vector" description="An STL vector.">
<HexValue name="sizeof" description="The total size in bytes." /> <HexValue name="sizeof" description="The total size in bytes." />
<Offset name="start" description="The offset where the actual start/end/alloc_end triplet is." /> <Offset name="start" description="The offset where the actual start/end/alloc_end triplet is." />
@ -1407,7 +1410,7 @@
<!-- Windows logo by Microsoft --> <!-- Windows logo by Microsoft -->
<!-- Tux logo by the Linux guys :) --> <!-- Tux logo by the Linux guys :) -->
<Version version="v0.31.05 linux" os="linux" base="DF2010"> <Version name="v0.31.05 linux" os="linux" base="DF2010">
<MD5 value="fea3801a26538b1741f3cc9294139fca" /> <MD5 value="fea3801a26538b1741f3cc9294139fca" />
<Offsets> <Offsets>
<Address name="WORLD" value="0x92C60E0" valid="false" /> <Address name="WORLD" value="0x92C60E0" valid="false" />
@ -1603,7 +1606,7 @@
</Group> </Group>
</Offsets> </Offsets>
</Version> </Version>
<Version version="v0.31.06 linux" os="linux" base="v0.31.05 linux" rebase="-0x20E0"> <Version name="v0.31.06 linux" os="linux" base="v0.31.05 linux" rebase="-0x20E0">
<MD5 value="13a1c19e8f59b74e307e094e2a0f28c3" /> <MD5 value="13a1c19e8f59b74e307e094e2a0f28c3" />
<Offsets> <Offsets>
<Address name="WORLD" value="0x92C4000" /> <Address name="WORLD" value="0x92C4000" />
@ -1618,18 +1621,18 @@
0x92d7a10 0x92d7a10
</Offsets> </Offsets>
</Version> </Version>
<Version version="v0.31.07 linux" os="linux" base="v0.31.06 linux" rebase="0x2000"> <Version name="v0.31.07 linux" os="linux" base="v0.31.06 linux" rebase="0x2000">
<MD5 value="b31979551782e89c049b11db8d2d86d7" /> <MD5 value="b31979551782e89c049b11db8d2d86d7" />
</Version> </Version>
<Version version="v0.31.08 linux" os="linux" base="v0.31.07 linux"> <Version name="v0.31.08 linux" os="linux" base="v0.31.07 linux">
<MD5 value="e37750890350d7b9d8203879aff8fa5c" /> <MD5 value="e37750890350d7b9d8203879aff8fa5c" />
</Version> </Version>
<Version version="v0.31.09 linux" os="linux" base="v0.31.08 linux" rebase="0x11000"> <Version name="v0.31.09 linux" os="linux" base="v0.31.08 linux" rebase="0x11000">
<!-- TODO: fix creature offsets --> <!-- TODO: fix creature offsets -->
<!-- TODO: small offsets added all over the place, investigate --> <!-- TODO: small offsets added all over the place, investigate -->
<MD5 value="4f1f988bc1b425d4193d3d8b7b0579a5" /> <MD5 value="4f1f988bc1b425d4193d3d8b7b0579a5" />
</Version> </Version>
<Version version="v0.31.10 linux" os="linux" base="v0.31.09 linux"> <Version name="v0.31.10 linux" os="linux" base="v0.31.09 linux">
<MD5 value="3e7bea269018a6fb88ef53715685aa64" /> <MD5 value="3e7bea269018a6fb88ef53715685aa64" />
<Offsets> <Offsets>
<Group name="Buildings"> <Group name="Buildings">
@ -1647,17 +1650,19 @@
<multiclass name="building_siegeenginest" typeoffset="0xC0" /> <multiclass name="building_siegeenginest" typeoffset="0xC0" />
</VTable> </VTable>
</Version> </Version>
<Version version="v0.31.11 linux" os="linux" base="v0.31.10 linux" rebase="0x1D020"> <Version name="v0.31.11 linux" os="linux" base="v0.31.10 linux" rebase="0x1D020">
<!-- BIG rebase, possible broken stuff --> <!-- BIG rebase, possible broken stuff -->
<MD5 value="7b04ad536b8b657588ac209a7f95e1d1" /> <MD5 value="7b04ad536b8b657588ac209a7f95e1d1" />
<Offsets> <Offsets>
<Address name="window_x" value="0x8cf7a58" /> VERIFIED <Group name="Position">
<Address name="window_y" value="0x8cf7a5C" /> VERIFIED <Address name="window_x" value="0x8cf7a58" /> VERIFIED
<Address name="window_z" value="0x8cf7a60" /> VERIFIED <Address name="window_y" value="0x8cf7a5C" /> VERIFIED
<Address name="cursor_xyz" value="0x8b3b328" /> VERIFIED <Address name="window_z" value="0x8cf7a60" /> VERIFIED
<Address name="cursor_xyz" value="0x8b3b328" /> VERIFIED
</Group>
</Offsets> </Offsets>
</Version> </Version>
<Version version="v0.31.12 linux" os="linux" base="v0.31.11 linux" rebase="-0x1000"> <Version name="v0.31.12 linux" os="linux" base="v0.31.11 linux" rebase="-0x1000">
<MD5 value="e79cead03187ecb692961b316b7cdcd4" /> <MD5 value="e79cead03187ecb692961b316b7cdcd4" />
</Version> </Version>
</DFHack> </DFHack>

@ -27,10 +27,10 @@ include_directories (${CMAKE_SOURCE_DIR}/library/depends/argstream/)
include_directories (${CMAKE_SOURCE_DIR}/library/private/) include_directories (${CMAKE_SOURCE_DIR}/library/private/)
SET(PROJECT_HDRS SET(PROJECT_HDRS
private/VersionInfoFactory.h
private/ContextShared.h private/ContextShared.h
private/Internal.h private/Internal.h
include/dfhack/DFError.h include/dfhack/DFError.h
include/dfhack/VersionInfoFactory.h
include/dfhack/VersionInfo.h include/dfhack/VersionInfo.h
include/dfhack/DFProcessEnumerator.h include/dfhack/DFProcessEnumerator.h
include/dfhack/DFProcess.h include/dfhack/DFProcess.h

@ -23,8 +23,8 @@ distribution.
*/ */
#include "Internal.h" #include "Internal.h"
#include "VersionInfoFactory.h"
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/DFProcess.h" #include "dfhack/DFProcess.h"
#include "dfhack/DFProcessEnumerator.h" #include "dfhack/DFProcessEnumerator.h"
#include "dfhack/DFError.h" #include "dfhack/DFError.h"

@ -120,6 +120,7 @@ bool NormalProcess::Private::validate(char * exe_file,uint32_t pid, char * memFi
{ {
try try
{ {
//cout << hash << " ?= " << (*it)->getMD5() << endl;
if(hash == (*it)->getMD5()) // are the md5 hashes the same? if(hash == (*it)->getMD5()) // are the md5 hashes the same?
{ {
VersionInfo * m = *it; VersionInfo * m = *it;

@ -23,8 +23,8 @@ distribution.
*/ */
#include "Internal.h" #include "Internal.h"
#include "VersionInfoFactory.h"
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/DFProcessEnumerator.h" #include "dfhack/DFProcessEnumerator.h"
#include "dfhack/DFProcess.h" #include "dfhack/DFProcess.h"
#include "dfhack/VersionInfo.h" #include "dfhack/VersionInfo.h"

@ -87,132 +87,195 @@ namespace DFHack
*/ */
namespace DFHack namespace DFHack
{ {
typedef pair <bool, uint32_t> nullableUint32;
typedef map <string, nullableUint32 >::iterator uint32_Iter;
typedef pair <bool, int32_t> nullableInt32;
typedef map <string, nullableInt32 >::iterator int32_Iter;
typedef pair <bool, string> nullableString;
typedef map <string, nullableString >::iterator strings_Iter;
typedef map <string, OffsetGroup *>::iterator groups_Iter;
class OffsetGroupPrivate class OffsetGroupPrivate
{ {
public: public:
map <string, uint32_t> addresses; map <string, nullableUint32 > addresses;
map <string, int32_t> offsets; map <string, nullableUint32 > hexvals;
map <string, uint32_t> hexvals; map <string, nullableInt32 > offsets;
map <string, string> strings; map <string, nullableString > strings;
map <string, OffsetGroup> groups; map <string, OffsetGroup *> groups;
}; };
} }
void OffsetGroup::createOffset(const string & key)
{
OGd->offsets[key] = nullableInt32(false, 0);
}
void OffsetGroup::createAddress(const string & key)
{
OGd->addresses[key] = nullableUint32(false, 0);
}
void OffsetGroup::createHexValue(const string & key)
{
OGd->hexvals[key] = nullableUint32(false, 0);
}
void OffsetGroup::createString(const string & key)
{
OGd->strings[key] = nullableString(false, std::string());
}
void OffsetGroup::setOffset (const string & key, const string & value) void OffsetGroup::setOffset (const string & key, const string & value)
{ {
int32_t offset = strtol(value.c_str(), NULL, 16); int32_Iter it;
d->offsets[key] = offset; if((it = OGd->offsets.find(key)) != OGd->offsets.end())
{
int32_t offset = strtol(value.c_str(), NULL, 16);
(*it).second.second = offset;
(*it).second.first = true;
}
else throw Error::MissingMemoryDefinition("offset", key);
} }
void OffsetGroup::setAddress (const string & key, const string & value) void OffsetGroup::setAddress (const string & key, const string & value)
{ {
uint32_t address = strtol(value.c_str(), NULL, 16); uint32_Iter it;
d->addresses[key] = address; if((it = OGd->addresses.find(key)) != OGd->addresses.end())
{
int32_t address = strtol(value.c_str(), NULL, 16);
(*it).second.second = address;
(*it).second.first = true;
}
else throw Error::MissingMemoryDefinition("address", key);
} }
void OffsetGroup::setHexValue (const string & key, const string & value) void OffsetGroup::setHexValue (const string & key, const string & value)
{ {
uint32_t hexval = strtol(value.c_str(), NULL, 16); uint32_Iter it;
d->hexvals[key] = hexval; if((it = OGd->hexvals.find(key)) != OGd->hexvals.end())
{
(*it).second.second = strtol(value.c_str(), NULL, 16);
(*it).second.first = true;
}
else throw Error::MissingMemoryDefinition("hexvalue", key);
} }
void OffsetGroup::setString (const string & key, const string & value) void OffsetGroup::setString (const string & key, const string & value)
{ {
d->strings[key] = value; strings_Iter it;
if((it = OGd->strings.find(key)) != OGd->strings.end())
{
(*it).second.second = value;
(*it).second.first = true;
}
else throw Error::MissingMemoryDefinition("string", key);
} }
// Get named address // Get named address
uint32_t OffsetGroup::getAddress (const char *key) uint32_t OffsetGroup::getAddress (const string & key)
{ {
map <string, uint32_t>::iterator iter = d->addresses.find(key); uint32_Iter iter = OGd->addresses.find(key);
if(iter != d->addresses.end()) if(iter != OGd->addresses.end())
{ {
return (*iter).second; if((*iter).second.first)
return (*iter).second.second;
throw Error::UnsetMemoryDefinition("address", key);
} }
throw Error::MissingMemoryDefinition("address", key); throw Error::MissingMemoryDefinition("address", key);
} }
// Get named offset // Get named offset
int32_t OffsetGroup::getOffset (const char *key) int32_t OffsetGroup::getOffset (const string & key)
{ {
map <string, int32_t>::iterator iter = d->offsets.find(key); int32_Iter iter = OGd->offsets.find(key);
if(iter != d->offsets.end()) if(iter != OGd->offsets.end())
{ {
return (*iter).second; if((*iter).second.first)
return (*iter).second.second;
throw Error::UnsetMemoryDefinition("offset", key);
} }
throw Error::MissingMemoryDefinition("offset", key); throw Error::MissingMemoryDefinition("offset", key);
} }
// Get named numerical value // Get named numerical value
uint32_t OffsetGroup::getHexValue (const char *key) uint32_t OffsetGroup::getHexValue (const string & key)
{ {
map <string, uint32_t>::iterator iter = d->hexvals.find(key); uint32_Iter iter = OGd->hexvals.find(key);
if(iter != d->hexvals.end()) if(iter != OGd->hexvals.end())
{ {
return (*iter).second; if((*iter).second.first)
return (*iter).second.second;
throw Error::UnsetMemoryDefinition("hexvalue", key);
} }
throw Error::MissingMemoryDefinition("hexvalue", key); throw Error::MissingMemoryDefinition("hexvalue", key);
} }
// Get named string
// Get named address std::string OffsetGroup::getString (const string &key)
uint32_t OffsetGroup::getAddress (const string &key)
{ {
map <string, uint32_t>::iterator iter = d->addresses.find(key); strings_Iter iter = OGd->strings.find(key);
if(iter != OGd->strings.end())
if(iter != d->addresses.end())
{ {
return (*iter).second; if((*iter).second.first)
return (*iter).second.second;
throw Error::UnsetMemoryDefinition("string", key);
} }
throw Error::MissingMemoryDefinition("address", key.c_str()); throw Error::MissingMemoryDefinition("string", key);
} }
OffsetGroup * OffsetGroup::getGroup(const std::string &name)
// Get named offset
int32_t OffsetGroup::getOffset (const string &key)
{ {
map <string, int32_t>::iterator iter = d->offsets.find(key); groups_Iter iter = OGd->groups.find(name);
if(iter != d->offsets.end()) if(iter != OGd->groups.end())
{ return ((*iter).second);
return (*iter).second; return 0;
}
throw Error::MissingMemoryDefinition("offset", key.c_str());
} }
OffsetGroup * OffsetGroup::createGroup(const std::string &name)
{
OffsetGroup * ret = getGroup(name);
if(ret)
return ret;
ret = new OffsetGroup();
OGd->groups[name] = ret;
return ret;
}
// Get named numerical value void OffsetGroup::RebaseAddresses(int32_t offset)
uint32_t OffsetGroup::getHexValue (const string &key)
{ {
map <string, uint32_t>::iterator iter = d->hexvals.find(key); for(uint32_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++)
if(iter != d->hexvals.end()) {
if(iter->second.first)
OGd->addresses[iter->first].second = iter->second.second + offset;
}
for(groups_Iter iter = OGd->groups.begin(); iter != OGd->groups.end(); iter++)
{ {
return (*iter).second; (*iter).second->RebaseAddresses(offset);
} }
throw Error::MissingMemoryDefinition("hexvalue", key.c_str());
} }
OffsetGroup::OffsetGroup()
{
OGd = new OffsetGroupPrivate();
}
// Get named string OffsetGroup::~OffsetGroup()
std::string OffsetGroup::getString (const string &key)
{ {
map <string, string>::iterator iter = d->strings.find(key); for(groups_Iter it = OGd->groups.begin();it != OGd->groups.end();it++)
if(iter != d->strings.end())
{ {
return (*iter).second; delete (*it).second;
} }
throw Error::MissingMemoryDefinition("string", key.c_str()); OGd->groups.clear();
delete OGd;
} }
/* /*
* Private data * Private data
*/ */
@ -221,11 +284,6 @@ namespace DFHack
class VersionInfoPrivate class VersionInfoPrivate
{ {
public: public:
map <string, uint32_t> addresses;
map <string, int32_t> offsets;
map <string, uint32_t> hexvals;
map <string, string> strings;
vector<string> professions; vector<string> professions;
vector<string> jobs; vector<string> jobs;
vector<string> skills; vector<string> skills;
@ -277,16 +335,26 @@ VersionInfo::VersionInfo(const VersionInfo &old)
copy(&old); copy(&old);
} }
void OffsetGroup::copy(const OffsetGroup * old)
{
OGd->addresses = old->OGd->addresses;
OGd->offsets = old->OGd->offsets;
OGd->hexvals = old->OGd->hexvals;
OGd->strings = old->OGd->strings;
for(groups_Iter it = old->OGd->groups.begin(); it != old->OGd->groups.end(); it++)
{
OffsetGroup * ogn = new OffsetGroup();
ogn->copy((*it).second);
OGd->groups[(*it).first] = ogn;
}
}
void VersionInfo::copy(const VersionInfo * old) void VersionInfo::copy(const VersionInfo * old)
{ {
d->version = old->d->version; d->version = old->d->version;
d->OS = old->d->OS; d->OS = old->d->OS;
d->md5 = old->d->md5; d->md5 = old->d->md5;
d->PE_timestamp = old->d->PE_timestamp; d->PE_timestamp = old->d->PE_timestamp;
d->addresses = old->d->addresses;
d->offsets = old->d->offsets;
d->hexvals = old->d->hexvals;
d->strings = old->d->strings;
d->base = old->d->base; d->base = old->d->base;
//d->classes = old.d->classes; //d->classes = old.d->classes;
for(uint32_t i = 0; i < old->d->classes.size(); i++) for(uint32_t i = 0; i < old->d->classes.size(); i++)
@ -303,6 +371,7 @@ void VersionInfo::copy(const VersionInfo * old)
d->labors = old->d->labors; d->labors = old->d->labors;
d->levels = old->d->levels; d->levels = old->d->levels;
d->moods = old->d->moods; d->moods = old->d->moods;
OffsetGroup::copy(reinterpret_cast<const OffsetGroup *>(old));
} }
void VersionInfo::setParentProcess(Process * _p) void VersionInfo::setParentProcess(Process * _p)
@ -677,12 +746,7 @@ const vector<string> * VersionInfo::getClassIDMapping()
// change base of all addresses // change base of all addresses
void VersionInfo::RebaseAddresses(const int32_t new_base) void VersionInfo::RebaseAddresses(const int32_t new_base)
{ {
map<string, uint32_t>::iterator iter; OffsetGroup::RebaseAddresses(- (int32_t)d->base + new_base);
int32_t rebase = - (int32_t)d->base + new_base;
for(iter = d->addresses.begin(); iter != d->addresses.end(); iter++)
{
d->addresses[iter->first] = iter->second + rebase;
}
} }
@ -841,25 +905,27 @@ std::string VersionInfo::PrintOffsets()
ss << " UNKNOWN" << endl; ss << " UNKNOWN" << endl;
} }
ss << "<Offsets>" << endl; ss << "<Offsets>" << endl;
/*
map<string,uint32_t>::const_iterator iter; map<string,uint32_t>::const_iterator iter;
for(iter = d->addresses.begin(); iter != d->addresses.end(); iter++) for(iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++)
{ {
ss << " <Address name=\"" << (*iter).first << "\" value=\"" << hex << "0x" << (*iter).second << "\" />" << endl; ss << " <Address name=\"" << (*iter).first << "\" value=\"" << hex << "0x" << (*iter).second << "\" />" << endl;
} }
map<string,int32_t>::const_iterator iter2; map<string,int32_t>::const_iterator iter2;
for(iter2 = d->offsets.begin(); iter2 != d->offsets.end(); iter2++) for(iter2 = OGd->offsets.begin(); iter2 != OGd->offsets.end(); iter2++)
{ {
ss << " <Offset name=\"" << (*iter2).first << "\" value=\"" << hex << "0x" << (*iter2).second <<"\" />" << endl; ss << " <Offset name=\"" << (*iter2).first << "\" value=\"" << hex << "0x" << (*iter2).second <<"\" />" << endl;
} }
for(iter = d->hexvals.begin(); iter != d->hexvals.end(); iter++) for(iter = OGd->hexvals.begin(); iter != OGd->hexvals.end(); iter++)
{ {
ss << " <HexValue name=\"" << (*iter).first << "\" value=\"" << hex << "0x" << (*iter).second <<"\" />" << endl; ss << " <HexValue name=\"" << (*iter).first << "\" value=\"" << hex << "0x" << (*iter).second <<"\" />" << endl;
} }
map<string,string>::const_iterator iter3; map<string,string>::const_iterator iter3;
for(iter3 = d->strings.begin(); iter3 != d->strings.end(); iter3++) for(iter3 = OGd->strings.begin(); iter3 != OGd->strings.end(); iter3++)
{ {
ss << " <String name=\"" << (*iter3).first << "\" value=\"" << (*iter3).second <<"\" />" << endl; ss << " <String name=\"" << (*iter3).first << "\" value=\"" << (*iter3).second <<"\" />" << endl;
} }
*/
ss << "</Offsets>" << endl; ss << "</Offsets>" << endl;
ss << "</Version>" << endl; ss << "</Version>" << endl;
return ss.str(); return ss.str();

@ -23,10 +23,11 @@ distribution.
*/ */
#include "Internal.h" #include "Internal.h"
#include "VersionInfoFactory.h"
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/VersionInfo.h" #include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h" #include "dfhack/DFError.h"
#include <algorithm>
using namespace DFHack; using namespace DFHack;
@ -94,6 +95,167 @@ void VersionInfoFactory::ParseVTable(TiXmlElement* vtable, VersionInfo* mem)
} }
} }
// FIXME: this is ripe for replacement with a more generic approach
void VersionInfoFactory::ParseOffsets(TiXmlElement * parent, VersionInfo* target, bool initial)
{
// we parse the groups iteratively instead of recursively
// breadcrubs acts like a makeshift stack
// first pair entry stores the current element of that level
// second pair entry the group object from OffsetGroup
typedef pair < TiXmlElement *, OffsetGroup * > groupPair;
vector< groupPair > breadcrumbs;
{
TiXmlElement* pEntry;
// we get the <Offsets>, look at the children
pEntry = parent->FirstChildElement();
if(!pEntry)
return;
OffsetGroup * currentGroup = reinterpret_cast<OffsetGroup *> (target);
breadcrumbs.push_back(groupPair(pEntry,currentGroup));
}
// work variables
OffsetGroup * currentGroup = 0;
TiXmlElement * currentElem = 0;
cerr << "<Offsets>"<< endl;
while(1)
{
// get current work variables
currentElem = breadcrumbs.back().first;
currentGroup = breadcrumbs.back().second;
// we reached the end of the current group?
if(!currentElem)
{
// go one level up
breadcrumbs.pop_back();
// exit if no more work
if(breadcrumbs.empty())
{
break;
}
else
{
cerr << "</group>" << endl;
continue;
}
}
if(!currentGroup)
{
groupPair & gp = breadcrumbs.back();
gp.first = gp.first->NextSiblingElement();
continue;
}
// skip non-elements
if (currentElem->Type() != TiXmlNode::ELEMENT)
{
groupPair & gp = breadcrumbs.back();
gp.first = gp.first->NextSiblingElement();
continue;
}
// we have a valid current element and current group
// get properties
string type = currentElem->Value();
std::transform(type.begin(), type.end(), type.begin(), ::tolower);
const char *cstr_name = currentElem->Attribute("name");
if(!cstr_name)
{
// ERROR, missing attribute
}
// evaluate elements
const char *cstr_value = currentElem->Attribute("value");
if(type == "group")
{
// FIXME: possibly use setGroup always, with the initial flag as parameter?
// create or get group
OffsetGroup * og;
if(initial)
og = currentGroup->createGroup(cstr_name);
else
og = currentGroup->getGroup(cstr_name);
cerr << "<group name=\"" << cstr_name << "\">" << endl;
// advance this level to the next element
groupPair & gp = breadcrumbs.back();
gp.first = gp.first->NextSiblingElement();
// add a new level that will be processed next
breadcrumbs.push_back(groupPair(currentElem->FirstChildElement(), og));
continue;
}
else if(type == "address")
{
if(initial)
{
currentGroup->createAddress(cstr_name);
}
else if(cstr_value)
{
currentGroup->setAddress(cstr_name, cstr_value);
}
else
{
// ERROR, missing attribute
}
}
else if(type == "offset")
{
if(initial)
{
currentGroup->createOffset(cstr_name);
}
else if(cstr_value)
{
currentGroup->setOffset(cstr_name, cstr_value);
}
else
{
// ERROR, missing attribute
}
}
else if(type == "string")
{
if(initial)
{
currentGroup->createString(cstr_name);
}
else if(cstr_value)
{
currentGroup->setString(cstr_name, cstr_value);
}
else
{
// ERROR, missing attribute
}
}
else if(type == "hexvalue")
{
if(initial)
{
currentGroup->createHexValue(cstr_name);
}
else if(cstr_value)
{
currentGroup->setHexValue(cstr_name, cstr_value);
}
else
{
// ERROR, missing attribute
}
}
// advance to next element
groupPair & gp = breadcrumbs.back();
gp.first = gp.first->NextSiblingElement();
continue;
}
cerr << "</Offsets>"<< endl;
}
void VersionInfoFactory::ParseBase (TiXmlElement* entry, VersionInfo* mem) void VersionInfoFactory::ParseBase (TiXmlElement* entry, VersionInfo* mem)
{ {
TiXmlElement* pElement; TiXmlElement* pElement;
@ -121,12 +283,12 @@ void VersionInfoFactory::ParseBase (TiXmlElement* entry, VersionInfo* mem)
else if(type == "Offsets") else if(type == "Offsets")
{ {
// we don't care about the descriptions here, do nothing // we don't care about the descriptions here, do nothing
//ParseBaseOffsets(pMemEntry, mem); ParseOffsets(pElement, mem, true);
continue; continue;
} }
else if (type == "Professions") else if (type == "Professions")
{ {
pElement2nd = entry->FirstChildElement("Profession")->ToElement(); pElement2nd = entry->FirstChildElement("Profession");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Profession")) for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Profession"))
{ {
const char * id = pElement2nd->Attribute("id"); const char * id = pElement2nd->Attribute("id");
@ -145,7 +307,7 @@ void VersionInfoFactory::ParseBase (TiXmlElement* entry, VersionInfo* mem)
} }
else if (type == "Jobs") else if (type == "Jobs")
{ {
pElement2nd = entry->FirstChildElement("Job")->ToElement(); pElement2nd = entry->FirstChildElement("Job");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Job")) for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Job"))
{ {
const char * id = pElement2nd->Attribute("id"); const char * id = pElement2nd->Attribute("id");
@ -163,7 +325,7 @@ void VersionInfoFactory::ParseBase (TiXmlElement* entry, VersionInfo* mem)
} }
else if (type == "Skills") else if (type == "Skills")
{ {
pElement2nd = entry->FirstChildElement("Skill")->ToElement(); pElement2nd = entry->FirstChildElement("Skill");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Skill")) for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Skill"))
{ {
const char * id = pElement2nd->Attribute("id"); const char * id = pElement2nd->Attribute("id");
@ -181,7 +343,7 @@ void VersionInfoFactory::ParseBase (TiXmlElement* entry, VersionInfo* mem)
} }
else if (type == "Traits") else if (type == "Traits")
{ {
pElement2nd = entry->FirstChildElement("Trait")->ToElement(); pElement2nd = entry->FirstChildElement("Trait");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Trait")) for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Trait"))
{ {
const char * id = pElement2nd->Attribute("id"); const char * id = pElement2nd->Attribute("id");
@ -205,7 +367,7 @@ void VersionInfoFactory::ParseBase (TiXmlElement* entry, VersionInfo* mem)
} }
else if (type == "Labors") else if (type == "Labors")
{ {
pElement2nd = entry->FirstChildElement("Labor")->ToElement(); pElement2nd = entry->FirstChildElement("Labor");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Labor")) for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Labor"))
{ {
const char * id = pElement2nd->Attribute("id"); const char * id = pElement2nd->Attribute("id");
@ -223,7 +385,7 @@ void VersionInfoFactory::ParseBase (TiXmlElement* entry, VersionInfo* mem)
} }
else if (type == "Levels") else if (type == "Levels")
{ {
pElement2nd = entry->FirstChildElement("Level")->ToElement(); pElement2nd = entry->FirstChildElement("Level");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Level")) for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Level"))
{ {
const char * id = pElement2nd->Attribute("id"); const char * id = pElement2nd->Attribute("id");
@ -242,7 +404,7 @@ void VersionInfoFactory::ParseBase (TiXmlElement* entry, VersionInfo* mem)
} }
else if (type == "Moods") else if (type == "Moods")
{ {
pElement2nd = entry->FirstChildElement("Mood")->ToElement(); pElement2nd = entry->FirstChildElement("Mood");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Mood")) for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Mood"))
{ {
const char * id = pElement2nd->Attribute("id"); const char * id = pElement2nd->Attribute("id");
@ -276,7 +438,6 @@ void VersionInfoFactory::EvalVersion(string base, VersionInfo * mem)
VersionInfo * newmem = new VersionInfo(); VersionInfo * newmem = new VersionInfo();
ParseVersion(desc.first, newmem); ParseVersion(desc.first, newmem);
desc.second = newmem; desc.second = newmem;
versions.push_back(newmem);
} }
mem->copy(desc.second); mem->copy(desc.second);
} }
@ -345,29 +506,7 @@ void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem)
} }
else if(type == "Offsets") else if(type == "Offsets")
{ {
/* ParseOffsets(pMemEntry, mem);
if (type == "HexValue")
{
mem->setHexValue(name, value);
}
else if (type == "Address")
{
mem->setAddress(name, value);
}
else if (type == "Offset")
{
mem->setOffset(name, value);
}
else if (type == "String")
{
mem->setString(name, value);
}
else
{
throw Error::MemoryXmlUnknownType(type.c_str());
}
*/
//ParseOffsets(pMemEntry, mem);
continue; continue;
} }
else if (type == "MD5") else if (type == "MD5")
@ -382,7 +521,7 @@ void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem)
const char *cstr_value = pMemEntry->Attribute("value"); const char *cstr_value = pMemEntry->Attribute("value");
if(!cstr_value) if(!cstr_value)
throw Error::MemoryXmlUnderspecifiedEntry(cstr_name); throw Error::MemoryXmlUnderspecifiedEntry(cstr_name);
mem->setPE(atol(cstr_value)); mem->setPE(strtol(cstr_value, 0, 16));
} }
} // for } // for
} // method } // method
@ -446,6 +585,7 @@ bool VersionInfoFactory::loadFile(string path_to_xml)
{ {
string str_name = name; string str_name = name;
VersionInfo *base = new VersionInfo(); VersionInfo *base = new VersionInfo();
mem = new VersionInfo();
ParseBase( pMemInfo , mem ); ParseBase( pMemInfo , mem );
knownVersions[str_name] = v_descr (pMemInfo, mem); knownVersions[str_name] = v_descr (pMemInfo, mem);
} }

@ -78,10 +78,10 @@ namespace DFHack
class DFHACK_EXPORT MissingMemoryDefinition : public std::exception class DFHACK_EXPORT MissingMemoryDefinition : public std::exception
{ {
public: public:
MissingMemoryDefinition(const char* _type, const char* _key) : type(_type), key(_key) MissingMemoryDefinition(const char* _type, const std::string _key) : type(_type), key(_key)
{ {
std::stringstream s; std::stringstream s;
s << "memory definition missing: type " << type << " key " << key; s << "memory object not declared: type " << type << " key " << key;
full = s.str(); full = s.str();
} }
// Used by functios using integer keys, such as getTrait // Used by functios using integer keys, such as getTrait
@ -92,24 +92,44 @@ namespace DFHack
key = s1.str(); key = s1.str();
std::stringstream s; std::stringstream s;
s << "memory definition missing: type " << type << " key " << key; s << "memory object not declared: type " << type << " key " << key;
full = s.str(); full = s.str();
} }
virtual ~MissingMemoryDefinition() throw(){}; virtual ~MissingMemoryDefinition() throw(){};
// (perhaps it should be an enum, but this is intended for easy printing/logging) std::string full;
// type can be any of the following: const std::string type;
// std::string key;
// address
// offset virtual const char* what() const throw()
// hexvalue {
// string return full.c_str();
// profession }
// job };
// skill
// trait // a call to DFHack::mem_info::get* failed
// traitname class DFHACK_EXPORT UnsetMemoryDefinition : public std::exception
// labor {
public:
UnsetMemoryDefinition(const char* _type, const std::string _key) : type(_type), key(_key)
{
std::stringstream s;
s << "memory object not set: type " << type << " key " << key;
full = s.str();
}
// Used by functios using integer keys, such as getTrait
UnsetMemoryDefinition(const char* _type, uint32_t _key) : type(_type)
{
std::stringstream s1;
s1 << _key;
key = s1.str();
std::stringstream s;
s << "memory object not set: type " << type << " key " << key;
full = s.str();
}
virtual ~UnsetMemoryDefinition() throw(){};
std::string full; std::string full;
const std::string type; const std::string type;
std::string key; std::string key;

@ -39,38 +39,42 @@ namespace DFHack
struct t_class; struct t_class;
class VersionInfoPrivate; class VersionInfoPrivate;
class OffsetGroupPrivate; class OffsetGroupPrivate;
/*
* Offset Group
*/
class DFHACK_EXPORT OffsetGroup class DFHACK_EXPORT OffsetGroup
{ {
protected: protected:
OffsetGroupPrivate * d; OffsetGroupPrivate * OGd;
public: public:
int32_t getOffset (const std::string&); OffsetGroup();
uint32_t getAddress (const std::string&); ~OffsetGroup();
uint32_t getHexValue (const std::string&);
std::string getString (const std::string&); void copy(const OffsetGroup * old); // recursive
void RebaseAddresses( int32_t offset ); // recursive
int32_t getOffset (const char *);
uint32_t getAddress (const char *); void createOffset (const std::string & key);
uint32_t getHexValue (const char *); void createAddress (const std::string & key);
std::string getString (const char *); void createHexValue (const std::string & key);
void createString (const std::string & key);
void setOffset (const std::string &, const int32_t); OffsetGroup * createGroup ( const std::string & name );
void setAddress (const std::string &, const uint32_t);
void setHexValue (const std::string &, const uint32_t); int32_t getOffset (const std::string & key);
uint32_t getAddress (const std::string & key);
void setOffset (const std::string &, const char *); uint32_t getHexValue (const std::string & key);
void setAddress (const std::string &, const char *); std::string getString (const std::string & key);
void setHexValue (const std::string &, const char *); OffsetGroup * getGroup ( const std::string & name );
void setString (const std::string &, const char *);
void setOffset (const std::string & key, const std::string & value);
void setOffset (const std::string &, const std::string &); void setAddress (const std::string & key, const std::string & value);
void setAddress (const std::string &, const std::string &); void setHexValue (const std::string & key, const std::string & value);
void setHexValue (const std::string &, const std::string &); void setString (const std::string & key, const std::string & value);
void setString (const std::string &, const std::string &);
OffsetGroup & getGroup (const std::string name);
}; };
/*
* Version Info
*/
class DFHACK_EXPORT VersionInfo : public OffsetGroup class DFHACK_EXPORT VersionInfo : public OffsetGroup
{ {
private: private:

@ -26,12 +26,13 @@ distribution.
#define MEMINFO_MANAGER_H_INCLUDED #define MEMINFO_MANAGER_H_INCLUDED
#include "dfhack/DFPragma.h" #include "dfhack/DFPragma.h"
#include "dfhack/DFExport.h"
class TiXmlElement; class TiXmlElement;
namespace DFHack namespace DFHack
{ {
class VersionInfo; class VersionInfo;
class VersionInfoFactory class DFHACK_EXPORT VersionInfoFactory
{ {
friend class ProcessEnumerator; friend class ProcessEnumerator;
public: public:
@ -47,6 +48,8 @@ namespace DFHack
void ParseVersion (TiXmlElement* version, VersionInfo* mem); void ParseVersion (TiXmlElement* version, VersionInfo* mem);
// copy version 'base' to 'target' or throw // copy version 'base' to 'target' or throw
void EvalVersion(std::string base, VersionInfo* target); void EvalVersion(std::string base, VersionInfo* target);
void ParseOffsets(TiXmlElement* elem, VersionInfo* target, bool initial = false);
bool error; bool error;
typedef std::pair < TiXmlElement *, VersionInfo *> v_descr; typedef std::pair < TiXmlElement *, VersionInfo *> v_descr;
std::map <std::string , v_descr > knownVersions; std::map <std::string , v_descr > knownVersions;

@ -8,31 +8,22 @@
using namespace std; using namespace std;
#include <DFHack.h> #include <DFHack.h>
#include <dfhack/VersionInfoFactory.h>
using namespace DFHack; using namespace DFHack;
int main (int numargs, const char ** args) int main (int numargs, const char ** args)
{ {
DFHack::ContextManager DFMgr("Memory.xml");
DFHack::Context * DF; DFHack::VersionInfoFactory * VIF = new DFHack::VersionInfoFactory("Memory.xml");
try for(int i = 0; i < VIF->versions.size(); i++)
{
DF = DFMgr.getSingleContext();
DF->Attach();
}
catch (exception& e)
{ {
cerr << e.what() << endl; cout << VIF->versions[i]->PrintOffsets();
#ifndef LINUX_BUILD
cin.ignore();
#endif
return 1;
} }
VersionInfo * minfo = DF->getMemoryInfo();
if(minfo)
cout << minfo->PrintOffsets();
#ifndef LINUX_BUILD #ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl; cout << "Done. Press any key to continue" << endl;
cin.ignore(); cin.ignore();
#endif #endif
delete VIF;
return 0; return 0;
} }