Merge branch 'master', remote branch 'peterix/master'

develop
Erik Youngren 2010-09-18 10:39:21 -07:00
commit e9a7026342
83 changed files with 4402 additions and 2363 deletions

1
.gitignore vendored

@ -9,6 +9,7 @@ output/*
# a file generated by cmake
dfhack/include/config.h
library/private/config.h
# any build folders
build*/

@ -4,6 +4,11 @@ cmake_minimum_required(VERSION 2.6)
SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/Modules)
SET ( DFHACK_VERSION "0.4.1.0-dev" )
# Set this to project source dir. When dfhack is used
# as a submodule, CMAKE_SOURCE_DIR is not pointing to
# the root where this particular CMakeLists.txt file sits.
SET(CMAKE_SOURCE_DIR ${PROJECT_SOURCE_DIR})
# disable warning, autosearch
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
@ -26,6 +31,8 @@ OPTION(BUILD_DFHACK_EXAMPLES "Build example tools" OFF)
OPTION(BUILD_DFHACK_PLAYGROUND "Build tools from the playground folder" OFF)
OPTION(BUILD_DFHACK_C_BINDIGS "Build the C portion of the library" ON)
OPTION(BUILD_OFFSET_EDITOR "Build the Offset GUI editor (not ready for use)." OFF)
OPTION(BUILD_DFHACK_SUPPORTED "Build the supported toold." ON)
OPTION(BUILD_DFHACK_SHM "Build the SHM." OFF)
include_directories (${CMAKE_SOURCE_DIR}/library/include/)
include_directories (${CMAKE_SOURCE_DIR}/library/shm/)
@ -35,12 +42,26 @@ include_directories (${CMAKE_SOURCE_DIR}/library/depends/argstream/)
add_subdirectory (library)
IF(BUILD_DFHACK_SUPPORTED)
add_subdirectory (tools/supported)
ENDIF(BUILD_DFHACK_SUPPORTED)
IF(BUILD_OFFSET_EDITOR)
add_subdirectory (offsetedit)
ENDIF(BUILD_OFFSET_EDITOR)
add_subdirectory (library/shm)
add_subdirectory (tools/examples)
add_subdirectory (tools/playground)
add_subdirectory (tools/supported)
add_subdirectory (doc)
IF(BUILD_DFHACK_SHM)
add_subdirectory (library/shm)
ENDIF(BUILD_DFHACK_SHM)
IF(BUILD_DFHACK_EXAMPLES)
add_subdirectory (tools/examples)
ENDIF(BUILD_DFHACK_EXAMPLES)
IF(BUILD_DFHACK_PLAYGROUND)
add_subdirectory (tools/playground)
ENDIF(BUILD_DFHACK_PLAYGROUND)
IF(BUILD_DFHACK_DOCUMENTATION)
add_subdirectory (doc)
ENDIF(BUILD_DFHACK_DOCUMENTATION)

File diff suppressed because it is too large Load Diff

@ -1698,6 +1698,7 @@ map_data_1b60_offset 0x1B9c
<Address name="creature_vector">0x168E73C</Address>
<Address name="dwarf_race_index">0x014b9f1c</Address>
<Offset name="creature_soulskill_vector">0X1F4</Offset>
<Offset name="creature_inventory_vector">0x2FC</Offset>
<Offset name="creature_physical">0x4AC</Offset>
<Offset name="creature_appearance_vector">0x64c</Offset> <!-- Maybe slightly wrong -->
<Offset name="creature_artifact_name">0x71c</Offset>
@ -1721,6 +1722,7 @@ map_data_1b60_offset 0x1B9c
<Entry version="v0.31.12" os="windows" id="0.31.12" base="0.31.11">
<String name="md5">f0459165a426a9f2dd8d957e9fa7f01d</String>
<HexValue name="pe_timestamp">0x4C4C32E7</HexValue>
<Address name="screen_tiles_pointer">0x18313D0</Address>
</Entry>
.-"""-.
' \
@ -2359,6 +2361,7 @@ map_data_1b60_offset 0x1B9c
</Entry>
<Entry version="v0.31.12" os="linux" id="30_12lin" base="30_11lin" rebase="-0x1000">
<String name="md5">e79cead03187ecb692961b316b7cdcd4</String>
<Address name="screen_tiles_pointer">0x09487970</Address>
</Entry>
</MemoryDescriptors>
</DFExtractor>

@ -10,8 +10,6 @@
# http://tobias.rautenkranz.ch/cmake/doxygen/
# but it is hard to understand...
IF (BUILD_DFHACK_DOCUMENTATION)
FIND_PACKAGE(Doxygen)
IF(DOXYGEN_FOUND)
@ -64,5 +62,3 @@ IF(DOXYGEN_FOUND)
ELSE(DOXYGEN_FOUND)
MESSAGE (FATAL_ERROR "doxygen binary couldn't be found")
ENDIF(DOXYGEN_FOUND)
ENDIF (BUILD_DFHACK_DOCUMENTATION)

@ -26,20 +26,29 @@ include_directories (${CMAKE_SOURCE_DIR}/library/depends/tinyxml/)
include_directories (${CMAKE_SOURCE_DIR}/library/depends/argstream/)
include_directories (${CMAKE_SOURCE_DIR}/library/private/)
SET(PROJECT_HDRS_INTERNAL
private/ContextShared.h
private/Internal.h
)
SET(PROJECT_HDRS
private/DFMemInfoManager.h
private/ContextShared.h
private/Internal.h
include/DFHack.h
include/dfhack/DFContext.h
include/dfhack/DFContextManager.h
include/dfhack/DFError.h
include/dfhack/DFMemInfo.h
include/dfhack/DFProcessEnumerator.h
include/dfhack/DFExport.h
include/dfhack/DFGlobal.h
include/dfhack/DFIntegers.h
include/dfhack/DFMiscUtils.h
include/dfhack/DFModule.h
include/dfhack/DFPragma.h
include/dfhack/DFProcess.h
include/dfhack/DFProcessEnumerator.h
include/dfhack/DFTileTypes.h
include/dfhack/DFTypes.h
include/dfhack/DFVector.h
include/dfhack-c/DFTypes_C.h
include/dfhack-c/DFContext_C.h
include/dfhack/DFIntegers.h
include/dfhack/VersionInfoFactory.h
include/dfhack/VersionInfo.h
include/dfhack/modules/Buildings.h
include/dfhack/modules/Constructions.h
include/dfhack/modules/Creatures.h
@ -55,13 +64,26 @@ include/dfhack/modules/World.h
)
SET(PROJECT_C_HDRS
include/DFHack_C.h
include/dfhack-c/DFTypes_C.h
include/dfhack-c/DFContext_C.h
include/dfhack-c/modules/Buildings_C.h
include/dfhack-c/modules/Constructions_C.h
include/dfhack-c/modules/Creatures_C.h
include/dfhack-c/modules/Gui_C.h
include/dfhack-c/modules/Items_C.h
include/dfhack-c/modules/Maps_C.h
include/dfhack-c/modules/Materials_C.h
include/dfhack-c/modules/Position_C.h
include/dfhack-c/modules/Translation_C.h
include/dfhack-c/modules/Vegetation_C.h
include/dfhack-c/modules/WindowIO_C.h
include/dfhack-c/modules/World_C.h
)
SET(PROJECT_SRCS
DFMemInfo.cpp
DFMemInfoManager.cpp
VersionInfo.cpp
VersionInfoFactory.cpp
DFContextManager.cpp
DFContext.cpp
DFProcessEnumerator.cpp
@ -134,10 +156,10 @@ ELSE(UNIX)
LIST(APPEND PROJECT_SRCS ${PROJECT_SRCS_WINDOWS})
ENDIF(UNIX)
IF(BUILD_DFHACK_C_BINDIGS)
IF(BUILD_DFHACK_C_BINDINGS)
LIST(APPEND PROJECT_HDRS ${PROJECT_C_HDRS})
LIST(APPEND PROJECT_SRCS ${PROJECT_C_SRCS})
ENDIF(BUILD_DFHACK_C_BINDIGS)
ENDIF(BUILD_DFHACK_C_BINDINGS)
SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE )
@ -184,7 +206,7 @@ if(MSVC)
#
# So, $(TargetDir) is ignored by cmake, and replaced with the actual output directory by MSVC
ADD_CUSTOM_COMMAND(TARGET dfhack POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/data/Memory.xml $(TargetDir)/Memory.xml
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/data/Memory-ng.xml $(TargetDir)/Memory.xml
)
ADD_CUSTOM_COMMAND(TARGET dfhack POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/Compile.html $(TargetDir)/Compile.html
@ -192,14 +214,19 @@ if(MSVC)
ADD_CUSTOM_COMMAND(TARGET dfhack POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/Readme.html $(TargetDir)/Readme.html
)
ADD_CUSTOM_COMMAND(TARGET dfhack POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/LICENSE $(TargetDir)/LICENSE.txt
)
else(MSVC)
# Just put the file in the output directory on Linux and Mac
configure_file(${CMAKE_SOURCE_DIR}/data/Memory.xml ${DATA_OUTPUT_PATH}/Memory.xml COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/data/Memory-ng.xml ${DATA_OUTPUT_PATH}/Memory.xml COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/Compile.html ${DATA_OUTPUT_PATH}/Compile.html COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/Readme.html ${DATA_OUTPUT_PATH}/Readme.html COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/LICENSE ${DATA_OUTPUT_PATH}/LICENSE.txt COPYONLY)
endif(MSVC)
IF(UNIX)
install(TARGETS dfhack LIBRARY DESTINATION lib)
install(FILES ${CMAKE_SOURCE_DIR}/output/Memory.xml DESTINATION share/dfhack)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/library/include/ DESTINATION include FILES_MATCHING PATTERN "*.h")
ENDIF(UNIX)

@ -4,7 +4,7 @@
#include <mod-maps.h>
#include <mod-creature40d.h>
#include "private/ContextShared.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/modules/Materials.h"
@ -40,9 +40,10 @@ DFContextShared::~DFContextShared()
bool DFContextShared::InitReadNames()
{
name_firstname_offset = offset_descriptor->getOffset("name_firstname");
name_nickname_offset = offset_descriptor->getOffset("name_nickname");
name_words_offset = offset_descriptor->getOffset("name_words");
OffsetGroup * OG = offset_descriptor->getGroup("name");
name_firstname_offset = OG->getOffset("first");
name_nickname_offset = OG->getOffset("nick");
name_words_offset = OG->getOffset("second_words");
return true;
}

@ -199,7 +199,7 @@ void Context::WriteRaw (const uint32_t offset, const uint32_t size, uint8_t *sou
d->p->write (offset, size, source);
}
memory_info *Context::getMemoryInfo()
VersionInfo *Context::getMemoryInfo()
{
return d->offset_descriptor;
}

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

@ -1,778 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/DFError.h"
#include "dfhack/DFProcess.h"
//Inital amount of space in levels vector (since we usually know the number, efficent!)
#define NUM_RESERVE_LVLS 20
#define NUM_RESERVE_MOODS 6
using namespace DFHack;
/*
* Common data types
*/
namespace DFHack
{
struct t_type
{
t_type(uint32_t assign, uint32_t type, std::string classname)
:classname(classname),assign(assign),type(type){};
std::string classname;
uint32_t assign;
uint32_t type;
};
struct t_class
{
t_class(const t_class &old)
{
classname = old.classname;
vtable = old.vtable;
assign = old.assign;
type_offset = old.type_offset;
for(uint32_t i = 0; i < old.subs.size();i++)
{
t_type * t = new t_type (*old.subs[i]);
subs.push_back(t);
}
}
t_class ()
{
vtable = 0;
assign = 0;
type_offset = 0;
}
~t_class()
{
for(uint32_t i = 0; i < subs.size();i++)
{
delete subs[i];
}
subs.clear();
}
std::string classname;
uint32_t vtable;
uint32_t assign;// index to typeclass array if multiclass. return value if not.
uint32_t type_offset; // offset of type data for multiclass
std::vector<t_type *> subs;
};
}
/*
* Private data
*/
class memory_info::Private
{
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> jobs;
vector<string> skills;
vector<DFHack::t_level> levels;
vector< vector<string> > traits;
vector<string> moods;
map <uint32_t, string> labors;
// storage for class and multiclass
vector<t_class *> classes;
// cache for faster name lookup, indexed by classID
vector<string> classnames;
// map between vptr and class id, needs further type id lookup for multi-classes, not inherited
map<uint32_t, t_class *> classIDs;
// index for the next added class
uint32_t classindex;
int32_t base;
Process * p; // the process this belongs to
string version;
OSType OS;
};
// normal constructor
memory_info::memory_info()
:d(new Private)
{
d->base = 0;
d->p = 0;
d->classindex = 0;
d->levels.reserve(NUM_RESERVE_LVLS);
d->moods.reserve(NUM_RESERVE_MOODS);
}
// copy constructor
memory_info::memory_info(const memory_info &old)
:d(new Private)
{
d->version = old.d->version;
d->OS = old.d->OS;
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->classes = old.d->classes;
for(uint32_t i = 0; i < old.d->classes.size(); i++)
{
t_class * copy = new t_class(*old.d->classes[i]);
d->classes.push_back(copy);
}
d->classnames = old.d->classnames;
d->classindex = old.d->classindex;
d->professions = old.d->professions;
d->jobs = old.d->jobs;
d->skills = old.d->skills;
d->traits = old.d->traits;
d->labors = old.d->labors;
d->levels = old.d->levels;
d->moods = old.d->moods;
}
void memory_info::setParentProcess(Process * _p)
{
d->p = _p;
}
// destructor
memory_info::~memory_info()
{
// delete the vtables
for(uint32_t i = 0; i < d->classes.size();i++)
{
delete d->classes[i];
}
// delete our data
delete d;
}
void memory_info::setVersion(const char * v)
{
d->version = v;
}
void memory_info::setVersion(const string &v)
{
d->version = v;
}
string memory_info::getVersion()
{
return d->version;
}
void memory_info::setOS(const char *os)
{
string oss = os;
if(oss == "windows")
d->OS = OS_WINDOWS;
else if(oss == "linux")
d->OS = OS_LINUX;
else
d->OS = OS_BAD;
}
void memory_info::setOS(const string &os)
{
if(os == "windows")
d->OS = OS_WINDOWS;
else if(os == "linux")
d->OS = OS_LINUX;
else
d->OS = OS_BAD;
}
void memory_info::setOS(OSType os)
{
if(os >= OS_WINDOWS && os < OS_BAD)
{
d->OS = os;
return;
}
d->OS = OS_BAD;
}
memory_info::OSType memory_info::getOS() const
{
return d->OS;
}
uint32_t memory_info::getBase () const
{
return d->base;
}
void memory_info::setBase (const string &s)
{
d->base = strtol(s.c_str(), NULL, 16);
}
void memory_info::setBase (const uint32_t b)
{
d->base = b;
}
void memory_info::setOffset (const string & key, const string & value)
{
int32_t offset = strtol(value.c_str(), NULL, 16);
d->offsets[key] = offset;
}
void memory_info::setAddress (const string & key, const string & value)
{
uint32_t address = strtol(value.c_str(), NULL, 16);
d->addresses[key] = address;
}
void memory_info::setHexValue (const string & key, const string & value)
{
uint32_t hexval = strtol(value.c_str(), NULL, 16);
d->hexvals[key] = hexval;
}
void memory_info::setString (const string & key, const string & value)
{
d->strings[key] = value;
}
void memory_info::setLabor(const string & key, const string & value)
{
uint32_t keyInt = strtol(key.c_str(), NULL, 10);
d->labors[keyInt] = value;
}
void memory_info::setProfession (const string & key, const string & value)
{
uint32_t keyInt = strtol(key.c_str(), NULL, 10);
if(d->professions.size() <= keyInt)
{
d->professions.resize(keyInt+1,"");
}
d->professions[keyInt] = value;
}
void memory_info::setJob (const string & key, const string & value)
{
uint32_t keyInt = strtol(key.c_str(), NULL, 10);
if(d->jobs.size() <= keyInt)
{
d->jobs.resize(keyInt+1);
}
d->jobs[keyInt] = value;
}
void memory_info::setSkill (const string & key, const string & value)
{
uint32_t keyInt = strtol(key.c_str(), NULL, 10);
if(d->skills.size() <= keyInt){
d->skills.resize(keyInt+1);
}
d->skills[keyInt] = value;
}
void memory_info::setLevel(const std::string &nLevel,
const std::string &nName,
const std::string &nXp)
{
uint32_t keyInt = strtol(nLevel.c_str(), NULL, 10);
if(d->levels.size() <= keyInt)
d->levels.resize(keyInt+1);
d->levels[keyInt].level = keyInt;
d->levels[keyInt].name = nName;
d->levels[keyInt].xpNxtLvl = strtol(nXp.c_str(), NULL, 10);
}
void memory_info::setMood(const std::string &id, const std::string &mood)
{
uint32_t keyInt = strtol(id.c_str(), NULL, 10);
if(d->moods.size() <= keyInt)
d->moods.resize(keyInt+1);
d->moods[keyInt] = mood;
}
void memory_info::setTrait(const string & key,
const string & value,
const string & zero,
const string & one,
const string & two,
const string & three,
const string & four,
const string & five)
{
uint32_t keyInt = strtol(key.c_str(), NULL, 10);
if(d->traits.size() <= keyInt)
{
d->traits.resize(keyInt+1);
}
d->traits[keyInt].push_back(zero);
d->traits[keyInt].push_back(one);
d->traits[keyInt].push_back(two);
d->traits[keyInt].push_back(three);
d->traits[keyInt].push_back(four);
d->traits[keyInt].push_back(five);
d->traits[keyInt].push_back(value);
}
// FIXME: next three methods should use some kind of custom container so it doesn't have to search so much.
t_class * memory_info::setClass (const char * name, uint32_t vtable, uint32_t typeoffset)
{
if(name == 0)
return 0;
for (uint32_t i=0; i<d->classes.size(); i++)
{
if(d->classes[i]->classname == name)
{
if(vtable != 0)
d->classes[i]->vtable = vtable;
if(typeoffset != 0)
d->classes[i]->type_offset = typeoffset;
return d->classes[i];
}
}
t_class *cls = new t_class();
// get an unique ID and add ourselves to the index
cls->assign = d->classindex;
cls->classname = name;
d->classnames.push_back(name);
// vtables no longer a requirement
cls->vtable = vtable;
// multi class yes/no
cls->type_offset = typeoffset;
d->classes.push_back(cls);
d->classindex++;
return cls;
}
void memory_info::setClassChild (t_class * parent, const char * name, const char * type)
{
vector <t_type *>& vec = parent->subs;
for (uint32_t i=0; i<vec.size(); i++)
{
if(vec[i]->classname == name)
{
vec[i]->type = strtol(type, NULL, 16);
return;
}
}
// new multiclass child
t_type *mcc = new t_type(d->classindex,strtol(type, NULL, 16),name);
d->classnames.push_back(name);
vec.push_back(mcc);
d->classindex++;
//cout << " classtype " << name << ", assign " << mcc->assign << ", vtable " << mcc->type << endl;
}
// FIXME: stupid. we need a better container
bool memory_info::resolveObjectToClassID(const uint32_t address, int32_t & classid)
{
uint32_t vtable = d->p->readDWord(address);
// try to find the vtable in our cache
map<uint32_t, t_class *>::iterator it;
it = d->classIDs.find(vtable);
t_class * cl;
// class found in cache?
if(it != d->classIDs.end())
{
cl = (*it).second;
}
else// couldn't find?
{
// we set up the class for the first time
string classname = d->p->readClassName(vtable);
d->classIDs[vtable] = cl = setClass(classname.c_str(),vtable);
}
// and isn't a multi-class
if(!cl->type_offset)
{
// return
classid = cl->assign;
return true;
}
// and is a multiclass
else
{
// find the type
vector <t_type*>& vec = cl->subs;
uint32_t type = d->p->readWord(address + cl->type_offset);
// return typed building if successful
//FIXME: the vector should map directly to the type IDs here, so we don't have to mess with O(n) search
for (uint32_t k = 0; k < vec.size();k++)
{
if(vec[k]->type == type)
{
//cout << " multi " << address + classes[i].type_offset << " " << vec[k].classname << endl;
classid = vec[k]->assign;
return true;
}
}
// couldn't find the type... now what do we do here? throw?
// this is a case where it might be a good idea, because it uncovers some deeper problems
// we return the parent class instead, it doesn't change the API semantics and sort-of makes sense
classid = cl->assign;
return true;
}
}
//ALERT: doesn't care about multiclasses
bool memory_info::resolveClassnameToVPtr(const string classname, uint32_t & vptr)
{
// FIXME: another stupid search.
for(uint32_t i = 0;i< d->classes.size();i++)
{
//if(classes[i].)
if(d->classes[i]->classname == classname) // got class
{
vptr = d->classes[i]->vtable;
return true;
}
}
// we failed to find anything that would match
return false;
}
bool memory_info::resolveClassnameToClassID (const string classname, int32_t & classID)
{
// FIXME: another stupid search.
classID = -1;
for(uint32_t i = 0;i< d->classnames.size();i++)
{
if(d->classnames[i] == classname)
{
classID = i;
return true;
}
}
// we failed to find anything that would match
return false;
}
bool memory_info::resolveClassIDToClassname (const int32_t classID, string & classname)
{
if (classID >=0 && (uint32_t)classID < d->classnames.size())
{
classname = d->classnames[classID];
return true;
}
return false;
}
// return pointer to our internal classID -> className mapping
const vector<string> * memory_info::getClassIDMapping()
{
return &d->classnames;
}
// change base of all addresses
void memory_info::RebaseAddresses(const int32_t new_base)
{
map<string, uint32_t>::iterator iter;
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;
}
}
// change base of all addresses *and* vtable entries
void memory_info::RebaseAll(int32_t new_base)
{
map<string, uint32_t>::iterator iter;
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;
}
RebaseVTable(rebase);
}
// change all vtable entries by offset
void memory_info::RebaseVTable(int32_t offset)
{
vector<t_class *>::iterator iter;
for(iter = d->classes.begin(); iter != d->classes.end(); iter++)
{
(*iter)->vtable += offset;
}
}
// Get named address
uint32_t memory_info::getAddress (const char *key)
{
map <string, uint32_t>::iterator iter = d->addresses.find(key);
if(iter != d->addresses.end())
{
return (*iter).second;
}
throw Error::MissingMemoryDefinition("address", key);
}
// Get named offset
int32_t memory_info::getOffset (const char *key)
{
map <string, int32_t>::iterator iter = d->offsets.find(key);
if(iter != d->offsets.end())
{
return (*iter).second;
}
throw Error::MissingMemoryDefinition("offset", key);
}
// Get named numerical value
uint32_t memory_info::getHexValue (const char *key)
{
map <string, uint32_t>::iterator iter = d->hexvals.find(key);
if(iter != d->hexvals.end())
{
return (*iter).second;
}
throw Error::MissingMemoryDefinition("hexvalue", key);
}
// Get named address
uint32_t memory_info::getAddress (const string &key)
{
map <string, uint32_t>::iterator iter = d->addresses.find(key);
if(iter != d->addresses.end())
{
return (*iter).second;
}
throw Error::MissingMemoryDefinition("address", key.c_str());
}
// Get named offset
int32_t memory_info::getOffset (const string &key)
{
map <string, int32_t>::iterator iter = d->offsets.find(key);
if(iter != d->offsets.end())
{
return (*iter).second;
}
throw Error::MissingMemoryDefinition("offset", key.c_str());
}
// Get named numerical value
uint32_t memory_info::getHexValue (const string &key)
{
map <string, uint32_t>::iterator iter = d->hexvals.find(key);
if(iter != d->hexvals.end())
{
return (*iter).second;
}
throw Error::MissingMemoryDefinition("hexvalue", key.c_str());
}
// Get named string
std::string memory_info::getString (const string &key)
{
map <string, string>::iterator iter = d->strings.find(key);
if(iter != d->strings.end())
{
return (*iter).second;
}
throw Error::MissingMemoryDefinition("string", key.c_str());
}
// Get Profession
string memory_info::getProfession (const uint32_t key) const
{
if(d->professions.size() > key)
{
return d->professions[key];
}
throw Error::MissingMemoryDefinition("profession", key);
}
// Get Job
string memory_info::getJob (const uint32_t key) const
{
if(d->jobs.size() > key)
{
return d->jobs[key];
}
throw Error::MissingMemoryDefinition("job", key);
}
string memory_info::getSkill (const uint32_t key) const
{
if(d->skills.size() > key)
{
return d->skills[key];
}
throw Error::MissingMemoryDefinition("skill", key);
}
DFHack::t_level memory_info::getLevelInfo(const uint32_t level) const
{
if(d->levels.size() > level)
{
return d->levels[level];
}
throw Error::MissingMemoryDefinition("Level", level);
}
// FIXME: ugly hack that needs to die
int absolute (int number)
{
if (number < 0)
return -number;
return number;
}
string memory_info::getTrait (const uint32_t traitIdx, const uint32_t traitValue) const
{
if(d->traits.size() > traitIdx)
{
int diff = absolute(traitValue-50);
if(diff < 10)
{
return string("");
}
if (traitValue >= 91)
return d->traits[traitIdx][5];
else if (traitValue >= 76)
return d->traits[traitIdx][4];
else if (traitValue >= 61)
return d->traits[traitIdx][3];
else if (traitValue >= 25)
return d->traits[traitIdx][2];
else if (traitValue >= 10)
return d->traits[traitIdx][1];
else
return d->traits[traitIdx][0];
}
throw Error::MissingMemoryDefinition("trait", traitIdx);
}
string memory_info::getTraitName(const uint32_t traitIdx) const
{
if(d->traits.size() > traitIdx)
{
return d->traits[traitIdx][d->traits[traitIdx].size()-1];
}
throw Error::MissingMemoryDefinition("traitname", traitIdx);
}
std::vector< std::vector<std::string> > const& memory_info::getAllTraits()
{
return d->traits;
}
string memory_info::getLabor (const uint32_t laborIdx)
{
if(d->labors.count(laborIdx))
{
return d->labors[laborIdx];
}
throw Error::MissingMemoryDefinition("labor", laborIdx);
}
std::string memory_info::getMood(const uint32_t moodID)
{
if(d->moods.size() > moodID)
{
return d->moods[moodID];
}
throw Error::MissingMemoryDefinition("Mood", moodID);
}
std::string memory_info::PrintOffsets()
{
ostringstream ss;
ss << "<Version name=\"" << getVersion() << "\">" << endl;
switch (getOS())
{
case OS_LINUX:
ss << "<MD5 value=\"" << getString("md5") << "\" />" << endl;
break;
case OS_WINDOWS:
ss << "<PETimeStamp value=\"" << hex << "0x" << getHexValue("pe_timestamp") << "\" />" << endl;
ss << "<MD5 value=\"" << getString("md5") << "\" />" << endl;
break;
default:
ss << " UNKNOWN" << endl;
}
ss << "<Offsets>" << endl;
map<string,uint32_t>::const_iterator iter;
for(iter = d->addresses.begin(); iter != d->addresses.end(); iter++)
{
ss << " <Address name=\"" << (*iter).first << "\" value=\"" << hex << "0x" << (*iter).second << "\" />" << endl;
}
map<string,int32_t>::const_iterator iter2;
for(iter2 = d->offsets.begin(); iter2 != d->offsets.end(); iter2++)
{
ss << " <Offset name=\"" << (*iter2).first << "\" value=\"" << hex << "0x" << (*iter2).second <<"\" />" << endl;
}
for(iter = d->hexvals.begin(); iter != d->hexvals.end(); iter++)
{
ss << " <HexValue name=\"" << (*iter).first << "\" value=\"" << hex << "0x" << (*iter).second <<"\" />" << endl;
}
map<string,string>::const_iterator iter3;
for(iter3 = d->strings.begin(); iter3 != d->strings.end(); iter3++)
{
ss << " <String name=\"" << (*iter3).first << "\" value=\"" << (*iter3).second <<"\" />" << endl;
}
ss << "</Offsets>" << endl;
ss << "</Version>" << endl;
return ss.str();
}

@ -1,297 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include "DFMemInfoManager.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/DFError.h"
using namespace DFHack;
MemInfoManager::~MemInfoManager()
{
// for each in std::vector<memory_info*> meminfo;, delete
for(uint32_t i = 0; i < meminfo.size();i++)
{
delete meminfo[i];
}
meminfo.clear();
}
void MemInfoManager::ParseVTable(TiXmlElement* vtable, memory_info* mem)
{
TiXmlElement* pClassEntry;
TiXmlElement* pClassSubEntry;
// check for rebase, do rebase if check positive
const char * rebase = vtable->Attribute("rebase");
if(rebase)
{
int32_t rebase_offset = strtol(rebase, NULL, 16);
mem->RebaseVTable(rebase_offset);
}
// parse vtable entries
pClassEntry = vtable->FirstChildElement();
for(;pClassEntry;pClassEntry=pClassEntry->NextSiblingElement())
{
string type = pClassEntry->Value();
const char *cstr_name = pClassEntry->Attribute("name");
const char *cstr_vtable = pClassEntry->Attribute("vtable");
uint32_t vtable = 0;
if(cstr_vtable)
vtable = strtol(cstr_vtable, NULL, 16);
// it's a simple class
if(type== "class")
{
mem->setClass(cstr_name, vtable);
}
// it's a multi-type class
else if (type == "multiclass")
{
// get offset of the type variable
const char *cstr_typeoffset = pClassEntry->Attribute("typeoffset");
uint32_t typeoffset = 0;
if(cstr_typeoffset)
typeoffset = strtol(cstr_typeoffset, NULL, 16);
t_class * mclass = mem->setClass(cstr_name, vtable, typeoffset);
// parse class sub-entries
pClassSubEntry = pClassEntry->FirstChildElement();
for(;pClassSubEntry;pClassSubEntry=pClassSubEntry->NextSiblingElement())
{
type = pClassSubEntry->Value();
if(type== "class")
{
// type is a value loaded from type offset
cstr_name = pClassSubEntry->Attribute("name");
const char *cstr_value = pClassSubEntry->Attribute("type");
mem->setClassChild(mclass,cstr_name,cstr_value);
}
}
}
}
}
void MemInfoManager::ParseEntry (TiXmlElement* entry, memory_info* mem, map <string ,TiXmlElement *>& knownEntries)
{
TiXmlElement* pMemEntry;
const char *cstr_version = entry->Attribute("version");
const char *cstr_os = entry->Attribute("os");
const char *cstr_base = entry->Attribute("base");
const char *cstr_rebase = entry->Attribute("rebase");
if(cstr_base)
{
string base = cstr_base;
ParseEntry(knownEntries[base], mem, knownEntries);
}
if (!cstr_version)
throw Error::MemoryXmlBadAttribute("version");
if (!cstr_os)
throw Error::MemoryXmlBadAttribute("os");
string os = cstr_os;
mem->setVersion(cstr_version);
mem->setOS(cstr_os);
// offset inherited addresses by 'rebase'.
int32_t rebase = 0;
if(cstr_rebase)
{
rebase = mem->getBase() + strtol(cstr_rebase, NULL, 16);
mem->RebaseAddresses(rebase);
}
//set base to default, we're overwriting this because the previous rebase could cause havoc on Vista/7
if(os == "windows")
{
// set default image base. this is fixed for base relocation later
mem->setBase(0x400000);
}
else if(os == "linux")
{
// this is wrong... I'm not going to do base image relocation on linux though.
// users are free to use a sane kernel that doesn't do this kind of **** by default
mem->setBase(0x0);
}
else if ( os == "all")
{
// yay
}
else
{
throw Error::MemoryXmlBadAttribute("os");
}
// process additional entries
//cout << "Entry " << cstr_version << " " << cstr_os << endl;
pMemEntry = entry->FirstChildElement()->ToElement();
for(;pMemEntry;pMemEntry=pMemEntry->NextSiblingElement())
{
// only elements get processed
const char *cstr_type = pMemEntry->Value();
const char *cstr_name = pMemEntry->Attribute("name");
const char *cstr_value = pMemEntry->GetText();
if(!cstr_value)
cstr_value = pMemEntry->Attribute("id");
// check for missing parts
string type, name, value;
type = cstr_type;
if(type == "VTable")
{
ParseVTable(pMemEntry, mem);
continue;
}
if(!(cstr_name && cstr_value))
{
throw Error::MemoryXmlUnderspecifiedEntry(cstr_version);
}
name = cstr_name;
value = cstr_value;
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 if (type == "Profession")
{
mem->setProfession(value,name);
}
else if (type == "Job")
{
mem->setJob(value,name);
}
else if (type == "Skill")
{
mem->setSkill(value,name);
}
else if (type == "Trait")
{
mem->setTrait(value, name,pMemEntry->Attribute("level_0"),pMemEntry->Attribute("level_1"),pMemEntry->Attribute("level_2"),pMemEntry->Attribute("level_3"),pMemEntry->Attribute("level_4"),pMemEntry->Attribute("level_5"));
}
else if (type == "Labor")
{
mem->setLabor(value,name);
}
else if (type == "Level")
{
mem->setLevel(value, name, pMemEntry->Attribute("xpNxtLvl"));
}
else if (type == "Mood")
{
mem->setMood(value, name);
}
else
{
throw Error::MemoryXmlUnknownType(type.c_str());
}
} // for
} // method
MemInfoManager::MemInfoManager(string path_to_xml)
{
error = false;
loadFile(path_to_xml);
}
// load the XML file with offsets
bool MemInfoManager::loadFile(string path_to_xml)
{
TiXmlDocument doc( path_to_xml.c_str() );
//bool loadOkay = doc.LoadFile();
if (!doc.LoadFile())
{
error = true;
throw Error::MemoryXmlParse(doc.ErrorDesc(), doc.ErrorId(), doc.ErrorRow(), doc.ErrorCol());
}
TiXmlHandle hDoc(&doc);
TiXmlElement* pElem;
TiXmlHandle hRoot(0);
memory_info mem;
// block: name
{
pElem=hDoc.FirstChildElement().Element();
// should always have a valid root but handle gracefully if it does
if (!pElem)
{
error = true;
throw Error::MemoryXmlNoRoot();
}
string m_name=pElem->Value();
if(m_name != "DFExtractor")
{
error = true;
throw Error::MemoryXmlNoDFExtractor(m_name.c_str());
}
// save this for later
hRoot=TiXmlHandle(pElem);
}
// transform elements
{
// trash existing list
for(uint32_t i = 0; i < meminfo.size(); i++)
{
delete meminfo[i];
}
meminfo.clear();
TiXmlElement* pMemInfo=hRoot.FirstChild( "MemoryDescriptors" ).FirstChild( "Entry" ).Element();
map <string ,TiXmlElement *> map_pNamedEntries;
vector <TiXmlElement *> v_pEntries;
for( ; pMemInfo; pMemInfo=pMemInfo->NextSiblingElement("Entry"))
{
v_pEntries.push_back(pMemInfo);
const char *id = pMemInfo->Attribute("id");
if(id)
{
string str_id = id;
map_pNamedEntries[str_id] = pMemInfo;
}
}
for(uint32_t i = 0; i< v_pEntries.size();i++)
{
memory_info *mem = new memory_info();
//FIXME: add a set of entries processed in a step of this cycle, use it to check for infinite loops
/* recursive */ParseEntry( v_pEntries[i] , mem , map_pNamedEntries);
meminfo.push_back(mem);
}
// process found things here
}
error = false;
return true;
}

@ -23,7 +23,7 @@ distribution.
*/
#include "Internal.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include <errno.h>
@ -63,7 +63,7 @@ class SHMProcess::Private
self = self_;
};
~Private(){};
memory_info * memdescriptor;
VersionInfo * memdescriptor;
Process * self;
pid_t process_ID;
char *shm_addr;
@ -79,7 +79,7 @@ class SHMProcess::Private
bool identified;
bool useYield;
bool validate(std::vector< memory_info* >& known_versions);
bool validate(std::vector< VersionInfo* >& known_versions);
bool Aux_Core_Attach(bool & versionOK, pid_t & PID);
//bool waitWhile (uint32_t state);
@ -258,7 +258,7 @@ bool SHMProcess::Private::GetLocks()
return false;
}
SHMProcess::SHMProcess(uint32_t PID, vector< memory_info* >& known_versions)
SHMProcess::SHMProcess(uint32_t PID, vector< VersionInfo* >& known_versions)
: d(new Private(this))
{
d->process_ID = PID;
@ -303,7 +303,7 @@ bool SHMProcess::isIdentified()
return d->identified;
}
bool SHMProcess::Private::validate(vector <memory_info *> & known_versions)
bool SHMProcess::Private::validate(vector <VersionInfo *> & known_versions)
{
char exe_link_name [256];
char target_name[1024];
@ -323,15 +323,15 @@ bool SHMProcess::Private::validate(vector <memory_info *> & known_versions)
md5wrapper md5;
// get hash of the running DF process
string hash = md5.getHashFromFile(target_name);
vector<memory_info *>::iterator it;
vector<VersionInfo *>::iterator it;
// cerr << exe_file << " " << hash << endl;
// iterate over the list of memory locations
for ( it=known_versions.begin() ; it < known_versions.end(); it++ )
{
try{
if(hash == (*it)->getString("md5")) // are the md5 hashes the same?
if(hash == (*it)->getMD5()) // are the md5 hashes the same?
{
memory_info *m = new memory_info(**it);
VersionInfo *m = new VersionInfo(**it);
memdescriptor = m;
m->setParentProcess(dynamic_cast<Process *>( self ));
identified = true;
@ -358,7 +358,7 @@ SHMProcess::~SHMProcess()
delete d;
}
memory_info * SHMProcess::getDescriptor()
VersionInfo * SHMProcess::getDescriptor()
{
return d->memdescriptor;
}

@ -23,7 +23,7 @@ distribution.
*/
#include "Internal.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include <errno.h>
#include <sys/ptrace.h>
@ -44,7 +44,7 @@ class WineProcess::Private
self = self_;
};
~Private(){};
memory_info * my_descriptor;
VersionInfo * my_descriptor;
Process * self;
pid_t my_handle;
uint32_t my_pid;
@ -53,10 +53,13 @@ class WineProcess::Private
bool attached;
bool suspended;
bool identified;
bool validate(char * exe_file, uint32_t pid, char * mem_file, vector <memory_info *> & known_versions);
uint32_t STLSTR_buf_off;
uint32_t STLSTR_size_off;
uint32_t STLSTR_cap_off;
bool validate(char * exe_file, uint32_t pid, char * mem_file, vector <VersionInfo *> & known_versions);
};
WineProcess::WineProcess(uint32_t pid, vector <memory_info *> & known_versions)
WineProcess::WineProcess(uint32_t pid, vector <VersionInfo *> & known_versions)
: d(new Private(this))
{
char dir_name [256];
@ -124,12 +127,12 @@ bool WineProcess::isIdentified()
return d->identified;
}
bool WineProcess::Private::validate(char* exe_file, uint32_t pid, char* mem_file, std::vector< memory_info* >& known_versions)
bool WineProcess::Private::validate(char* exe_file, uint32_t pid, char* mem_file, std::vector< VersionInfo* >& known_versions)
{
md5wrapper md5;
// get hash of the running DF process
string hash = md5.getHashFromFile(exe_file);
vector<memory_info *>::iterator it;
vector<VersionInfo *>::iterator it;
// iterate over the list of memory locations
for ( it=known_versions.begin() ; it < known_versions.end(); it++ )
@ -137,24 +140,28 @@ bool WineProcess::Private::validate(char* exe_file, uint32_t pid, char* mem_file
string thishash;
try
{
thishash = (*it)->getString("md5");
thishash = (*it)->getMD5();
}
catch (Error::MissingMemoryDefinition& e)
{
continue;
}
// are the md5 hashes the same?
if(memory_info::OS_WINDOWS == (*it)->getOS() && hash == thishash)
if(VersionInfo::OS_WINDOWS == (*it)->getOS() && hash == thishash)
{
// keep track of created memory_info object so we can destroy it later
memory_info *m = new memory_info(**it);
VersionInfo *m = new VersionInfo(**it);
my_descriptor = m;
m->setParentProcess(dynamic_cast<Process *>( self ));
my_handle = my_pid = pid;
// tell WineProcess about the /proc/PID/mem file
memFile = mem_file;
identified = true;
OffsetGroup * strGrp = m->getGroup("string")->getGroup("MSVC");
STLSTR_buf_off = strGrp->getOffset("buffer");
STLSTR_size_off = strGrp->getOffset("size");
STLSTR_cap_off = strGrp->getOffset("capacity");
return true;
}
}
@ -173,7 +180,7 @@ WineProcess::~WineProcess()
delete d;
}
memory_info * WineProcess::getDescriptor()
VersionInfo * WineProcess::getDescriptor()
{
return d->my_descriptor;
}
@ -563,21 +570,10 @@ const std::string WineProcess::readCString (uint32_t offset)
size_t WineProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
/*
MSVC++ string
ptr allocator
union
{
char[16] start;
char * start_ptr
}
Uint32 length
Uint32 capacity
*/
uint32_t start_offset = offset + 4;
size_t length = readDWord(offset + 20);
uint32_t start_offset = offset + d->STLSTR_buf_off;
size_t length = readDWord(offset + d->STLSTR_size_off);
size_t capacity = readDWord(offset + d->STLSTR_cap_off);
size_t capacity = readDWord(offset + 24);
size_t read_real = min(length, bufcapacity-1);// keep space for null termination
// read data from inside the string structure
@ -597,20 +593,10 @@ size_t WineProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcap
const string WineProcess::readSTLString (uint32_t offset)
{
/*
MSVC++ string
ptr allocator
union
{
char[16] start;
char * start_ptr
}
Uint32 length
Uint32 capacity
*/
uint32_t start_offset = offset + 4;
uint32_t length = readDWord(offset + 20);
uint32_t capacity = readDWord(offset + 24);
uint32_t start_offset = offset + d->STLSTR_buf_off;
size_t length = readDWord(offset + d->STLSTR_size_off);
size_t capacity = readDWord(offset + d->STLSTR_cap_off);
char * temp = new char[capacity+1];
// read data from inside the string structure

@ -23,7 +23,7 @@ distribution.
*/
#include "Internal.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include <errno.h>
#include <sys/ptrace.h>
@ -44,7 +44,7 @@ class NormalProcess::Private
};
~Private(){};
Window* my_window;
memory_info * my_descriptor;
VersionInfo * my_descriptor;
pid_t my_handle;
uint32_t my_pid;
string memFile;
@ -53,10 +53,10 @@ class NormalProcess::Private
bool suspended;
bool identified;
Process * self;
bool validate(char * exe_file, uint32_t pid, char * mem_file, vector <memory_info *> & known_versions);
bool validate(char * exe_file, uint32_t pid, char * mem_file, vector <VersionInfo *> & known_versions);
};
NormalProcess::NormalProcess(uint32_t pid, vector< memory_info* >& known_versions)
NormalProcess::NormalProcess(uint32_t pid, vector< VersionInfo* >& known_versions)
: d(new Private(this))
{
char dir_name [256];
@ -108,24 +108,25 @@ bool NormalProcess::isIdentified()
return d->identified;
}
bool NormalProcess::Private::validate(char * exe_file,uint32_t pid, char * memFile, vector <memory_info *> & known_versions)
bool NormalProcess::Private::validate(char * exe_file,uint32_t pid, char * memFile, vector <VersionInfo *> & known_versions)
{
md5wrapper md5;
// get hash of the running DF process
string hash = md5.getHashFromFile(exe_file);
vector<memory_info *>::iterator it;
vector<VersionInfo *>::iterator it;
// iterate over the list of memory locations
for ( it=known_versions.begin() ; it < known_versions.end(); it++ )
{
try
{
if(hash == (*it)->getString("md5")) // are the md5 hashes the same?
//cout << hash << " ?= " << (*it)->getMD5() << endl;
if(hash == (*it)->getMD5()) // are the md5 hashes the same?
{
memory_info * m = *it;
if (memory_info::OS_LINUX == m->getOS())
VersionInfo * m = *it;
if (VersionInfo::OS_LINUX == m->getOS())
{
memory_info *m2 = new memory_info(*m);
VersionInfo *m2 = new VersionInfo(*m);
my_descriptor = m2;
m2->setParentProcess(dynamic_cast<Process *>( self ));
my_handle = my_pid = pid;
@ -161,7 +162,7 @@ NormalProcess::~NormalProcess()
delete d;
}
memory_info * NormalProcess::getDescriptor()
VersionInfo * NormalProcess::getDescriptor()
{
return d->my_descriptor;
}

@ -23,7 +23,7 @@ distribution.
*/
#include "Internal.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include "shms.h"
#include "mod-core.h"
@ -48,7 +48,7 @@ class SHMProcess::Private
attachmentIdx = -1;
};
~Private(){};
memory_info * memdescriptor;
VersionInfo * memdescriptor;
SHMProcess * self;
uint32_t process_ID;
char *shm_addr;
@ -62,7 +62,7 @@ class SHMProcess::Private
bool identified;
bool useYield;
bool validate(std::vector< memory_info* >& known_versions);
bool validate(std::vector< VersionInfo* >& known_versions);
bool Aux_Core_Attach(bool & versionOK, uint32_t & PID);
bool SetAndWait (uint32_t state);
@ -274,7 +274,7 @@ bool SHMProcess::Private::AreLocksOk()
}
*/
SHMProcess::SHMProcess(uint32_t PID, vector <memory_info *> & known_versions)
SHMProcess::SHMProcess(uint32_t PID, vector <VersionInfo *> & known_versions)
: d(new Private())
{
d->process_ID = PID;
@ -314,7 +314,7 @@ bool SHMProcess::isIdentified()
{
return d->identified;
}
bool SHMProcess::Private::validate(vector <memory_info *> & known_versions)
bool SHMProcess::Private::validate(vector <VersionInfo *> & known_versions)
{
// try to identify the DF version
IMAGE_NT_HEADERS32 pe_header;
@ -345,13 +345,13 @@ bool SHMProcess::Private::validate(vector <memory_info *> & known_versions)
self->read(base + pe_offset+ sizeof(pe_header), sizeof(sections) , (uint8_t *)&sections );
// iterate over the list of memory locations
vector<memory_info *>::iterator it;
vector<VersionInfo *>::iterator it;
for ( it=known_versions.begin() ; it < known_versions.end(); it++ )
{
uint32_t pe_timestamp;
try
{
pe_timestamp = (*it)->getHexValue("pe_timestamp");
pe_timestamp = (*it)->getPE();
}
catch(Error::MissingMemoryDefinition&)
{
@ -359,7 +359,7 @@ bool SHMProcess::Private::validate(vector <memory_info *> & known_versions)
}
if (pe_timestamp == pe_header.FileHeader.TimeDateStamp)
{
memory_info *m = new memory_info(**it);
VersionInfo *m = new VersionInfo(**it);
m->RebaseAll(base);
memdescriptor = m;
m->setParentProcess(self);
@ -385,7 +385,7 @@ SHMProcess::~SHMProcess()
delete d;
}
memory_info * SHMProcess::getDescriptor()
VersionInfo * SHMProcess::getDescriptor()
{
return d->memdescriptor;
}

@ -23,7 +23,7 @@ distribution.
*/
#include "Internal.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
using namespace DFHack;
@ -40,7 +40,7 @@ class NormalProcess::Private
suspended = false;
};
~Private(){};
memory_info * my_descriptor;
VersionInfo * my_descriptor;
HANDLE my_handle;
HANDLE my_main_thread;
uint32_t my_pid;
@ -48,9 +48,12 @@ class NormalProcess::Private
bool attached;
bool suspended;
bool identified;
uint32_t STLSTR_buf_off;
uint32_t STLSTR_size_off;
uint32_t STLSTR_cap_off;
};
NormalProcess::NormalProcess(uint32_t pid, vector <memory_info *> & known_versions)
NormalProcess::NormalProcess(uint32_t pid, vector <VersionInfo *> & known_versions)
: d(new Private())
{
HMODULE hmod = NULL;
@ -96,17 +99,17 @@ NormalProcess::NormalProcess(uint32_t pid, vector <memory_info *> & known_versio
}
// see if there's a version entry that matches this process
vector<memory_info*>::iterator it;
vector<VersionInfo*>::iterator it;
for ( it=known_versions.begin() ; it < known_versions.end(); it++ )
{
// filter by OS
if(memory_info::OS_WINDOWS != (*it)->getOS())
if(VersionInfo::OS_WINDOWS != (*it)->getOS())
continue;
uint32_t pe_timestamp;
// filter by timestamp, skip entries without a timestamp
try
{
pe_timestamp = (*it)->getHexValue("pe_timestamp");
pe_timestamp = (*it)->getPE();
}
catch(Error::MissingMemoryDefinition&)
{
@ -120,7 +123,7 @@ NormalProcess::NormalProcess(uint32_t pid, vector <memory_info *> & known_versio
printf("Match found! Using version %s.\n", (*it)->getVersion().c_str());
d->identified = true;
// give the process a data model and memory layout fixed for the base of first module
memory_info *m = new memory_info(**it);
VersionInfo *m = new VersionInfo(**it);
m->RebaseAll(base);
// keep track of created memory_info object so we can destroy it later
d->my_descriptor = m;
@ -134,7 +137,10 @@ NormalProcess::NormalProcess(uint32_t pid, vector <memory_info *> & known_versio
vector<uint32_t> threads;
getThreadIDs( threads );
d->my_main_thread = OpenThread(THREAD_ALL_ACCESS, FALSE, (DWORD) threads[0]);
OffsetGroup * strGrp = m->getGroup("string")->getGroup("MSVC");
d->STLSTR_buf_off = strGrp->getOffset("buffer");
d->STLSTR_size_off = strGrp->getOffset("size");
d->STLSTR_cap_off = strGrp->getOffset("capacity");
found = true;
break; // break the iterator loop
}
@ -167,7 +173,7 @@ NormalProcess::~NormalProcess()
delete d;
}
memory_info * NormalProcess::getDescriptor()
VersionInfo * NormalProcess::getDescriptor()
{
return d->my_descriptor;
}
@ -430,21 +436,9 @@ const string NormalProcess::readCString (const uint32_t offset)
size_t NormalProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
/*
MSVC++ string
ptr allocator
union
{
char[16] start;
char * start_ptr
}
Uint32 length
Uint32 capacity
*/
uint32_t start_offset = offset + 4;
size_t length = readDWord(offset + 20);
size_t capacity = readDWord(offset + 24);
uint32_t start_offset = offset + d->STLSTR_buf_off;
size_t length = readDWord(offset + d->STLSTR_size_off);
size_t capacity = readDWord(offset + d->STLSTR_cap_off);
size_t read_real = min(length, bufcapacity-1);// keep space for null termination
// read data from inside the string structure
@ -464,20 +458,9 @@ Uint32 capacity
const string NormalProcess::readSTLString (uint32_t offset)
{
/*
MSVC++ string
ptr allocator
union
{
char[16] start;
char * start_ptr
}
Uint32 length
Uint32 capacity
*/
uint32_t start_offset = offset + 4;
uint32_t length = readDWord(offset + 20);
uint32_t capacity = readDWord(offset + 24);
uint32_t start_offset = offset + d->STLSTR_buf_off;
size_t length = readDWord(offset + d->STLSTR_size_off);
size_t capacity = readDWord(offset + d->STLSTR_cap_off);
char * temp = new char[capacity+1];
// read data from inside the string structure

@ -23,11 +23,11 @@ distribution.
*/
#include "Internal.h"
#include "DFMemInfoManager.h"
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/DFProcessEnumerator.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
using namespace DFHack;
@ -39,7 +39,7 @@ class DFHack::ProcessEnumerator::Private
{
public:
Private(){};
MemInfoManager *meminfo;
VersionInfoFactory *meminfo;
PROC_V Processes;
PID2PROC ProcMap;
Process *GetProcessObject(ProcessID ID);
@ -120,19 +120,19 @@ Process * BadProcesses::operator[](uint32_t index)
Process *ProcessEnumerator::Private::GetProcessObject(ProcessID ID)
{
Process *p1 = new SHMProcess(ID.pid,meminfo->meminfo);
Process *p1 = new SHMProcess(ID.pid,meminfo->versions);
if(p1->isIdentified())
return p1;
else
delete p1;
Process *p2 = new NormalProcess(ID.pid,meminfo->meminfo);
Process *p2 = new NormalProcess(ID.pid,meminfo->versions);
if(p2->isIdentified())
return p2;
else
delete p2;
#ifdef LINUX_BUILD
Process *p3 = new WineProcess(ID.pid,meminfo->meminfo);
Process *p3 = new WineProcess(ID.pid,meminfo->versions);
if(p3->isIdentified())
return p3;
else
@ -358,7 +358,7 @@ Process * ProcessEnumerator::operator[](uint32_t index)
ProcessEnumerator::ProcessEnumerator( string path_to_xml )
: d(new Private())
{
d->meminfo = new MemInfoManager(path_to_xml);
d->meminfo = new VersionInfoFactory(path_to_xml);
}
void ProcessEnumerator::purge()

@ -57,6 +57,10 @@ int (*alloc_matgloss_buffer_callback)(t_matgloss*, uint32_t) = NULL;
int (*alloc_descriptor_buffer_callback)(t_descriptor_color*, uint32_t) = NULL;
int (*alloc_matgloss_other_buffer_callback)(t_matglossOther*, uint32_t) = NULL;
int (*alloc_t_feature_buffer_callback)(t_feature*, uint32_t) = NULL;
int (*alloc_t_hotkey_buffer_callback)(t_hotkey*, uint32_t) = NULL;
int (*alloc_t_screen_buffer_callback)(t_screen*, uint32_t) = NULL;
int (*alloc_t_customWorkshop_buffer_callback)(t_customWorkshop*, uint32_t) = NULL;
int (*alloc_t_material_buffer_callback)(t_material*, uint32_t) = NULL;

File diff suppressed because it is too large Load Diff

@ -0,0 +1,630 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include <algorithm>
using namespace DFHack;
VersionInfoFactory::~VersionInfoFactory()
{
// for each stored version, delete
for(uint32_t i = 0; i < versions.size();i++)
{
delete versions[i];
}
versions.clear();
}
void VersionInfoFactory::ParseVTable(TiXmlElement* vtable, VersionInfo* mem)
{
TiXmlElement* pClassEntry;
TiXmlElement* pClassSubEntry;
/*
// check for rebase, do rebase if check positive
const char * rebase = vtable->Attribute("rebase");
if(rebase)
{
int32_t rebase_offset = strtol(rebase, NULL, 16);
mem->RebaseVTable(rebase_offset);
}
*/
// parse vtable entries
pClassEntry = vtable->FirstChildElement();
for(;pClassEntry;pClassEntry=pClassEntry->NextSiblingElement())
{
string type = pClassEntry->Value();
const char *cstr_name = pClassEntry->Attribute("name");
const char *cstr_vtable = pClassEntry->Attribute("vtable");
uint32_t vtable = 0;
if(cstr_vtable)
vtable = strtol(cstr_vtable, NULL, 16);
// it's a simple class
if(type== "class")
{
mem->setClass(cstr_name, vtable);
}
// it's a multi-type class
else if (type == "multiclass")
{
// get offset of the type variable
const char *cstr_typeoffset = pClassEntry->Attribute("typeoffset");
uint32_t typeoffset = 0;
if(cstr_typeoffset)
typeoffset = strtol(cstr_typeoffset, NULL, 16);
t_class * mclass = mem->setClass(cstr_name, vtable, typeoffset);
// parse class sub-entries
pClassSubEntry = pClassEntry->FirstChildElement();
for(;pClassSubEntry;pClassSubEntry=pClassSubEntry->NextSiblingElement())
{
type = pClassSubEntry->Value();
if(type== "class")
{
// type is a value loaded from type offset
cstr_name = pClassSubEntry->Attribute("name");
const char *cstr_value = pClassSubEntry->Attribute("type");
mem->setClassChild(mclass,cstr_name,cstr_value);
}
}
}
}
}
// 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 = currentElem->NextSiblingElement();
if(!og)
{
string fullname = currentGroup->getFullName() + cstr_name;
throw Error::MissingMemoryDefinition("group", fullname);
}
// 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 = currentElem->NextSiblingElement();
continue;
}
//cerr << "</Offsets>"<< endl;
}
void VersionInfoFactory::ParseBase (TiXmlElement* entry, VersionInfo* mem)
{
TiXmlElement* pElement;
TiXmlElement* pElement2nd;
const char *cstr_version = entry->Attribute("name");
if (!cstr_version)
throw Error::MemoryXmlBadAttribute("name");
mem->setVersion(cstr_version);
mem->setOS(VersionInfo::OS_BAD);
// process additional entries
pElement = entry->FirstChildElement()->ToElement();
for(;pElement;pElement=pElement->NextSiblingElement())
{
// only elements get processed
const char *cstr_type = pElement->Value();
std::string type = cstr_type;
if(type == "VTable")
{
ParseVTable(pElement, mem);
continue;
}
else if(type == "Offsets")
{
// we don't care about the descriptions here, do nothing
ParseOffsets(pElement, mem, true);
continue;
}
else if (type == "Professions")
{
pElement2nd = pElement->FirstChildElement("Profession");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Profession"))
{
const char * id = pElement2nd->Attribute("id");
const char * name = pElement2nd->Attribute("name");
// FIXME: missing some attributes here
if(id && name)
{
mem->setProfession(id,name);
}
else
{
// FIXME: this is crap, doesn't tell anything about the error
throw Error::MemoryXmlUnderspecifiedEntry(name);
}
}
}
else if (type == "Jobs")
{
pElement2nd = pElement->FirstChildElement("Job");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Job"))
{
const char * id = pElement2nd->Attribute("id");
const char * name = pElement2nd->Attribute("name");
if(id && name)
{
mem->setJob(id,name);
}
else
{
// FIXME: this is crap, doesn't tell anything about the error
throw Error::MemoryXmlUnderspecifiedEntry(name);
}
}
}
else if (type == "Skills")
{
pElement2nd = pElement->FirstChildElement("Skill");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Skill"))
{
const char * id = pElement2nd->Attribute("id");
const char * name = pElement2nd->Attribute("name");
if(id && name)
{
mem->setSkill(id,name);
}
else
{
// FIXME: this is crap, doesn't tell anything about the error
throw Error::MemoryXmlUnderspecifiedEntry(name);
}
}
}
else if (type == "Traits")
{
pElement2nd = pElement->FirstChildElement("Trait");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Trait"))
{
const char * id = pElement2nd->Attribute("id");
const char * name = pElement2nd->Attribute("name");
const char * lvl0 = pElement2nd->Attribute("level_0");
const char * lvl1 = pElement2nd->Attribute("level_1");
const char * lvl2 = pElement2nd->Attribute("level_2");
const char * lvl3 = pElement2nd->Attribute("level_3");
const char * lvl4 = pElement2nd->Attribute("level_4");
const char * lvl5 = pElement2nd->Attribute("level_5");
if(id && name && lvl0 && lvl1 && lvl2 && lvl3 && lvl4 && lvl5)
{
mem->setTrait(id, name, lvl0, lvl1, lvl2, lvl3, lvl4, lvl5);
}
else
{
// FIXME: this is crap, doesn't tell anything about the error
throw Error::MemoryXmlUnderspecifiedEntry(name);
}
}
}
else if (type == "Labors")
{
pElement2nd = pElement->FirstChildElement("Labor");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Labor"))
{
const char * id = pElement2nd->Attribute("id");
const char * name = pElement2nd->Attribute("name");
if(id && name)
{
mem->setLabor(id,name);
}
else
{
// FIXME: this is crap, doesn't tell anything about the error
throw Error::MemoryXmlUnderspecifiedEntry(name);
}
}
}
else if (type == "Levels")
{
pElement2nd = pElement->FirstChildElement("Level");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Level"))
{
const char * id = pElement2nd->Attribute("id");
const char * name = pElement2nd->Attribute("name");
const char * nextlvl = pElement2nd->Attribute("xpNxtLvl");
if(id && name && nextlvl)
{
mem->setLevel(id, name, nextlvl);
}
else
{
// FIXME: this is crap, doesn't tell anything about the error
throw Error::MemoryXmlUnderspecifiedEntry(name);
}
}
}
else if (type == "Moods")
{
pElement2nd = pElement->FirstChildElement("Mood");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Mood"))
{
const char * id = pElement2nd->Attribute("id");
const char * name = pElement2nd->Attribute("name");
if(id && name)
{
mem->setMood(id, name);
}
else
{
// FIXME: this is crap, doesn't tell anything about the error
throw Error::MemoryXmlUnderspecifiedEntry(name);
}
}
}
else
{
//FIXME: only log, not hard error
//throw Error::MemoryXmlUnknownType(type.c_str());
}
} // for
} // method
void VersionInfoFactory::EvalVersion(string base, VersionInfo * mem)
{
if(knownVersions.find(base) != knownVersions.end())
{
v_descr & desc = knownVersions[base];
if (!desc.second)
{
VersionInfo * newmem = new VersionInfo();
ParseVersion(desc.first, newmem);
desc.second = newmem;
}
mem->copy(desc.second);
}
}
void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem)
{
TiXmlElement* pMemEntry;
const char *cstr_name = entry->Attribute("name");
const char *cstr_os = entry->Attribute("os");
const char *cstr_base = entry->Attribute("base");
const char *cstr_rebase = entry->Attribute("rebase");
if(cstr_base)
{
string base = cstr_base;
EvalVersion(base, mem);
}
if (!cstr_name)
throw Error::MemoryXmlBadAttribute("name");
if (!cstr_os)
throw Error::MemoryXmlBadAttribute("os");
string os = cstr_os;
mem->setVersion(cstr_name);
mem->setOS(cstr_os);
// offset inherited addresses by 'rebase'.
int32_t rebase = 0;
if(cstr_rebase)
{
rebase = mem->getBase() + strtol(cstr_rebase, NULL, 16);
mem->RebaseAddresses(rebase);
}
//set base to default, we're overwriting this because the previous rebase could cause havoc on Vista/7
if(os == "windows")
{
// set default image base. this is fixed for base relocation later
mem->setBase(0x400000);
}
else if(os == "linux")
{
// this is wrong... I'm not going to do base image relocation on linux though.
// users are free to use a sane kernel that doesn't do this kind of **** by default
mem->setBase(0x0);
}
else
{
throw Error::MemoryXmlBadAttribute("os");
}
// process additional entries
//cout << "Entry " << cstr_version << " " << cstr_os << endl;
pMemEntry = entry->FirstChildElement()->ToElement();
for(;pMemEntry;pMemEntry=pMemEntry->NextSiblingElement())
{
string type, name, value;
const char *cstr_type = pMemEntry->Value();
type = cstr_type;
// check for missing parts
if(type == "VTable")
{
ParseVTable(pMemEntry, mem);
continue;
}
else if(type == "Offsets")
{
ParseOffsets(pMemEntry, mem);
continue;
}
else if (type == "MD5")
{
const char *cstr_value = pMemEntry->Attribute("value");
if(!cstr_value)
throw Error::MemoryXmlUnderspecifiedEntry(cstr_name);
mem->setMD5(cstr_value);
}
else if (type == "PETimeStamp")
{
const char *cstr_value = pMemEntry->Attribute("value");
if(!cstr_value)
throw Error::MemoryXmlUnderspecifiedEntry(cstr_name);
mem->setPE(strtol(cstr_value, 0, 16));
}
} // for
} // method
VersionInfoFactory::VersionInfoFactory(string path_to_xml)
{
error = false;
loadFile(path_to_xml);
}
// load the XML file with offsets
bool VersionInfoFactory::loadFile(string path_to_xml)
{
TiXmlDocument doc( path_to_xml.c_str() );
//bool loadOkay = doc.LoadFile();
if (!doc.LoadFile())
{
error = true;
throw Error::MemoryXmlParse(doc.ErrorDesc(), doc.ErrorId(), doc.ErrorRow(), doc.ErrorCol());
}
TiXmlHandle hDoc(&doc);
TiXmlElement* pElem;
TiXmlHandle hRoot(0);
VersionInfo *mem;
// block: name
{
pElem=hDoc.FirstChildElement().Element();
// should always have a valid root but handle gracefully if it does
if (!pElem)
{
error = true;
throw Error::MemoryXmlNoRoot();
}
string m_name=pElem->Value();
if(m_name != "DFHack")
{
error = true;
throw Error::MemoryXmlNoRoot();
}
// save this for later
hRoot=TiXmlHandle(pElem);
}
// transform elements
{
// trash existing list
for(uint32_t i = 0; i < versions.size(); i++)
{
delete versions[i];
}
versions.clear();
// For each base version
TiXmlElement* pMemInfo=hRoot.FirstChild( "Base" ).Element();
map <string ,TiXmlElement *> map_pNamedEntries;
vector <string> v_sEntries;
for( ; pMemInfo; pMemInfo=pMemInfo->NextSiblingElement("Base"))
{
const char *name = pMemInfo->Attribute("name");
if(name)
{
string str_name = name;
VersionInfo *base = new VersionInfo();
mem = new VersionInfo();
ParseBase( pMemInfo , mem );
knownVersions[str_name] = v_descr (pMemInfo, mem);
}
}
// For each derivative version
pMemInfo=hRoot.FirstChild( "Version" ).Element();
for( ; pMemInfo; pMemInfo=pMemInfo->NextSiblingElement("Version"))
{
const char *name = pMemInfo->Attribute("name");
if(name)
{
string str_name = name;
knownVersions[str_name] = v_descr (pMemInfo, NULL);
v_sEntries.push_back(str_name);
}
}
// Parse the versions
for(uint32_t i = 0; i< v_sEntries.size();i++)
{
//FIXME: add a set of entries processed in a step of this cycle, use it to check for infinite loops
string & name = v_sEntries[i];
v_descr & desc = knownVersions[name];
if(!desc.second)
{
VersionInfo *version = new VersionInfo();
ParseVersion( desc.first , version );
versions.push_back(version);
}
}
// process found things here
}
error = false;
return true;
}

@ -17,7 +17,7 @@
#include "dfhack/DFError.h"
#include "dfhack/DFContextManager.h"
#include "dfhack/DFContext.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFTypes.h"
@ -32,6 +32,7 @@
#include "dfhack/modules/Items.h"
#include "dfhack/modules/Vegetation.h"
#include "dfhack/modules/Maps.h"
#include "dfhack/modules/Gui.h"
/*
* This is a header full of ugly, volatile things.

@ -29,6 +29,7 @@ distribution.
#include "dfhack/DFTypes.h"
#include "dfhack/modules/Maps.h"
#include "dfhack/modules/Materials.h"
#include "dfhack/modules/Position.h"
#include "dfhack/DFTileTypes.h"
#ifdef __cplusplus
@ -49,6 +50,10 @@ DFHACK_EXPORT extern int (*alloc_matgloss_buffer_callback)(t_matgloss*, uint32_t
DFHACK_EXPORT extern int (*alloc_descriptor_buffer_callback)(t_descriptor_color*, uint32_t);
DFHACK_EXPORT extern int (*alloc_matgloss_other_buffer_callback)(t_matglossOther*, uint32_t);
DFHACK_EXPORT extern int (*alloc_t_feature_buffer_callback)(t_feature*, uint32_t);
DFHACK_EXPORT extern int (*alloc_t_hotkey_buffer_callback)(t_hotkey*, uint32_t);
DFHACK_EXPORT extern int (*alloc_t_screen_buffer_callback)(t_screen*, uint32_t);
struct t_customWorkshop
{
uint32_t index;

@ -54,16 +54,35 @@ Buffer Callback List
- alloc_ubyte_buffer_callback(uint8_t*, uint32_t)
- alloc_ushort_buffer_callback(uint16_t*, uint32_t)
- alloc_uint_buffer_callback(uint32_t*, uint32_t)
- alloc_char_buffer_callback(char* uint32_t)
- alloc_matgloss_buffer_callback(t_matgloss*, uint32_t)
- alloc_descriptor_buffer_callback(t_descriptor_color*, uint32_t)
- alloc_matgloss_other_buffer_callback(t_matglossOther*, uint32_t)
- alloc_vein_buffer_callback(t_vein*, uint32_t)
- alloc_t_feature_buffer_callback(t_feature*, uint32_t)
- alloc_t_hotkey_buffer_callback(t_hotkey*, uint32_t)
- alloc_t_screen_buffer_callback(t_screen*, uint32_t)
- alloc_frozenliquidvein_buffer_callback(t_frozenliquidvein*, uint32_t)
- alloc_spattervein_buffer_callback(t_spattervein*, uint32_t)
Templates Make My Life Harder
-------------------------------
Three dfhack structures (t_colormodifier, t_creaturecaste, and t_creaturetype) contain vectors, which (obviously) don't work in C. Therefore, these structures have C versions that replace the vector with a buffer and length, but are otherwise identical to their C++ counterparts. For each structure, there are three associated callbacks. One initializes an empty instance of the structure, one initializes an instance with values passed in, and one allocates a buffer in the same manner as the other allocators.
Several dfhack structures contain vectors, which (obviously) don't work in C. Therefore, these structures have C versions that replace the vector with a buffer and length, but are otherwise identical to their C++ counterparts. For each structure, there are three associated callbacks. One initializes an empty instance of the structure (*alloc_empty_colormodifier_callback*, for instance), one initializes an instance with values passed in (*alloc_colormodifier_callback*), and one allocates a buffer in the same manner as the other allocators (*alloc_colormodifier_buffer_callback*).
The replaced structures and their callbacks are as follows.
- c_colormodifier
* alloc_empty_colormodifier_callback(c_colormodifier*)
* alloc_colormodifier_callback(c_colormodifier*, const char*, uint32_t)
* alloc_colormodifier_buffer_callback(c_colormodifier*, uint32_t)
- c_creaturecaste
* alloc_empty_creaturecaste_callback(c_creaturecaste*)
* alloc_creaturecaste_callback(c_creaturecaste*, const char*, const char*, const char*, const char*, uint32_t, uint32_t)
* alloc_creaturecaste_buffer_callback(c_creaturecaste*, uint32_t)
- c_creaturetype
* alloc_empty_creaturetype_callback(c_creaturetype*)
* alloc_creaturetype_callback(c_creaturetype*, const char*, uint32_t, uint32_t, uint8_t, uint16_t, uint16_t, uint16_t)
* alloc_creaturetype_buffer_callback(c_creaturetype*, uint32_t)
A Small Callback Example In Python
-------------------------------------

@ -38,6 +38,7 @@ DFHACK_EXPORT int Gui_Finish(DFHackObject* gui);
DFHACK_EXPORT int Gui_ReadPauseState(DFHackObject* gui);
DFHACK_EXPORT int Gui_ReadViewScreen(DFHackObject* gui, t_viewscreen* viewscreen);
DFHACK_EXPORT int Gui_ReadMenuState(DFHackObject* gui, uint32_t* menuState);
#ifdef __cplusplus
}

@ -36,6 +36,8 @@ extern "C" {
DFHACK_EXPORT int Maps_Start(DFHackObject* maps);
DFHACK_EXPORT int Maps_Finish(DFHackObject* maps);
DFHACK_EXPORT t_feature* Maps_ReadGlobalFeatures(DFHackObject* maps);
DFHACK_EXPORT void Maps_getSize(DFHackObject* maps, uint32_t* x, uint32_t* y, uint32_t* z);
DFHACK_EXPORT int Maps_isValidBlock(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z);

@ -44,6 +44,7 @@ DFHACK_EXPORT int Materials_ReadOthers(DFHackObject* mat);
DFHACK_EXPORT void Materials_ReadAllMaterials(DFHackObject* mat);
DFHACK_EXPORT const char* Materials_getType(DFHackObject* mat, t_material* material);
DFHACK_EXPORT const char* Materials_getDescription(DFHackObject* mat, t_material* material);
DFHACK_EXPORT int Materials_getInorganicSize(DFHackObject* mat);

@ -38,8 +38,12 @@ DFHACK_EXPORT int Position_setViewCoords(DFHackObject* pos, const int32_t x, con
DFHACK_EXPORT int Position_getCursorCoords(DFHackObject* pos, int32_t* x, int32_t* y, int32_t* z);
DFHACK_EXPORT int Position_setCursorCoords(DFHackObject* pos, const int32_t x, const int32_t y, const int32_t z);
DFHACK_EXPORT t_hotkey* Position_ReadHotkeys(DFHackObject* pos);
DFHACK_EXPORT int Position_getWindowSize(DFHackObject* pos, int32_t* width, int32_t* height);
DFHACK_EXPORT t_screen* Position_getScreenTiles(DFHackObject* pos, int32_t width, int32_t height);
#ifdef __cplusplus
}
#endif

@ -40,6 +40,9 @@ DFHACK_EXPORT int World_ReadCurrentYear(DFHackObject* world, uint32_t* year);
DFHACK_EXPORT int World_ReadCurrentMonth(DFHackObject* world, uint32_t* month);
DFHACK_EXPORT int World_ReadCurrentDay(DFHackObject* world, uint32_t* day);
DFHACK_EXPORT int World_ReadCurrentWeather(DFHackObject* world, uint8_t* weather);
DFHACK_EXPORT int World_WriteCurrentWeather(DFHackObject* world, uint8_t weather);
#ifdef __cplusplus
}
#endif

@ -40,7 +40,7 @@ namespace DFHack
class Vegetation;
class Buildings;
class Constructions;
class memory_info;
class VersionInfo;
class DFContextShared;
class WindowIO;
class Process;
@ -71,7 +71,7 @@ namespace DFHack
/// forces resume on Windows. This can be a bad thing with multiple tools running!
bool ForceResume();
memory_info *getMemoryInfo();
VersionInfo *getMemoryInfo();
Process* getProcess();
void ReadRaw (const uint32_t offset, const uint32_t size, uint8_t *target);

@ -34,7 +34,12 @@ namespace DFHack
{
namespace Error
{
class DFHACK_EXPORT NoProcess : public std::exception
/*
* our wrapper for the C++ exception. used to differentiate
* the whole array of DFHack exceptions from the rest
*/
class DFHACK_EXPORT All : public std::exception{};
class DFHACK_EXPORT NoProcess : public All
{
public:
virtual const char* what() const throw()
@ -43,7 +48,7 @@ namespace DFHack
}
};
class DFHACK_EXPORT CantAttach : public std::exception
class DFHACK_EXPORT CantAttach : public All
{
public:
virtual const char* what() const throw()
@ -52,7 +57,7 @@ namespace DFHack
}
};
class DFHACK_EXPORT NoMapLoaded : public std::exception
class DFHACK_EXPORT NoMapLoaded : public All
{
public:
virtual const char* what() const throw()
@ -61,7 +66,7 @@ namespace DFHack
}
};
class DFHACK_EXPORT BadMapDimensions : public std::exception
class DFHACK_EXPORT BadMapDimensions : public All
{
public:
BadMapDimensions(uint32_t& _x, uint32_t& _y) : x(_x), y(_y) {}
@ -75,13 +80,13 @@ namespace DFHack
};
// a call to DFHack::mem_info::get* failed
class DFHACK_EXPORT MissingMemoryDefinition : public std::exception
class DFHACK_EXPORT MissingMemoryDefinition : public All
{
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;
s << "memory definition missing: type " << type << " key " << key;
s << "memory object not declared: type=" << type << " key=" << key;
full = s.str();
}
// Used by functios using integer keys, such as getTrait
@ -92,24 +97,44 @@ namespace DFHack
key = s1.str();
std::stringstream s;
s << "memory definition missing: type " << type << " key " << key;
s << "memory object not declared: type=" << type << " key=" << key;
full = s.str();
}
virtual ~MissingMemoryDefinition() throw(){};
// (perhaps it should be an enum, but this is intended for easy printing/logging)
// type can be any of the following:
//
// address
// offset
// hexvalue
// string
// profession
// job
// skill
// trait
// traitname
// labor
std::string full;
const std::string type;
std::string key;
virtual const char* what() const throw()
{
return full.c_str();
}
};
// a call to DFHack::mem_info::get* failed
class DFHACK_EXPORT UnsetMemoryDefinition : public All
{
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;
const std::string type;
std::string key;
@ -121,7 +146,7 @@ namespace DFHack
};
// Syntax errors and whatnot, the xml cant be read
class DFHACK_EXPORT MemoryXmlParse : public std::exception
class DFHACK_EXPORT MemoryXmlParse : public All
{
public:
MemoryXmlParse(const char* _desc, int _id, int _row, int _col)
@ -147,7 +172,7 @@ namespace DFHack
}
};
class DFHACK_EXPORT MemoryXmlBadAttribute : public std::exception
class DFHACK_EXPORT MemoryXmlBadAttribute : public All
{
public:
MemoryXmlBadAttribute(const char* _attr) : attr(_attr)
@ -167,7 +192,7 @@ namespace DFHack
}
};
class DFHACK_EXPORT MemoryXmlNoRoot : public std::exception
class DFHACK_EXPORT MemoryXmlNoRoot : public All
{
public:
MemoryXmlNoRoot() {}
@ -180,7 +205,7 @@ namespace DFHack
}
};
class DFHACK_EXPORT MemoryXmlNoDFExtractor : public std::exception
class DFHACK_EXPORT MemoryXmlNoDFExtractor : public All
{
public:
MemoryXmlNoDFExtractor(const char* _name) : name(_name)
@ -200,7 +225,7 @@ namespace DFHack
}
};
class DFHACK_EXPORT MemoryXmlUnderspecifiedEntry : public std::exception
class DFHACK_EXPORT MemoryXmlUnderspecifiedEntry : public All
{
public:
MemoryXmlUnderspecifiedEntry(const char * _where) : where(_where)
@ -218,7 +243,7 @@ namespace DFHack
}
};
class DFHACK_EXPORT MemoryXmlUnknownType : public std::exception
class DFHACK_EXPORT MemoryXmlUnknownType : public All
{
public:
MemoryXmlUnknownType(const char* _type) : type(_type)
@ -238,7 +263,7 @@ namespace DFHack
}
};
class DFHACK_EXPORT SHMServerDisappeared : public std::exception
class DFHACK_EXPORT SHMServerDisappeared : public All
{
public:
SHMServerDisappeared(){}
@ -248,7 +273,7 @@ namespace DFHack
return "The server process has disappeared";
}
};
class DFHACK_EXPORT SHMLockingError : public std::exception
class DFHACK_EXPORT SHMLockingError : public All
{
public:
SHMLockingError(const char* _type) : type(_type)
@ -267,7 +292,7 @@ namespace DFHack
return full.c_str();
}
};
class DFHACK_EXPORT MemoryAccessDenied : public std::exception
class DFHACK_EXPORT MemoryAccessDenied : public All
{
public:
MemoryAccessDenied() {}
@ -277,7 +302,7 @@ namespace DFHack
return "SHM ACCESS DENIED";
}
};
class DFHACK_EXPORT SHMVersionMismatch : public std::exception
class DFHACK_EXPORT SHMVersionMismatch : public All
{
public:
SHMVersionMismatch() {}
@ -287,7 +312,7 @@ namespace DFHack
return "SHM VERSION MISMATCH";
}
};
class DFHACK_EXPORT SHMAttachFailure : public std::exception
class DFHACK_EXPORT SHMAttachFailure : public All
{
public:
SHMAttachFailure() {}
@ -297,7 +322,7 @@ namespace DFHack
return "SHM ATTACH FAILURE";
}
};
class DFHACK_EXPORT ModuleNotInitialized : public std::exception
class DFHACK_EXPORT ModuleNotInitialized : public All
{
public:
ModuleNotInitialized() {}

@ -12,7 +12,7 @@
using namespace std;
#include <dfhack/DFProcess.h>
#include <dfhack/DFMemInfo.h>
#include <dfhack/VersionInfo.h>
#include <dfhack/DFVector.h>
void DumpObjStr0Vector (const char * name, DFHack::Process *p, uint32_t addr)

@ -31,7 +31,7 @@ distribution.
namespace DFHack
{
class memory_info;
class VersionInfo;
class Process;
class Window;
@ -160,7 +160,7 @@ namespace DFHack
virtual void getMemRanges(std::vector<t_memrange> & ranges ) = 0;
/// get the flattened Memory.xml entry of this process
virtual memory_info *getDescriptor() = 0;
virtual VersionInfo *getDescriptor() = 0;
/// get the DF Process ID
virtual int getPID() = 0;
/// get module index by name and version. bool 1 = error
@ -182,7 +182,7 @@ namespace DFHack
private:
Private * const d;
public:
NormalProcess(uint32_t pid, std::vector <memory_info *> & known_versions);
NormalProcess(uint32_t pid, std::vector <VersionInfo *> & known_versions);
~NormalProcess();
bool attach();
bool detach();
@ -228,7 +228,7 @@ namespace DFHack
bool getThreadIDs(std::vector<uint32_t> & threads );
void getMemRanges(std::vector<t_memrange> & ranges );
memory_info *getDescriptor();
VersionInfo *getDescriptor();
int getPID();
// get module index by name and version. bool 1 = error
bool getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT) { OUTPUT=0; return false;};
@ -246,7 +246,7 @@ namespace DFHack
Private * const d;
public:
SHMProcess(uint32_t PID, std::vector <memory_info *> & known_versions);
SHMProcess(uint32_t PID, std::vector <VersionInfo *> & known_versions);
~SHMProcess();
// Set up stuff so we can read memory
bool attach();
@ -293,7 +293,7 @@ namespace DFHack
bool getThreadIDs(std::vector<uint32_t> & threads );
void getMemRanges(std::vector<t_memrange> & ranges );
memory_info *getDescriptor();
VersionInfo *getDescriptor();
int getPID();
// get module index by name and version. bool 1 = error
bool getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT);
@ -311,7 +311,7 @@ namespace DFHack
Private * const d;
public:
WineProcess(uint32_t pid, std::vector <memory_info *> & known_versions);
WineProcess(uint32_t pid, std::vector <VersionInfo *> & known_versions);
~WineProcess();
bool attach();
bool detach();
@ -357,7 +357,7 @@ namespace DFHack
bool getThreadIDs(std::vector<uint32_t> & threads );
void getMemRanges(std::vector<t_memrange> & ranges );
memory_info *getDescriptor();
VersionInfo *getDescriptor();
int getPID();
// get module index by name and version. bool 1 = error
bool getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT) {OUTPUT=0; return false;};

@ -30,7 +30,7 @@ distribution.
namespace DFHack
{
class memory_info;
class VersionInfo;
class Process;
class BadProcesses;
/**

@ -29,6 +29,7 @@ distribution.
#include "DFExport.h"
namespace DFHack
{
class VersionInfo;
class Process;
template <class T>
class DFHACK_EXPORT DfVector
@ -41,8 +42,8 @@ namespace DFHack
DfVector(Process * p, uint32_t address)
{
uint32_t triplet[3];
memory_info * mem = p->getDescriptor();
uint32_t offs = mem->getOffset("vector_triplet");
VersionInfo * mem = p->getDescriptor();
uint32_t offs = mem->getGroup("vector")->getOffset("start");
p->read(address + offs, sizeof(triplet), (uint8_t *) &triplet);
_start = triplet[0];

@ -28,6 +28,7 @@ distribution.
#include "DFPragma.h"
#include "DFExport.h"
#include "dfhack/DFTypes.h"
#include <sys/types.h>
namespace DFHack
{
@ -35,23 +36,67 @@ namespace DFHack
* Stubs
*/
class Process;
class XMLPP;
struct t_class;
class VersionInfoPrivate;
class OffsetGroupPrivate;
class DFHACK_EXPORT memory_info
/*
* Offset Group
*/
class DFHACK_EXPORT OffsetGroup
{
protected:
OffsetGroupPrivate * OGd;
public:
OffsetGroup();
OffsetGroup(const std::string & _name, OffsetGroup * parent = 0);
~OffsetGroup();
void copy(const OffsetGroup * old); // recursive
void RebaseAddresses( int32_t offset ); // recursive
void createOffset (const std::string & key);
void createAddress (const std::string & key);
void createHexValue (const std::string & key);
void createString (const std::string & key);
OffsetGroup * createGroup ( const std::string & name );
int32_t getOffset (const std::string & key);
uint32_t getAddress (const std::string & key);
uint32_t getHexValue (const std::string & key);
std::string getString (const std::string & key);
OffsetGroup * getGroup ( const std::string & name );
void setOffset (const std::string & key, const std::string & value);
void setAddress (const std::string & key, const std::string & value);
void setHexValue (const std::string & key, const std::string & value);
void setString (const std::string & key, const std::string & value);
std::string PrintOffsets(int indentation);
std::string getName();
std::string getFullName();
OffsetGroup * getParent();
};
/*
* Version Info
*/
class DFHACK_EXPORT VersionInfo : public OffsetGroup
{
private:
class Private;
Private * d;
VersionInfoPrivate * d;
public:
enum OSType
{
OS_WINDOWS,
OS_LINUX,
OS_APPLE,
OS_BAD
};
memory_info();
memory_info(const memory_info&);
~memory_info();
VersionInfo();
VersionInfo(const VersionInfo&);
void copy(const DFHack::VersionInfo* old);
~VersionInfo();
void RebaseAddresses(const int32_t new_base);
void RebaseAll(const int32_t new_base);
@ -59,12 +104,11 @@ namespace DFHack
void setBase (const std::string&);
void setBase (const uint32_t);
int32_t getOffset (const std::string&);
uint32_t getAddress (const std::string&);
uint32_t getHexValue (const std::string&);
int32_t getOffset (const char *);
uint32_t getAddress (const char *);
uint32_t getHexValue (const char *);
void setMD5 (const std::string & _md5);
std::string getMD5();
void setPE (uint32_t PE_);
uint32_t getPE();
std::string getMood(const uint32_t moodID);
std::string getString (const std::string&);
@ -75,6 +119,7 @@ namespace DFHack
std::string getTraitName(const uint32_t) const;
std::string getLabor (const uint32_t);
std::vector< std::vector<std::string> > const& getAllTraits();
std::map<uint32_t, std::string> const& getAllLabours();
DFHack::t_level getLevelInfo(const uint32_t level) const;
@ -87,21 +132,7 @@ namespace DFHack
void setOS(const OSType);
OSType getOS() const;
void setOffset (const std::string &, const int32_t);
void setAddress (const std::string &, const uint32_t);
void setHexValue (const std::string &, const uint32_t);
void setOffset (const std::string &, const char *);
void setAddress (const std::string &, const char *);
void setHexValue (const std::string &, const char *);
void setString (const std::string &, const char *);
void setOffset (const std::string &, const std::string &);
void setAddress (const std::string &, const std::string &);
void setHexValue (const std::string &, const std::string &);
void setString (const std::string &, const std::string &);
void setProfession(const std::string &, const std::string &);
void setProfession(const std::string & id, const std::string & name);
void setJob(const std::string &, const std::string &);
void setSkill(const std::string &, const std::string &);
void setTrait(const std::string &, const std::string &, const std::string &,

@ -26,25 +26,33 @@ distribution.
#define MEMINFO_MANAGER_H_INCLUDED
#include "dfhack/DFPragma.h"
#include "dfhack/DFExport.h"
class TiXmlElement;
namespace DFHack
{
class memory_info;
class MemInfoManager
class VersionInfo;
class DFHACK_EXPORT VersionInfoFactory
{
friend class ProcessEnumerator;
public:
MemInfoManager(string path_to_xml);
~MemInfoManager();
VersionInfoFactory(std::string path_to_xml);
~VersionInfoFactory();
// memory info entries loaded from a file
bool loadFile( string path_to_xml);
bool loadFile( std::string path_to_xml);
bool isInErrorState() const {return error;};
std::vector<memory_info*> meminfo;
std::vector<VersionInfo*> versions;
private:
void ParseVTable(TiXmlElement* vtable, memory_info* mem);
void ParseEntry (TiXmlElement* entry, memory_info* mem, map <string ,TiXmlElement *>& knownEntries);
void ParseVTable(TiXmlElement* vtable, VersionInfo* mem);
void ParseBase (TiXmlElement* base, VersionInfo* mem);
void ParseVersion (TiXmlElement* version, VersionInfo* mem);
// copy version 'base' to 'target' or throw
void EvalVersion(std::string base, VersionInfo* target);
void ParseOffsets(TiXmlElement* elem, VersionInfo* target, bool initial = false);
bool error;
typedef std::pair < TiXmlElement *, VersionInfo *> v_descr;
std::map <std::string , v_descr > knownVersions;
};
}

@ -5,6 +5,7 @@
*/
#include "dfhack/DFExport.h"
#include "dfhack/DFModule.h"
#include "dfhack/modules/Items.h"
namespace DFHack
{
/*
@ -374,6 +375,8 @@ namespace DFHack
const uint16_t x2, const uint16_t y2,const uint16_t z2);
bool ReadCreature(const int32_t index, t_creature & furball);
bool ReadJob(const t_creature * furball, std::vector<t_material> & mat);
bool ReadInventoryIdx(const uint32_t index, std::vector<uint32_t> & item);
bool ReadInventoryPtr(const uint32_t index, std::vector<uint32_t> & item);
/* Getters */
uint32_t GetDwarfRaceIndex ( void );

@ -22,6 +22,8 @@ namespace DFHack
///true if paused, false if not
bool ReadPauseState();
///true if paused, false if not
void SetPauseState(bool paused);
/// read the DF menu view state (stock screen, unit screen, other screens
bool ReadViewScreen(t_viewscreen &);
/// read the DF menu state (designation menu ect)

@ -1,5 +1,10 @@
#ifndef CL_MOD_ITEMS
#define CL_MOD_ITEMS
/*
* DEPRECATED, DO NOT USE UNTIL FURTHER NOTICE!
**/
/*
* Creatures
*/

@ -9,6 +9,12 @@
namespace DFHack
{
enum WeatherType
{
CLEAR,
RAINING,
SNOWING
};
class DFContextShared;
class DFHACK_EXPORT World : public Module
{
@ -23,6 +29,8 @@ namespace DFHack
uint32_t ReadCurrentYear();
uint32_t ReadCurrentMonth();
uint32_t ReadCurrentDay();
uint8_t ReadCurrentWeather();
void SetCurrentWeather(uint8_t weather);
private:
struct Private;

@ -25,7 +25,7 @@ distribution.
#include "Internal.h"
#include "ContextShared.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFTypes.h"
@ -71,12 +71,13 @@ Buildings::Buildings(DFContextShared * d_)
d->d = d_;
d->owner = d_->p;
d->Inited = d->Started = false;
memory_info * mem = d->d->offset_descriptor;
d->custom_workshop_vector = mem->getAddress("custom_workshop_vector");
d->building_custom_workshop_type = mem->getOffset("building_custom_workshop_type");
d->custom_workshop_type = mem->getOffset("custom_workshop_type");
d->custom_workshop_name = mem->getOffset("custom_workshop_name");
d->buildings_vector = mem->getAddress ("buildings_vector");
VersionInfo * mem = d->d->offset_descriptor;
OffsetGroup * OG_build = mem->getGroup("Buildings");
d->custom_workshop_vector = OG_build->getAddress("custom_workshop_vector");
d->building_custom_workshop_type = OG_build->getOffset("building_custom_workshop_type");
d->custom_workshop_type = OG_build->getOffset("custom_workshop_type");
d->custom_workshop_name = OG_build->getOffset("custom_workshop_name");
d->buildings_vector = OG_build->getAddress ("buildings_vector");
mem->resolveClassnameToClassID("building_custom_workshop", d->custom_workshop_id);
d->Inited = true;
}

@ -25,7 +25,7 @@ distribution.
#include "Internal.h"
#include "ContextShared.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFTypes.h"
@ -52,8 +52,8 @@ Constructions::Constructions(DFContextShared * d_)
d->owner = d_->p;
d->p_cons = 0;
d->Inited = d->Started = false;
memory_info * mem = d->d->offset_descriptor;
d->construction_vector = mem->getAddress ("construction_vector");
VersionInfo * mem = d->d->offset_descriptor;
d->construction_vector = mem->getGroup("Constructions")->getAddress ("vector");
d->Inited = true;
}

@ -25,7 +25,7 @@ distribution.
#include "Internal.h"
#include "ContextShared.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFError.h"
@ -50,10 +50,16 @@ struct Creatures::Private
{
bool Inited;
bool Started;
bool Ft_basic;
bool Ft_advanced;
bool Ft_jobs;
bool Ft_soul;
Creatures2010::creature_offsets creatures;
uint32_t creature_module;
uint32_t dwarf_race_index_addr;
uint32_t dwarf_civ_id_addr;
OffsetGroup * OG_jobs;
OffsetGroup * OG_job_mats;
DfVector <uint32_t> *p_cre;
DFContextShared *d;
Process *owner;
@ -67,67 +73,72 @@ Creatures::Creatures(DFContextShared* _d)
d->Inited = false;
d->Started = false;
d->d->InitReadNames(); // throws on error
VersionInfo * minfo = d->d->offset_descriptor;
OffsetGroup *OG_Creatures = minfo->getGroup("Creatures");
OffsetGroup *OG_creature = OG_Creatures->getGroup("creature");
OffsetGroup *OG_creature_ex = OG_creature->getGroup("advanced");
OffsetGroup *OG_soul = OG_Creatures->getGroup("soul");
OffsetGroup * OG_name = minfo->getGroup("name");
d->OG_jobs = OG_Creatures->getGroup("job");
d->OG_job_mats = d->OG_jobs->getGroup("material");
d->Ft_basic = d->Ft_advanced = d->Ft_jobs = d->Ft_soul = false;
Creatures2010::creature_offsets &creatures = d->creatures;
try
{
memory_info * minfo = d->d->offset_descriptor;
Creatures2010::creature_offsets &creatures = d->creatures;
creatures.vector = minfo->getAddress ("creature_vector");
creatures.pos_offset = minfo->getOffset ("creature_position");
creatures.profession_offset = minfo->getOffset ("creature_profession");
creatures.custom_profession_offset = minfo->getOffset ("creature_custom_profession");
creatures.race_offset = minfo->getOffset ("creature_race");
creatures.civ_offset = minfo->getOffset ("creature_civ");
creatures.flags1_offset = minfo->getOffset ("creature_flags1");
creatures.flags2_offset = minfo->getOffset ("creature_flags2");
creatures.name_offset = minfo->getOffset ("creature_name");
creatures.sex_offset = minfo->getOffset ("creature_sex");
creatures.caste_offset = minfo->getOffset ("creature_caste");
creatures.id_offset = minfo->getOffset ("creature_id");
creatures.labors_offset = minfo->getOffset ("creature_labors");
creatures.happiness_offset = minfo->getOffset ("creature_happiness");
creatures.artifact_name_offset = minfo->getOffset("creature_artifact_name");
creatures.soul_vector_offset = minfo->getOffset("creature_soul_vector");
creatures.default_soul_offset = minfo->getOffset("creature_default_soul");
creatures.physical_offset = minfo->getOffset("creature_physical");
creatures.mood_offset = minfo->getOffset("creature_mood");
creatures.mood_skill_offset = minfo->getOffset("creature_mood_skill");
creatures.pickup_equipment_bit = minfo->getOffset("creature_pickup_equipment_bit");
creatures.current_job_offset = minfo->getOffset("creature_current_job");
// soul offsets
creatures.soul_skills_vector_offset = minfo->getOffset("soul_skills_vector");
creatures.soul_mental_offset = minfo->getOffset("soul_mental");
creatures.soul_traits_offset = minfo->getOffset("soul_traits");
// appearance
creatures.appearance_vector_offset = minfo->getOffset("creature_appearance_vector");
//birth
creatures.birth_year_offset = minfo->getOffset("creature_birth_year");
creatures.birth_time_offset = minfo->getOffset("creature_birth_time");
// name offsets for the creature module
creatures.name_firstname_offset = minfo->getOffset("name_firstname");
creatures.name_nickname_offset = minfo->getOffset("name_nickname");
creatures.name_words_offset = minfo->getOffset("name_words");
d->dwarf_race_index_addr = minfo->getAddress("dwarf_race_index");
d->dwarf_civ_id_addr = minfo->getAddress("dwarf_civ_id");
/*
// upload offsets to the SHM
if(p->getModuleIndex("Creatures2010",1,d->creature_module))
// Creatures
creatures.vector = OG_Creatures->getAddress ("vector");
d->dwarf_race_index_addr = OG_Creatures->getAddress("current_race");
d->dwarf_civ_id_addr = OG_Creatures->getAddress("current_civ");
// Creatures/creature
creatures.name_offset = OG_creature->getOffset ("name");
creatures.custom_profession_offset = OG_creature->getOffset ("custom_profession");
creatures.profession_offset = OG_creature->getOffset ("profession");
creatures.race_offset = OG_creature->getOffset ("race");
creatures.pos_offset = OG_creature->getOffset ("position");
creatures.flags1_offset = OG_creature->getOffset ("flags1");
creatures.flags2_offset = OG_creature->getOffset ("flags2");
creatures.sex_offset = OG_creature->getOffset ("sex");
creatures.caste_offset = OG_creature->getOffset ("caste");
creatures.id_offset = OG_creature->getOffset ("id");
creatures.civ_offset = OG_creature->getOffset ("civ");
// name struct
creatures.name_firstname_offset = OG_name->getOffset("first");
creatures.name_nickname_offset = OG_name->getOffset("nick");
creatures.name_words_offset = OG_name->getOffset("second_words");
d->Ft_basic = true;
try
{
// supply the module with offsets so it can work with them
memcpy(SHMDATA(Creatures2010::creature_offsets),&creatures,sizeof(Creatures2010::creature_offsets));
const uint32_t cmd = Creatures2010::CREATURE_INIT + (d->creature_module << 16);
p->SetAndWait(cmd);
}
*/
d->Inited = true;
}
catch (Error::MissingMemoryDefinition&)
creatures.inventory_offset = OG_creature_ex->getOffset("inventory_vector");
creatures.pickup_equipment_bit = OG_creature_ex->getOffset("pickup_equipment_bit");
creatures.mood_offset = OG_creature_ex->getOffset("mood");
// pregnancy
// pregnancy_ptr
creatures.birth_year_offset = OG_creature_ex->getOffset("birth_year");
creatures.birth_time_offset = OG_creature_ex->getOffset("birth_time");
creatures.current_job_offset = OG_creature_ex->getOffset("current_job");
creatures.mood_skill_offset = OG_creature_ex->getOffset("current_job_skill");
creatures.physical_offset = OG_creature_ex->getOffset("physical");
creatures.appearance_vector_offset = OG_creature_ex->getOffset("appearance_vector");
creatures.artifact_name_offset = OG_creature_ex->getOffset("artifact_name");
creatures.labors_offset = OG_creature_ex->getOffset ("labors");
creatures.happiness_offset = OG_creature_ex->getOffset ("happiness");
d->Ft_advanced = true;
}
catch(Error::All&){};
try
{
d->Inited = false;
throw;
creatures.soul_vector_offset = OG_creature_ex->getOffset("soul_vector");
creatures.default_soul_offset = OG_creature_ex->getOffset("current_soul");
creatures.soul_mental_offset = OG_soul->getOffset("mental");
creatures.soul_skills_vector_offset = OG_soul->getOffset("skills_vector");
creatures.soul_traits_offset = OG_soul->getOffset("traits");
d->Ft_soul = true;
}
catch(Error::All&){};
}
catch(Error::All&){};
d->Inited = true;
}
Creatures::~Creatures()
@ -158,6 +169,7 @@ bool Creatures::Finish()
bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
{
if(!d->Started) return false;
memset(&furball, 0, sizeof(t_creature));
// SHM fast path
Process * p = d->owner;
/*
@ -171,7 +183,7 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
}
*/
// non-SHM slow path
memory_info * minfo = d->d->offset_descriptor;
VersionInfo * minfo = d->d->offset_descriptor;
// read pointer from vector at position
uint32_t temp = d->p_cre->at (index);
@ -179,12 +191,12 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
Creatures2010::creature_offsets &offs = d->creatures;
//read creature from memory
if(d->Ft_basic)
{
// name
d->d->readName(furball.name,temp + offs.name_offset);
// basic stuff
p->readDWord (temp + offs.happiness_offset, furball.happiness);
p->readDWord (temp + offs.id_offset, furball.id);
p->read (temp + offs.pos_offset, 3 * sizeof (uint16_t), (uint8_t *) & (furball.x)); // xyz really
p->readDWord (temp + offs.race_offset, furball.race);
@ -193,6 +205,15 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
p->readWord (temp + offs.caste_offset, furball.caste);
p->readDWord (temp + offs.flags1_offset, furball.flags1.whole);
p->readDWord (temp + offs.flags2_offset, furball.flags2.whole);
// custom profession
p->readSTLString(temp + offs.custom_profession_offset, furball.custom_profession, sizeof(furball.custom_profession));
// profession
furball.profession = p->readByte (temp + offs.profession_offset);
}
if(d->Ft_advanced)
{
// happiness
p->readDWord (temp + offs.happiness_offset, furball.happiness);
// physical attributes
p->read(temp + offs.physical_offset,
@ -204,50 +225,36 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
furball.mood_skill = p->readWord (temp + offs.mood_skill_offset);
d->d->readName(furball.artifact_name, temp + offs.artifact_name_offset);
// custom profession
p->readSTLString(temp + offs.custom_profession_offset, furball.custom_profession, sizeof(furball.custom_profession));
//fill_char_buf (furball.custom_profession, p->readSTLString (temp + offs.custom_profession_offset));
// labors
p->read (temp + offs.labors_offset, NUM_CREATURE_LABORS, furball.labors);
// profession
furball.profession = p->readByte (temp + offs.profession_offset);
furball.current_job.occupationPtr = p->readDWord (temp + offs.current_job_offset);
if(furball.current_job.occupationPtr)
{
furball.current_job.active = true;
furball.current_job.jobType = p->readByte (furball.current_job.occupationPtr + minfo->getOffset("job_type") );
furball.current_job.jobId = p->readDWord (furball.current_job.occupationPtr + minfo->getOffset("job_id") );
}
else
{
furball.current_job.active = false;;
}
furball.birth_year = p->readDWord (temp + offs.birth_year_offset );
furball.birth_time = p->readDWord (temp + offs.birth_time_offset );
// current job HACK: the job object isn't cleanly represented here
/*
uint32_t jobIdAddr = p->readDWord (temp + offs.creature_current_job_offset);
* p->readDWord(temp + offs.creature_pregnancy_offset, furball.pregnancy_timer);
*/
if (jobIdAddr)
{
furball.current_job.active = true;
furball.current_job.jobId = p->readByte (jobIdAddr + offs.creature_current_job_id_offset);
}
else
// appearance
DfVector <uint32_t> app(p, temp + offs.appearance_vector_offset);
furball.nbcolors = app.size();
if(furball.nbcolors>MAX_COLORS)
furball.nbcolors = MAX_COLORS;
for(uint32_t i = 0; i < furball.nbcolors; i++)
{
furball.current_job.active = false;
furball.color[i] = app[i];
}
*/
//likes
/*
p->readDWord(temp + offs.creature_pregnancy_offset, furball.pregnancy_timer);
*/
DfVector <uint32_t> likes(d->p, temp + offs.creature_likes_offset);
furball.numLikes = likes.getSize();
for(uint32_t i = 0;i<furball.numLikes;i++)
{
uint32_t temp2 = *(uint32_t *) likes[i];
p->read(temp2,sizeof(t_like),(uint8_t *) &furball.likes[i]);
}*/
}
if(d->Ft_soul)
{
/*
// enum soul pointer vector
DfVector <uint32_t> souls(p,temp + offs.creature_soul_vector_offset);
@ -283,25 +290,21 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
sizeof (uint16_t) * NUM_CREATURE_TRAITS,
(uint8_t *) &furball.defaultSoul.traits);
}
DfVector <uint32_t> app(p, temp + offs.appearance_vector_offset);
furball.nbcolors = app.size();
if(furball.nbcolors>MAX_COLORS)
furball.nbcolors = MAX_COLORS;
for(uint32_t i = 0; i < furball.nbcolors; i++)
}
if(d->Ft_jobs)
{
furball.color[i] = app[i];
furball.current_job.occupationPtr = p->readDWord (temp + offs.current_job_offset);
if(furball.current_job.occupationPtr)
{
furball.current_job.active = true;
furball.current_job.jobType = p->readByte (furball.current_job.occupationPtr + d->OG_jobs->getOffset("type") );
furball.current_job.jobId = p->readDWord (furball.current_job.occupationPtr + d->OG_jobs->getOffset("id") );
}
//likes
/*
DfVector <uint32_t> likes(d->p, temp + offs.creature_likes_offset);
furball.numLikes = likes.getSize();
for(uint32_t i = 0;i<furball.numLikes;i++)
else
{
uint32_t temp2 = *(uint32_t *) likes[i];
p->read(temp2,sizeof(t_like),(uint8_t *) &furball.likes[i]);
}*/
furball.current_job.active = false;;
}
}
return true;
}
@ -525,17 +528,15 @@ bool Creatures::WriteJob(const t_creature * furball, std::vector<t_material> con
if(!d->Inited) return false;
if(!furball->current_job.active) return false;
Process * p = d->owner;
memory_info * minfo = d->d->offset_descriptor;
DfVector <uint32_t> cmats(p, furball->current_job.occupationPtr + minfo->getOffset("job_materials_vector"));
DfVector <uint32_t> cmats(p, furball->current_job.occupationPtr + d->OG_jobs->getOffset("materials_vector"));
for(i=0;i<cmats.size();i++)
{
p->writeWord(cmats[i] + minfo->getOffset("job_material_maintype"), mat[i].itemType);
p->writeWord(cmats[i] + minfo->getOffset("job_material_sectype1"), mat[i].subType);
p->writeWord(cmats[i] + minfo->getOffset("job_material_sectype2"), mat[i].subIndex);
p->writeDWord(cmats[i] + minfo->getOffset("job_material_sectype3"), mat[i].index);
p->writeDWord(cmats[i] + minfo->getOffset("job_material_flags"), mat[i].flags);
p->writeWord(cmats[i] + d->OG_job_mats->getOffset("maintype"), mat[i].itemType);
p->writeWord(cmats[i] + d->OG_job_mats->getOffset("sectype1"), mat[i].subType);
p->writeWord(cmats[i] + d->OG_job_mats->getOffset("sectype2"), mat[i].subIndex);
p->writeDWord(cmats[i] + d->OG_job_mats->getOffset("sectype3"), mat[i].index);
p->writeDWord(cmats[i] + d->OG_job_mats->getOffset("flags"), mat[i].flags);
}
return true;
}
@ -595,17 +596,40 @@ bool Creatures::ReadJob(const t_creature * furball, vector<t_material> & mat)
if(!d->Inited) return false;
if(!furball->current_job.active) return false;
Process * p = d->owner;
memory_info * minfo = d->d->offset_descriptor;
VersionInfo * minfo = d->d->offset_descriptor;
DfVector <uint32_t> cmats(p, furball->current_job.occupationPtr + minfo->getOffset("job_materials_vector"));
DfVector <uint32_t> cmats(p, furball->current_job.occupationPtr + d->OG_jobs->getOffset("materials_vector"));
mat.resize(cmats.size());
for(i=0;i<cmats.size();i++)
{
mat[i].itemType = p->readWord(cmats[i] + minfo->getOffset("job_material_maintype"));
mat[i].subType = p->readWord(cmats[i] + minfo->getOffset("job_material_sectype1"));
mat[i].subIndex = p->readWord(cmats[i] + minfo->getOffset("job_material_sectype2"));
mat[i].index = p->readDWord(cmats[i] + minfo->getOffset("job_material_sectype3"));
mat[i].flags = p->readDWord(cmats[i] + minfo->getOffset("job_material_flags"));
mat[i].itemType = p->readWord(cmats[i] + d->OG_job_mats->getOffset("maintype"));
mat[i].subType = p->readWord(cmats[i] + d->OG_job_mats->getOffset("sectype1"));
mat[i].subIndex = p->readWord(cmats[i] + d->OG_job_mats->getOffset("sectype2"));
mat[i].index = p->readDWord(cmats[i] + d->OG_job_mats->getOffset("sectype3"));
mat[i].flags = p->readDWord(cmats[i] + d->OG_job_mats->getOffset("flags"));
}
return true;
}
bool Creatures::ReadInventoryIdx(const uint32_t index, std::vector<uint32_t> & item)
{
if(!d->Started) return false;
Process * p = d->owner;
uint32_t temp = d->p_cre->at (index);
return this->ReadInventoryPtr(temp, item);
}
bool Creatures::ReadInventoryPtr(const uint32_t temp, std::vector<uint32_t> & item)
{
unsigned int i;
if(!d->Started) return false;
Process * p = d->owner;
DfVector <uint32_t> citem(p, temp + d->creatures.inventory_offset);
if(citem.size() == 0)
return false;
item.resize(citem.size());
for(i=0;i<citem.size();i++)
item[i] = p->readDWord(citem[i]);
return true;
}

@ -26,19 +26,24 @@ distribution.
#include "ContextShared.h"
#include "dfhack/modules/Gui.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFTypes.h"
using namespace DFHack;
struct Gui::Private
{
bool Inited;
Private()
{
Started = PauseInited = ViewScreeInited = MenuStateInited = false;
}
bool Started;
uint32_t pause_state_offset;
bool PauseInited;
uint32_t view_screen_offset;
uint32_t current_cursor_creature_offset;
bool ViewScreeInited;
uint32_t current_menu_state_offset;
bool MenuStateInited;
DFContextShared *d;
Process * owner;
};
@ -49,13 +54,26 @@ Gui::Gui(DFContextShared * _d)
d = new Private;
d->d = _d;
d->owner = _d->p;
d->Inited = d->Started = true;
memory_info * mem = d->d->offset_descriptor;
d->current_menu_state_offset = mem->getAddress("current_menu_state");
d->pause_state_offset = mem->getAddress ("pause_state");
d->view_screen_offset = mem->getAddress ("view_screen");
d->Inited = d->Started = true;
OffsetGroup * OG_Gui = d->d->offset_descriptor->getGroup("GUI");
try
{
d->current_menu_state_offset = OG_Gui->getAddress("current_menu_state");
d->MenuStateInited = true;
}
catch(exception &){};
try
{
d->pause_state_offset = OG_Gui->getAddress ("pause_state");
d->PauseInited = true;
}
catch(exception &){};
try
{
d->view_screen_offset = OG_Gui->getAddress ("view_screen");
d->ViewScreeInited = true;
}
catch(exception &){};
d->Started = true;
}
Gui::~Gui()
@ -75,23 +93,29 @@ bool Gui::Finish()
bool Gui::ReadPauseState()
{
// replace with an exception
if(!d->Inited) return false;
if(!d->PauseInited) return false;
uint32_t pauseState = d->owner->readDWord (d->pause_state_offset);
return pauseState & 1;
}
void Gui::SetPauseState(bool paused)
{
if(!d->PauseInited) return;
cout << "pause set" << endl;
d->owner->writeDWord (d->pause_state_offset, paused);
}
uint32_t Gui::ReadMenuState()
{
if(d->Inited)
if(d->MenuStateInited)
return(d->owner->readDWord(d->current_menu_state_offset));
return false;
}
bool Gui::ReadViewScreen (t_viewscreen &screen)
{
if (!d->Inited) return false;
if (!d->ViewScreeInited) return false;
Process * p = d->owner;
uint32_t last = p->readDWord (d->view_screen_offset);

@ -60,8 +60,6 @@ int Gui_ReadPauseState(DFHackObject* gui)
int Gui_ReadViewScreen(DFHackObject* gui, t_viewscreen* viewscreen)
{
//int result;
if(gui != NULL)
{
return ((DFHack::Gui*)gui)->ReadViewScreen(*viewscreen);
@ -70,6 +68,18 @@ int Gui_ReadViewScreen(DFHackObject* gui, t_viewscreen* viewscreen)
return -1;
}
int Gui_ReadMenuState(DFHackObject* gui, uint32_t* menuState)
{
if(gui != NULL)
{
*menuState = ((DFHack::Gui*)gui)->ReadMenuState();
return 1;
}
return -1;
}
#ifdef __cplusplus
}
#endif

@ -25,7 +25,7 @@ distribution.
#include "Internal.h"
#include "ContextShared.h"
#include "dfhack/DFTypes.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/modules/Materials.h"
@ -189,11 +189,12 @@ int32_t Accessor::getValue(uint32_t objectPtr)
ItemDesc::ItemDesc(uint32_t VTable, Process *p)
{
uint32_t funcOffsetA = p->getDescriptor()->getOffset("item_type_accessor");
uint32_t funcOffsetB = p->getDescriptor()->getOffset("item_subtype_accessor");
uint32_t funcOffsetC = p->getDescriptor()->getOffset("item_subindex_accessor");
uint32_t funcOffsetD = p->getDescriptor()->getOffset("item_index_accessor");
uint32_t funcOffsetQuality = p->getDescriptor()->getOffset("item_quality_accessor");
OffsetGroup * Items = p->getDescriptor()->getGroup("Items");
uint32_t funcOffsetA = Items->getOffset("item_type_accessor");
uint32_t funcOffsetB = Items->getOffset("item_subtype_accessor");
uint32_t funcOffsetC = Items->getOffset("item_subindex_accessor");
uint32_t funcOffsetD = Items->getOffset("item_index_accessor");
uint32_t funcOffsetQuality = Items->getOffset("item_quality_accessor");
this->vtable = VTable;
this->p = p;
this->className = p->readClassName(VTable).substr(5);

@ -29,7 +29,7 @@ distribution.
#include "ContextShared.h"
#include "dfhack/modules/Maps.h"
#include "dfhack/DFError.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
@ -52,6 +52,9 @@ struct Maps::Private
DFContextShared *d;
Process * owner;
OffsetGroup *OG_local_features;
OffsetGroup *OG_global_features;
OffsetGroup *OG_vector;
bool Inited;
bool Started;
@ -67,40 +70,52 @@ Maps::Maps(DFContextShared* _d)
d->d = _d;
Process *p = d->owner = _d->p;
d->Inited = d->Started = false;
d->block = NULL;
DFHack::memory_info * mem = p->getDescriptor();
DFHack::VersionInfo * mem = p->getDescriptor();
Server::Maps::maps_offsets &off = d->offsets;
// get the offsets once here
off.map_offset = mem->getAddress ("map_data");
off.x_count_offset = mem->getAddress ("x_count_block");
off.y_count_offset = mem->getAddress ("y_count_block");
off.z_count_offset = mem->getAddress ("z_count_block");
off.tile_type_offset = mem->getOffset ("map_data_type");
off.designation_offset = mem->getOffset ("map_data_designation");
off.occupancy_offset = mem->getOffset("map_data_occupancy");
off.biome_stuffs = mem->getOffset ("map_data_biome_stuffs");
off.veinvector = mem->getOffset ("map_data_vein_vector");
off.local_feature_offset = mem->getOffset ("map_data_feature_local");
off.global_feature_offset = mem->getOffset ("map_data_feature_global");
off.temperature1_offset = mem->getOffset ("map_data_temperature1_offset");
off.temperature2_offset = mem->getOffset ("map_data_temperature2_offset");
off.region_x_offset = mem->getAddress ("region_x");
off.region_y_offset = mem->getAddress ("region_y");
off.region_z_offset = mem->getAddress ("region_z");
off.world_regions = mem->getAddress ("ptr2_region_array");
off.region_size = mem->getHexValue ("region_size");
off.region_geo_index_offset = mem->getOffset ("region_geo_index_off");
off.geolayer_geoblock_offset = mem->getOffset ("geolayer_geoblock_offset");
off.world_geoblocks_vector = mem->getAddress ("geoblock_vector");
off.type_inside_geolayer = mem->getOffset ("type_inside_geolayer");
off.world_size_x = mem->getAddress ("world_size_x");
off.world_size_y = mem->getAddress ("world_size_y");
// these can fail and will be found when looking at the actual veins later
OffsetGroup *OG_Maps = mem->getGroup("Maps");
{
off.map_offset = OG_Maps->getAddress ("map_data");
off.x_count_offset = OG_Maps->getAddress ("x_count_block");
off.y_count_offset = OG_Maps->getAddress ("y_count_block");
off.z_count_offset = OG_Maps->getAddress ("z_count_block");
off.region_x_offset = OG_Maps->getAddress ("region_x");
off.region_y_offset = OG_Maps->getAddress ("region_y");
off.region_z_offset = OG_Maps->getAddress ("region_z");
off.world_size_x = OG_Maps->getAddress ("world_size_x");
off.world_size_y = OG_Maps->getAddress ("world_size_y");
OffsetGroup *OG_MapBlock = OG_Maps->getGroup("block");
{
off.tile_type_offset = OG_MapBlock->getOffset ("type");
off.designation_offset = OG_MapBlock->getOffset ("designation");
off.occupancy_offset = OG_MapBlock->getOffset("occupancy");
off.biome_stuffs = OG_MapBlock->getOffset ("biome_stuffs");
off.veinvector = OG_MapBlock->getOffset ("vein_vector");
off.local_feature_offset = OG_MapBlock->getOffset ("feature_local");
off.global_feature_offset = OG_MapBlock->getOffset ("feature_global");
off.temperature1_offset = OG_MapBlock->getOffset ("temperature1");
off.temperature2_offset = OG_MapBlock->getOffset ("temperature2");
}
OffsetGroup *OG_Geology = OG_Maps->getGroup("geology");
{
off.world_regions = OG_Geology->getAddress ("ptr2_region_array");
off.region_size = OG_Geology->getHexValue ("region_size");
off.region_geo_index_offset = OG_Geology->getOffset ("region_geo_index_off");
off.geolayer_geoblock_offset = OG_Geology->getOffset ("geolayer_geoblock_offset");
off.world_geoblocks_vector = OG_Geology->getAddress ("geoblock_vector");
off.type_inside_geolayer = OG_Geology->getOffset ("type_inside_geolayer");
}
d->OG_global_features = OG_Maps->getGroup("features")->getGroup("global");
d->OG_local_features = OG_Maps->getGroup("features")->getGroup("local");
}
d->OG_vector = mem->getGroup("vector");
// these can (will) fail and will be found when looking at the actual veins later
// basically a cache
off.vein_ice_vptr = 0;
mem->resolveClassnameToVPtr("block_square_event_frozen_liquid", off.vein_ice_vptr);
@ -646,7 +661,7 @@ __int16 __userpurge GetGeologicalRegion<ax>(__int16 block_X<cx>, int X<ebx>, __i
bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
{
MAPS_GUARD
memory_info * minfo = d->d->offset_descriptor;
VersionInfo * minfo = d->d->offset_descriptor;
Process *p = d->owner;
// get needed addresses and offsets. Now this is what I call crazy.
uint16_t worldSizeX, worldSizeY;
@ -721,16 +736,16 @@ bool Maps::ReadLocalFeatures( std::map <planecoord, std::vector<t_feature *> > &
return false;
Process * p = d->owner;
memory_info * mem = p->getDescriptor();
VersionInfo * mem = p->getDescriptor();
// deref pointer to the humongo-structure
uint32_t base = p->readDWord(mem->getAddress("local_feature_start_ptr"));
uint32_t base = p->readDWord(d->OG_local_features->getAddress("start_ptr"));
if(!base)
return false;
uint32_t sizeof_vec = mem->getHexValue("sizeof_vector");
const uint32_t sizeof_vec = d->OG_vector->getHexValue("sizeof");
const uint32_t sizeof_elem = 16;
const uint32_t offset_elem = 4;
const uint32_t main_mat_offset = mem->getOffset("local_feature_mat"); // 0x30
const uint32_t sub_mat_offset = mem->getOffset("local_feature_submat"); // 0x34
const uint32_t main_mat_offset = d->OG_local_features->getOffset("material"); // 0x30
const uint32_t sub_mat_offset = d->OG_local_features->getOffset("submaterial"); // 0x34
local_features.clear();
@ -814,12 +829,11 @@ bool Maps::ReadGlobalFeatures( std::vector <t_feature> & features)
return false;
Process * p = d->owner;
memory_info * mem = p->getDescriptor();
uint32_t global_feature_vector = mem->getAddress("global_feature_vector");
uint32_t global_feature_funcptr = mem->getOffset("global_feature_funcptr_");
const uint32_t main_mat_offset = mem->getOffset("global_feature_mat"); // 0x34
const uint32_t sub_mat_offset = mem->getOffset("global_feature_submat"); // 0x38
const uint32_t global_feature_vector = d->OG_global_features->getAddress("vector");
const uint32_t global_feature_funcptr = d->OG_global_features->getOffset("funcptr");
const uint32_t main_mat_offset = d->OG_global_features->getOffset("material"); // 0x34
const uint32_t sub_mat_offset = d->OG_global_features->getOffset("submaterial"); // 0x38
DfVector<uint32_t> p_features (p,global_feature_vector);
features.clear();

@ -54,6 +54,37 @@ int Maps_Finish(DFHackObject* maps)
return -1;
}
t_feature* Maps_ReadGlobalFeatures(DFHackObject* maps)
{
if(maps != NULL)
{
std::vector<t_feature> featureVec;
if(((DFHack::Maps*)maps)->ReadGlobalFeatures(featureVec))
{
if(featureVec.size() <= 0)
return NULL;
t_feature* buf;
(*alloc_t_feature_buffer_callback)(buf, featureVec.size());
if(buf != NULL)
{
copy(featureVec.begin(), featureVec.end(), buf);
return buf;
}
else
return NULL;
}
else
return NULL;
}
return NULL;
}
void Maps_getSize(DFHackObject* maps, uint32_t* x, uint32_t* y, uint32_t* z)
{
if(maps != NULL)

@ -26,9 +26,10 @@ distribution.
#include "ContextShared.h"
#include "dfhack/DFTypes.h"
#include "dfhack/modules/Materials.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include <dfhack/DFError.h>
using namespace DFHack;
@ -37,6 +38,13 @@ class Materials::Private
public:
DFContextShared *d;
Process * owner;
OffsetGroup * OG_Materials;
uint32_t vector_inorganic;
uint32_t vector_organic_all;
uint32_t vector_organic_plants;
uint32_t vector_organic_trees;
uint32_t vector_races;
uint32_t vector_other;
/*
bool Inited;
bool Started;
@ -48,6 +56,14 @@ Materials::Materials(DFContextShared * d_)
d = new Private;
d->d = d_;
d->owner = d_->p;
OffsetGroup *OG_Materials = d->OG_Materials = d->owner->getDescriptor()->getGroup("Materials");
{
d->vector_inorganic = OG_Materials->getAddress("inorganics");
d->vector_organic_all = OG_Materials->getAddress ("organics_all");
d->vector_organic_plants = OG_Materials->getAddress ("organics_plants");
d->vector_organic_trees = OG_Materials->getAddress ("organics_trees");
d->vector_races = OG_Materials->getAddress("creature_type_vector");
}
}
Materials::~Materials()
{
@ -56,6 +72,7 @@ Materials::~Materials()
bool Materials::Finish()
{
/*
inorganic.clear();
organic.clear();
tree.clear();
@ -65,6 +82,7 @@ bool Materials::Finish()
color.clear();
other.clear();
alldesc.clear();
*/
return true;
}
@ -216,7 +234,7 @@ inline bool ReadNamesOnly(Process* p, uint32_t address, vector<t_matgloss> & nam
bool Materials::ReadInorganicMaterials (void)
{
Process * p = d->owner;
DfVector <uint32_t> p_matgloss (p, d->owner->getDescriptor()->getAddress ("mat_inorganics"));
DfVector <uint32_t> p_matgloss (p, d->vector_inorganic);
uint32_t size = p_matgloss.size();
inorganic.clear();
inorganic.reserve (size);
@ -237,29 +255,29 @@ bool Materials::ReadInorganicMaterials (void)
bool Materials::ReadOrganicMaterials (void)
{
return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("mat_organics_all"), organic );
return ReadNamesOnly(d->owner, d->vector_organic_all, organic );
}
bool Materials::ReadWoodMaterials (void)
{
return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("mat_organics_trees"), tree );
return ReadNamesOnly(d->owner, d->vector_organic_trees, tree );
}
bool Materials::ReadPlantMaterials (void)
{
return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("mat_organics_plants"), plant );
return ReadNamesOnly(d->owner, d->vector_organic_plants, plant );
}
bool Materials::ReadCreatureTypes (void)
{
return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("creature_type_vector"), race );
return ReadNamesOnly(d->owner, d->vector_races, race );
return true;
}
bool Materials::ReadOthers(void)
{
Process * p = d->owner;
uint32_t matBase = p->getDescriptor()->getAddress ("mat_other");
uint32_t matBase = d->OG_Materials->getAddress ("other");
uint32_t i = 0;
uint32_t ptr;
@ -281,7 +299,8 @@ bool Materials::ReadOthers(void)
bool Materials::ReadDescriptorColors (void)
{
Process * p = d->owner;
DfVector <uint32_t> p_colors (p, p->getDescriptor()->getAddress ("descriptor_colors_vector"));
OffsetGroup * OG_Descriptors = p->getDescriptor()->getGroup("Materials")->getGroup("descriptors");
DfVector <uint32_t> p_colors (p, OG_Descriptors->getAddress ("colors_vector"));
uint32_t size = p_colors.size();
color.clear();
@ -291,43 +310,70 @@ bool Materials::ReadDescriptorColors (void)
for (uint32_t i = 0; i < size;i++)
{
t_descriptor_color col;
p->readSTLString (p_colors[i] + p->getDescriptor()->getOffset ("descriptor_rawname"), col.id, 128);
p->readSTLString (p_colors[i] + p->getDescriptor()->getOffset ("descriptor_name"), col.name, 128);
col.r = p->readFloat( p_colors[i] + p->getDescriptor()->getOffset ("descriptor_color_r") );
col.v = p->readFloat( p_colors[i] + p->getDescriptor()->getOffset ("descriptor_color_v") );
col.b = p->readFloat( p_colors[i] + p->getDescriptor()->getOffset ("descriptor_color_b") );
p->readSTLString (p_colors[i] + OG_Descriptors->getOffset ("rawname"), col.id, 128);
p->readSTLString (p_colors[i] + OG_Descriptors->getOffset ("name"), col.name, 128);
col.r = p->readFloat( p_colors[i] + OG_Descriptors->getOffset ("color_r") );
col.v = p->readFloat( p_colors[i] + OG_Descriptors->getOffset ("color_v") );
col.b = p->readFloat( p_colors[i] + OG_Descriptors->getOffset ("color_b") );
color.push_back(col);
}
return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("descriptor_all_colors"), alldesc );
return ReadNamesOnly(d->owner, OG_Descriptors->getAddress ("all_colors_vector"), alldesc );
return true;
}
bool Materials::ReadCreatureTypesEx (void)
{
Process *p = d->owner;
memory_info *mem = d->owner->getDescriptor();
DfVector <uint32_t> p_races (p, mem->getAddress ("creature_type_vector"));
uint32_t castes_vector_offset = mem->getOffset ("creature_type_caste_vector");
uint32_t extract_vector_offset = mem->getOffset ("creature_type_extract_vector");
uint32_t sizeof_string = mem->getHexValue ("sizeof_string");
uint32_t caste_colormod_offset = mem->getOffset ("caste_color_modifiers");
uint32_t caste_bodypart_offset = mem->getOffset ("caste_bodypart_vector");
uint32_t caste_attributes_offset = mem->getOffset ("caste_attributes");
uint32_t bodypart_id_offset = mem->getOffset ("bodypart_id");
uint32_t bodypart_category_offset = mem->getOffset ("bodypart_category");
uint32_t bodypart_layers_offset = mem->getOffset ("bodypart_layers_vector");
uint32_t bodypart_singular_offset = mem->getOffset ("bodypart_singular_vector"); // unused
uint32_t bodypart_plural_offset = mem->getOffset ("bodypart_plural_vector"); // unused
uint32_t color_modifier_part_offset = mem->getOffset ("color_modifier_part");
uint32_t color_modifier_startdate_offset = mem->getOffset ("color_modifier_startdate");
uint32_t color_modifier_enddate_offset = mem->getOffset ("color_modifier_enddate");
VersionInfo *mem = p->getDescriptor();
OffsetGroup * OG_string = mem->getGroup("string");
uint32_t sizeof_string = OG_string->getHexValue ("sizeof");
OffsetGroup * OG_Mats = mem->getGroup("Materials");
DfVector <uint32_t> p_races (p, OG_Mats->getAddress ("creature_type_vector"));
OffsetGroup * OG_Creature = OG_Mats->getGroup("creature");
uint32_t castes_vector_offset = OG_Creature->getOffset ("caste_vector");
uint32_t extract_vector_offset = OG_Creature->getOffset ("extract_vector");
uint32_t tile_offset = OG_Creature->getOffset ("tile");
uint32_t tile_color_offset = OG_Creature->getOffset ("tile_color");
bool have_advanced = false;
uint32_t caste_colormod_offset;
uint32_t caste_attributes_offset;
uint32_t caste_bodypart_offset;
uint32_t bodypart_id_offset;
uint32_t bodypart_category_offset;
uint32_t bodypart_layers_offset;
uint32_t bodypart_singular_offset;
uint32_t bodypart_plural_offset;
uint32_t color_modifier_part_offset;
uint32_t color_modifier_startdate_offset;
uint32_t color_modifier_enddate_offset;
try
{
OffsetGroup * OG_Caste = OG_Creature->getGroup("caste");
caste_colormod_offset = OG_Caste->getOffset ("color_modifiers");
caste_attributes_offset = OG_Caste->getOffset ("attributes");
caste_bodypart_offset = OG_Caste->getOffset ("bodypart_vector");
OffsetGroup * OG_CasteBodyparts = OG_Creature->getGroup("caste_bodyparts");
bodypart_id_offset = OG_CasteBodyparts->getOffset ("id");
bodypart_category_offset = OG_CasteBodyparts->getOffset ("category");
bodypart_layers_offset = OG_CasteBodyparts->getOffset ("layers_vector"); // unused
bodypart_singular_offset = OG_CasteBodyparts->getOffset ("singular_vector"); // unused
bodypart_plural_offset = OG_CasteBodyparts->getOffset ("plural_vector"); // unused
OffsetGroup * OG_CasteColorMods = OG_Creature->getGroup("caste_color_mods");
color_modifier_part_offset = OG_CasteColorMods->getOffset ("part");
color_modifier_startdate_offset = OG_CasteColorMods->getOffset ("startdate");
color_modifier_enddate_offset = OG_CasteColorMods->getOffset ("enddate");
have_advanced = true;
}
catch (Error::All &){};
uint32_t size = p_races.size();
uint32_t sizecas = 0;
uint32_t sizecolormod;
uint32_t sizecolorlist;
uint32_t sizebp;
uint32_t tile_offset = mem->getOffset ("creature_tile");
uint32_t tile_color_offset = mem->getOffset ("creature_tile_color");
raceEx.clear();
raceEx.reserve (size);
for (uint32_t i = 0; i < size;i++)
@ -356,7 +402,8 @@ bool Materials::ReadCreatureTypesEx (void)
p->readSTLString (caste_start + sizeof_string, caste.singular, sizeof(caste.singular));
p->readSTLString (caste_start + 2 * sizeof_string, caste.plural, sizeof(caste.plural));
p->readSTLString (caste_start + 3 * sizeof_string, caste.adjective, sizeof(caste.adjective));
if(have_advanced)
{
/* color mod reading */
DfVector <uint32_t> p_colormod(p, caste_start + caste_colormod_offset);
sizecolormod = p_colormod.size();
@ -372,7 +419,6 @@ bool Materials::ReadCreatureTypesEx (void)
caste.ColorModifier[k].startdate = p->readDWord( p_colormod[k] + color_modifier_startdate_offset );
caste.ColorModifier[k].enddate = p->readDWord( p_colormod[k] + color_modifier_enddate_offset );
}
/* body parts */
DfVector <uint32_t> p_bodypart(p, caste_start + caste_bodypart_offset);
caste.bodypart.empty();
@ -384,10 +430,8 @@ bool Materials::ReadCreatureTypesEx (void)
p->readSTLString (p_bodypart[k] + bodypart_category_offset, part.category, sizeof(part.category));
caste.bodypart.push_back(part);
}
p->read(caste_start + caste_attributes_offset, sizeof(t_attrib) * (6+11), (uint8_t *)&caste.strength);
}
mat.castes.push_back(caste);
}
DfVector <uint32_t> p_extract(p, p_races[i] + extract_vector_offset);
@ -411,7 +455,7 @@ void Materials::ReadAllMaterials(void)
this->ReadCreatureTypes();
this->ReadCreatureTypesEx();
this->ReadDescriptorColors();
this->ReadOthers();
//this->ReadOthers();
}
std::string Materials::getDescription(t_material & mat)

@ -116,6 +116,18 @@ void Materials_ReadAllMaterials(DFHackObject* mat)
}
}
const char* Materials_getType(DFHackObject* mat, t_material* material)
{
if(mat != NULL)
{
std::string type = ((DFHack::Materials*)mat)->getType(*material);
return type.c_str();
}
return "\0";
}
const char* Materials_getDescription(DFHackObject* mat, t_material* material)
{
if(mat != NULL)

@ -25,8 +25,9 @@ distribution.
#include "Internal.h"
#include "ContextShared.h"
#include "dfhack/modules/Position.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFError.h"
using namespace DFHack;
struct Position::Private
@ -59,33 +60,36 @@ Position::Position(DFContextShared * d_)
d->owner = d_->p;
d->Inited = true;
d->StartedHotkeys = d->Started = d->StartedScreen = false;
memory_info * mem;
OffsetGroup * OG_Position;
VersionInfo * mem = d->d->offset_descriptor;
// this is how to do feature detection properly
try
{
mem = d->d->offset_descriptor;
d->window_x_offset = mem->getAddress ("window_x");
d->window_y_offset = mem->getAddress ("window_y");
d->window_z_offset = mem->getAddress ("window_z");
d->cursor_xyz_offset = mem->getAddress ("cursor_xyz");
d->window_dims_offset = mem->getAddress ("window_dims");
OG_Position = mem->getGroup("Position");
d->window_x_offset = OG_Position->getAddress ("window_x");
d->window_y_offset = OG_Position->getAddress ("window_y");
d->window_z_offset = OG_Position->getAddress ("window_z");
d->cursor_xyz_offset = OG_Position->getAddress ("cursor_xyz");
d->window_dims_offset = OG_Position->getAddress ("window_dims");
d->Started = true;
}
catch(exception &){};
catch(Error::All &){};
try
{
d->hotkey_start = mem->getAddress("hotkey_start");
d->hotkey_mode_offset = mem->getOffset ("hotkey_mode");
d->hotkey_xyz_offset = mem->getOffset("hotkey_xyz");
d->hotkey_size = mem->getHexValue("hotkey_size");
OffsetGroup * OG_Hotkeys = mem->getGroup("Hotkeys");
d->hotkey_start = OG_Hotkeys->getAddress("start");
d->hotkey_mode_offset = OG_Hotkeys->getOffset ("mode");
d->hotkey_xyz_offset = OG_Hotkeys->getOffset("coords");
d->hotkey_size = OG_Hotkeys->getHexValue("size");
d->StartedHotkeys = true;
}
catch(exception &){};
catch(Error::All &){};
try
{
d->screen_tiles_ptr_offset = mem->getAddress ("screen_tiles_pointer");
d->screen_tiles_ptr_offset = OG_Position->getAddress ("screen_tiles_pointer");
d->StartedScreen = true;
}
catch(exception &){};
catch(Error::All &){};
}
Position::~Position()
@ -176,9 +180,7 @@ bool Position::getScreenTiles (int32_t width, int32_t height, t_screen screen[])
if(!d->Inited) return false;
if(!d->StartedScreen) return false;
uint32_t screen_addr;
d->owner->read (d->screen_tiles_ptr_offset, sizeof(uint32_t), (uint8_t *) screen_addr);
uint32_t screen_addr = d->owner->readDWord(d->screen_tiles_ptr_offset);
uint8_t* tiles = new uint8_t[width*height*4/* + 80 + width*height*4*/];
d->owner->read (screen_addr, (width*height*4/* + 80 + width*height*4*/), (uint8_t *) tiles);
@ -187,10 +189,10 @@ bool Position::getScreenTiles (int32_t width, int32_t height, t_screen screen[])
{
for(int32_t ix=0; ix<width; ix++)
{
screen[ix + iy*width].symbol = tiles[iy + ix*height*4 +0];
screen[ix + iy*width].foreground = tiles[iy + ix*height*4 +1];
screen[ix + iy*width].background = tiles[iy + ix*height*4 +2];
screen[ix + iy*width].bright = tiles[iy + ix*height*4 +3];
screen[ix + iy*width].symbol = tiles[(iy + ix*height)*4 +0];
screen[ix + iy*width].foreground = tiles[(iy + ix*height)*4 +1];
screen[ix + iy*width].background = tiles[(iy + ix*height)*4 +2];
screen[ix + iy*width].bright = tiles[(iy + ix*height)*4 +3];
//screen[ix + iy*width].gtile = tiles[width*height*4 + 80 + iy + ix*height +0];
//screen[ix + iy*width].grayscale = tiles[width*height*4 + 80 + iy + ix*height +1];
}

@ -22,6 +22,7 @@ must not be misrepresented as being the original software.
distribution.
*/
#include "dfhack-c/DFTypes_C.h"
#include "dfhack-c/modules/Position_C.h"
#ifdef __cplusplus
@ -97,6 +98,28 @@ int Position_setCursorCoords(DFHackObject* pos, int32_t x, int32_t y, int32_t z)
return -1;
}
t_hotkey* Position_ReadHotkeys(DFHackObject* pos)
{
if(pos != NULL)
{
t_hotkey* buf;
(*alloc_t_hotkey_buffer_callback)(buf, NUM_HOTKEYS);
if(buf != NULL)
{
if(((DFHack::Position*)pos)->ReadHotkeys(buf))
return buf;
else
return NULL;
}
else
return NULL;
}
return NULL;
}
int Position_getWindowSize(DFHackObject* pos, int32_t* width, int32_t* height)
{
if(pos != NULL)
@ -117,6 +140,26 @@ int Position_getWindowSize(DFHackObject* pos, int32_t* width, int32_t* height)
return -1;
}
t_screen* Position_getScreenTiles(DFHackObject* pos, int32_t width, int32_t height)
{
if(pos != NULL)
{
t_screen* buf;
(*alloc_t_screen_buffer_callback)(buf, width * height);
if(buf == NULL)
return NULL;
if(((DFHack::Position*)pos)->getScreenTiles(width, height, buf))
return buf;
else
return NULL;
}
return NULL;
}
#ifdef __cplusplus
}
#endif

@ -25,7 +25,7 @@ distribution.
#include "Internal.h"
#include "ContextShared.h"
#include "dfhack/modules/Translation.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFTypes.h"
@ -52,11 +52,12 @@ Translation::Translation(DFContextShared * d_)
d = new Private;
d->d = d_;
d->Inited = d->Started = false;
memory_info * mem = d->d->offset_descriptor;
d->genericAddress = mem->getAddress ("language_vector");
d->transAddress = mem->getAddress ("translation_vector");
d->word_table_offset = mem->getOffset ("word_table");
d->sizeof_string = mem->getHexValue ("sizeof_string");
OffsetGroup * OG_Translation = d->d->offset_descriptor->getGroup("Translations");
OffsetGroup * OG_String = d->d->offset_descriptor->getGroup("string");
d->genericAddress = OG_Translation->getAddress ("language_vector");
d->transAddress = OG_Translation->getAddress ("translation_vector");
d->word_table_offset = OG_Translation->getOffset ("word_table");
d->sizeof_string = OG_String->getHexValue ("sizeof");
d->Inited = true;
}

@ -25,7 +25,7 @@ distribution.
#include "Internal.h"
#include "ContextShared.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFTypes.h"
@ -53,9 +53,9 @@ Vegetation::Vegetation(DFContextShared * d_)
d->owner = d_->p;
d->d = d_;
d->Inited = d->Started = false;
memory_info * mem = d->d->offset_descriptor;
d->vegetation_vector = mem->getAddress ("vegetation_vector");
d->tree_desc_offset = mem->getOffset ("tree_desc_offset");
OffsetGroup * OG_Veg = d->d->offset_descriptor->getGroup("Vegetation");
d->vegetation_vector = OG_Veg->getAddress ("vector");
d->tree_desc_offset = OG_Veg->getOffset ("tree_desc_offset");
d->Inited = true;
}
@ -68,6 +68,8 @@ Vegetation::~Vegetation()
bool Vegetation::Start(uint32_t & numplants)
{
if(!d->Inited)
return false;
d->p_veg = new DfVector <uint32_t> (d->owner, d->vegetation_vector);
numplants = d->p_veg->size();
d->Started = true;

@ -38,17 +38,20 @@ FIXME: Japa said that he had to do this with the time stuff he got from here
#include "ContextShared.h"
#include "dfhack/modules/World.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFMemInfo.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFTypes.h"
#include "dfhack/DFError.h"
using namespace DFHack;
struct World::Private
{
bool Inited;
bool Started;
bool StartedTime;
bool StartedWeather;
uint32_t year_offset;
uint32_t tick_offset;
uint32_t weather_offset;
DFContextShared *d;
Process * owner;
};
@ -59,11 +62,23 @@ World::World(DFContextShared * _d)
d = new Private;
d->d = _d;
d->owner = _d->p;
memory_info * mem = d->d->offset_descriptor;
d->year_offset = mem->getAddress( "current_year" );
d->tick_offset = mem->getAddress( "current_tick" );
d->Inited = d->Started = true;
d->Inited = d->StartedTime = d->StartedWeather = false;
OffsetGroup * OG_World = d->d->offset_descriptor->getGroup("World");
try
{
d->year_offset = OG_World->getAddress( "current_year" );
d->tick_offset = OG_World->getAddress( "current_tick" );
d->StartedTime = true;
}
catch(Error::All &){};
try
{
d->weather_offset = OG_World->getAddress( "current_weather" );
d->StartedWeather = true;
}
catch(Error::All &){};
d->Inited = true;
}
World::~World()
@ -83,14 +98,14 @@ bool World::Finish()
uint32_t World::ReadCurrentYear()
{
if(d->Inited)
if(d->Inited && d->StartedTime)
return(d->owner->readDWord(d->year_offset));
return 0;
}
uint32_t World::ReadCurrentTick()
{
if(d->Inited)
if(d->Inited && d->StartedTime)
return(d->owner->readDWord(d->tick_offset));
return 0;
}
@ -114,3 +129,26 @@ uint32_t World::ReadCurrentDay()
{
return ((this->ReadCurrentTick() / 1200) % 28) + 1;
}
uint8_t World::ReadCurrentWeather()
{
if (d->Inited && d->StartedWeather)
return(d->owner->readByte(d->weather_offset + 12));
return 0;
}
/*
void World::SetCurrentWeather(uint8_t weather)
{
if (d->Inited && d->StartedWeather)
d->owner->writeByte(d->weather_offset,weather);
}
*/
void World::SetCurrentWeather(uint8_t weather)
{
if (d->Inited && d->StartedWeather)
{
uint8_t buf[25];
memset(&buf,weather, sizeof(buf));
d->owner->write(d->weather_offset,sizeof(buf),buf);
}
}

@ -100,6 +100,28 @@ int World_ReadCurrentDay(DFHackObject* world, uint32_t* day)
return -1;
}
int World_ReadCurrentWeather(DFHackObject* world, uint8_t* weather)
{
if(world != NULL)
{
*weather = ((DFHack::World*)world)->ReadCurrentWeather();
return 1;
}
return -1;
}
int World_WriteCurrentWeather(DFHackObject* world, uint8_t weather)
{
if (world != NULL)
{
((DFHack::World*)world)->SetCurrentWeather(weather);
return 1;
}
return -1;
}
#ifdef __cplusplus
}
#endif

@ -48,7 +48,7 @@ namespace DFHack
class ProcessEnumerator;
class Process;
class memory_info;
class VersionInfo;
struct t_name;
class DFContextShared
{
@ -68,7 +68,7 @@ namespace DFHack
ProcessEnumerator* pm;
Process* p;
char * shm_start;
memory_info* offset_descriptor;
VersionInfo* offset_descriptor;
string xml;
// Modules

@ -67,6 +67,7 @@ typedef struct
uint32_t appearance_vector_offset;
uint32_t birth_year_offset;
uint32_t birth_time_offset;
uint32_t inventory_offset;
} creature_offsets;
typedef struct

@ -1,8 +1,5 @@
# don't use this file directly. use the one in the root folder of the project
# only build this stuff when BUILD_DFHACK_EXAMPLES is set to ON
IF (BUILD_DFHACK_EXAMPLES)
# this is required to ensure we use the right configuration for the system.
IF(UNIX)
add_definitions(-DLINUX_BUILD)
@ -62,4 +59,3 @@ dfspatterdump
dfprocessenum
RUNTIME DESTINATION bin
)
ENDIF (BUILD_DFHACK_EXAMPLES)

@ -54,7 +54,7 @@ int main (int argc,const char* argv[])
return 1;
}
DFHack::memory_info * mem = DF->getMemoryInfo();
DFHack::VersionInfo * mem = DF->getMemoryInfo();
DFHack::Buildings * Bld = DF->getBuildings();
DFHack::Position * Pos = DF->getPosition();

@ -19,7 +19,7 @@ enum likeType
};
DFHack::Materials * Materials;
DFHack::memory_info *mem;
DFHack::VersionInfo *mem;
vector< vector<string> > englishWords;
vector< vector<string> > foreignWords;
DFHack::Creatures * Creatures = NULL;
@ -134,7 +134,7 @@ likeType printLike40d(DFHack::t_like like, const matGlosses & mat,const vector<
void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature)
{
uint32_t dayoflife;
cout << "address: " << hex << creature.origin << dec << " creature type: " << Materials->raceEx[creature.race].rawname
cout << "address: " << hex << creature.origin << dec << ", creature race: " << creature.race << "/" << Materials->raceEx[creature.race].rawname
<< "[" << Materials->raceEx[creature.race].tile_character
<< "," << Materials->raceEx[creature.race].tilecolor.fore
<< "," << Materials->raceEx[creature.race].tilecolor.back
@ -154,7 +154,7 @@ void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature)
}
DFHack::Translation *Tran = DF->getTranslation();
DFHack::memory_info *mem = DF->getMemoryInfo();
DFHack::VersionInfo *mem = DF->getMemoryInfo();
string transName = Tran->TranslateName(creature.name,false);
if(!transName.empty())
@ -172,7 +172,7 @@ void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature)
if(creature.civ)
{
cout << "civilization: " << creature.civ;
cout << ", civilization: " << creature.civ;
addendl = true;
}
@ -191,7 +191,7 @@ void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature)
cout << endl;
addendl = false;
}
cout << "profession: " << mem->getProfession(creature.profession) << "(" << (int) creature.profession << ")";
cout << ", profession: " << mem->getProfession(creature.profession) << "(" << (int) creature.profession << ")";
if(creature.custom_profession[0])
{
@ -271,6 +271,20 @@ void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature)
}
}
//std::vector<uint32_t> inventory;
// FIXME: TOO BAD...
/*
if( Creatures->ReadInventoryPtr(creature.origin, inventory) )
{
DFHack::Items * Items = DF->getItems();
printf("\tInventory:\n");
for(unsigned int i = 0; i < inventory.size(); i++)
{
printf("\t\t%s\n", Items->getItemDescription(inventory[i], Materials).c_str());
}
}
*/
/*
if(creature.pregnancy_timer > 0)
cout << "gives birth in " << creature.pregnancy_timer/1200 << " days. ";
@ -439,7 +453,13 @@ int main (int numargs, char ** args)
}
mem = DF->getMemoryInfo();
Materials->ReadAllMaterials();
Materials->ReadInorganicMaterials();
Materials->ReadOrganicMaterials();
Materials->ReadWoodMaterials();
Materials->ReadPlantMaterials();
Materials->ReadCreatureTypes();
Materials->ReadCreatureTypesEx();
Materials->ReadDescriptorColors();
if(!Tran->Start())
{
@ -450,6 +470,7 @@ int main (int numargs, char ** args)
//DF.InitViewAndCursor();
for(uint32_t i = 0; i < numCreatures; i++)
{
printf("%d/%d\n", i, numCreatures);
DFHack::t_creature temp;
Creatures->ReadCreature(i,temp);
if(check.empty() || string(Materials->raceEx[temp.race].rawname) == check)
@ -459,6 +480,7 @@ int main (int numargs, char ** args)
printCreature(DF,temp);
addrs.push_back(temp.origin);
}
printf("!\n");
}
if(addrs.size() <= 10)
{
@ -473,6 +495,7 @@ int main (int numargs, char ** args)
DF.ReadCreature(currentIdx, currentCreature);
printCreature(DF,currentCreature);
*/
Creatures->Finish();
DF->Detach();
#ifndef LINUX_BUILD

@ -37,7 +37,7 @@ int main ()
return 1;
}
DFHack::memory_info * mem = DF->getMemoryInfo();
DFHack::VersionInfo * mem = DF->getMemoryInfo();
Materials = DF->getMaterials();
Materials->ReadAllMaterials();
p = DF->getProcess();

@ -25,7 +25,7 @@ int main (void)
return 1;
}
DFHack::memory_info * mem = DF->getMemoryInfo();
DFHack::VersionInfo * mem = DF->getMemoryInfo();
DFHack::Position * Pos = DF->getPosition();
// get stone matgloss mapping
/*

@ -35,7 +35,7 @@ int main (int numargs, const char ** args)
}
DFHack::Process* p = DF->getProcess();
DFHack::memory_info* mem = DF->getMemoryInfo();
DFHack::VersionInfo* mem = DF->getMemoryInfo();
DFHack::Materials *Materials = DF->getMaterials();
cout << "----==== Inorganic ====----" << endl;

@ -56,7 +56,7 @@ int main (void)
{
cout << "Testing ProcessEnumerator" << endl;
ProcessEnumerator Penum("Memory.xml");
memory_info * mem;
VersionInfo * mem;
do
{
// make the ProcessEnumerator update its list of Processes
@ -90,7 +90,7 @@ int main (void)
{
cout << "Testing ContextManager" << endl;
ContextManager Cman("Memory.xml");
memory_info * mem;
VersionInfo * mem;
do
{
// make the ContextManager update its list of Contexts

@ -37,7 +37,7 @@ int main (int numargs, const char ** args)
}
DFHack::Process* p = DF->getProcess();
DFHack::memory_info* mem = DF->getMemoryInfo();
DFHack::VersionInfo* mem = DF->getMemoryInfo();
DFHack::Position * pos = DF->getPosition();
DFHack::Vegetation * v = DF->getVegetation();
DFHack::Materials * mat = DF->getMaterials();

@ -1,8 +1,5 @@
# don't use this file directly. use the one in the root folder of the project
# only build this stuff when BUILD_DFHACK_PLAYGROUND is set to ON
IF (BUILD_DFHACK_PLAYGROUND)
# this is required to ensure we use the right configuration for the system.
IF(UNIX)
add_definitions(-DLINUX_BUILD)
@ -56,8 +53,15 @@ TARGET_LINK_LIBRARIES(dfcatsplosion dfhack)
#ADD_EXECUTABLE(dfrenamer renamer.cpp)
#TARGET_LINK_LIBRARIES(dfrenamer dfhack)
# copypaste
# Author: belal
# copies the current buildings in a df map, and then designates the area to be dug
# mainly a proof of concept for my gui application dfCopyPaste
ADD_EXECUTABLE(dfcopypaste copypaste.cpp)
TARGET_LINK_LIBRARIES(dfcopypaste dfhack)
# this needs the C bindings
IF(BUILD_DFHACK_C_BINDIGS)
IF(BUILD_DFHACK_C_BINDINGS)
# for trying out some 'stuff'
ADD_EXECUTABLE(dftest test.cpp)
TARGET_LINK_LIBRARIES(dftest dfhack)
@ -65,7 +69,7 @@ IF(BUILD_DFHACK_C_BINDIGS)
dftest
RUNTIME DESTINATION bin
)
ENDIF(BUILD_DFHACK_C_BINDIGS)
ENDIF(BUILD_DFHACK_C_BINDINGS)
install(TARGETS
dfmoodump
@ -80,4 +84,3 @@ IF(UNIX)
RUNTIME DESTINATION bin
)
ENDIF(UNIX)
ENDIF (BUILD_DFHACK_PLAYGROUND)

@ -311,4 +311,11 @@ bool findString (SegmentedFinder* s, uint32_t *addr, const char * compare )
return false;
}
bool findStrBuffer (SegmentedFinder* s, uint32_t *addr, const char * compare )
{
if(strcmp((const char *)addr, compare) == 0)
return true;
return false;
}
#endif // SEGMENTED_FINDER_H

@ -21,7 +21,7 @@ using namespace DFHack;
int main ( int argc, char** argv )
{
DFHack::memory_info *mem;
DFHack::VersionInfo *mem;
DFHack::Process *proc;
uint32_t creature_pregnancy_offset;

@ -0,0 +1,449 @@
// Console version of DF copy paste, proof of concept
// By belal
#include <iostream>
#include <iomanip>
#include <climits>
#include <vector>
#include <sstream>
#include <ctime>
#include <cstdio>
#include <fstream>
#define DFHACK_WANT_MISCUTILS
#define DFHACK_WANT_TILETYPES
#include <DFHack.h>
#include "dfhack/modules/WindowIO.h"
using namespace DFHack;
//bool waitTillCursorState(DFHack::Context *DF, bool On);
//bool waitTillCursorPositionState(DFHack::Context *DF, int32_t x,int32_t y, int32_t z);
//change this if you are having problems getting correct results, lower if you would like to go faster
//const int WAIT_AMT = 25;
void sort(uint32_t &a,uint32_t &b)
{
if(a > b){
uint32_t c = b;
b = a;
a = c;
}
}
void sort(int32_t &a,int32_t &b)
{
if(a > b){
int16_t c = b;
b = a;
a = c;
}
}
void printVecOfVec(ostream &out, vector<vector<vector<string> > >vec,char sep){
for(int k=0;k<vec.size();k++){
for(int i =0;i<vec[k].size();i++){
for(int j=0;j<vec[k][i].size();j++){
out << vec[k][i][j];
if(j==vec[k][i].size()-1)
{
out << "\n";
}
else
{
out << sep;
}
}
}
out << "#<\n";
}
}
int main (int numargs, const char ** args)
{
map<string, string> buildCommands;
buildCommands["building_stockpilest"]="";
buildCommands["building_zonest"]="";
buildCommands["building_construction_blueprintst"]="";
buildCommands["building_wagonst"]="";
buildCommands["building_armor_standst"]="a";
buildCommands["building_bedst"]="b";
buildCommands["building_seatst"]="c";
buildCommands["building_burial_receptaclest"]="n";
buildCommands["building_doorst"]="d";
buildCommands["building_floodgatest"]="x";
buildCommands["building_floor_hatchst"]="H";
buildCommands["building_wall_gratest"]="W";
buildCommands["building_floor_gratest"]="G";
buildCommands["building_vertical_barsst"]="B";
buildCommands["building_floor_barsst"]="alt-b";
buildCommands["building_cabinetst"]="f";
buildCommands["building_containerst"]="h";
buildCommands["building_shopst"]="";
buildCommands["building_workshopst"]="";
buildCommands["building_alchemists_laboratoryst"]="wa";
buildCommands["building_carpenters_workshopst"]="wc";
buildCommands["building_farmers_workshopst"]="ww";
buildCommands["building_masons_workshopst"]="wm";
buildCommands["building_craftdwarfs_workshopst"]="wr";
buildCommands["building_jewelers_workshopst"]="wj";
buildCommands["building_metalsmiths_workshopst"]="wf";
buildCommands["building_magma_forgest"]="";
buildCommands["building_bowyers_workshopst"]="wb";
buildCommands["building_mechanics_workshopst"]="wt";
buildCommands["building_siege_workshopst"]="ws";
buildCommands["building_butchers_shopst"]="wU";
buildCommands["building_leather_worksst"]="we";
buildCommands["building_tanners_shopst"]="wn";
buildCommands["building_clothiers_shopst"]="wk";
buildCommands["building_fisheryst"]="wh";
buildCommands["building_stillst"]="wl";
buildCommands["building_loomst"]="wo";
buildCommands["building_quernst"]="wq";
buildCommands["building_kennelsst"]="k";
buildCommands["building_kitchenst"]="wz";
buildCommands["building_asheryst"]="wy";
buildCommands["building_dyers_shopst"]="wd";
buildCommands["building_millstonest"]="wM";
buildCommands["building_farm_plotst"]="p";
buildCommands["building_weapon_rackst"]="r";
buildCommands["building_statuest"]="s";
buildCommands["building_tablest"]="t";
buildCommands["building_paved_roadst"]="o";
buildCommands["building_bridgest"]="g";
buildCommands["building_wellst"]="l";
buildCommands["building_siege enginest"]="i";
buildCommands["building_catapultst"]="ic";
buildCommands["building_ballistast"]="ib";
buildCommands["building_furnacest"]="";
buildCommands["building_wood_furnacest"]="ew";
buildCommands["building_smelterst"]="es";
buildCommands["building_glass_furnacest"]="ek";
buildCommands["building_kilnst"]="ek";
buildCommands["building_magma_smelterst"]="es";
buildCommands["building_magma_glass_furnacest"]="ek";
buildCommands["building_magma_kilnst"]="ek";
buildCommands["building_glass_windowst"]="y";
buildCommands["building_gem_windowst"]="Y";
buildCommands["building_tradedepotst"]="D";
buildCommands["building_mechanismst"]="";
buildCommands["building_leverst"]="Tl";
buildCommands["building_pressure_platest"]="Tp";
buildCommands["building_cage_trapst"]="Tc";
buildCommands["building_stonefall_trapst"]="Ts";
buildCommands["building_weapon_trapst"]="Tw";
buildCommands["building_spikest"]="";
buildCommands["building_animal_trapst"]="m";
buildCommands["building_screw_pumpst"]="Ms";
buildCommands["building_water_wheelst"]="Mw";
buildCommands["building_windmillst"]="Mm";
buildCommands["building_gear_assemblyst"]="Mg";
buildCommands["building_horizontal_axlest"]="Mh";
buildCommands["building_vertical_axlest"]="Mv";
buildCommands["building_supportst"]="S";
buildCommands["building_cagest"]="j";
buildCommands["building_archery_targetst"]="A";
buildCommands["building_restraintst"]="v";
DFHack::ContextManager DFMgr("Memory.xml");
DFHack::Context *DF = DFMgr.getSingleContext();
try
{
DF->Attach();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
return 1;
}
DFHack::Position *Pos = DF->getPosition();
DFHack::VersionInfo* mem = DF->getMemoryInfo();
DFHack::Process * p = DF->getProcess();
OffsetGroup * OG_Maps = mem->getGroup("Maps");
OffsetGroup * OG_MapBlock = OG_Maps->getGroup("block");
OffsetGroup * OG_LocalFt = OG_Maps->getGroup("features")->getGroup("local");
uint32_t designations = OG_MapBlock->getOffset("designation");
uint32_t block_feature1 = OG_MapBlock->getOffset("feature_local");
uint32_t block_feature2 = OG_MapBlock->getOffset("feature_global");
uint32_t region_x_offset = OG_Maps->getAddress("region_x");
uint32_t region_y_offset = OG_Maps->getAddress("region_y");
uint32_t region_z_offset = OG_Maps->getAddress("region_z");
uint32_t feature1_start_ptr = OG_LocalFt->getAddress("start_ptr");
int32_t regionX, regionY, regionZ;
// read position of the region inside DF world
p->readDWord (region_x_offset, (uint32_t &)regionX);
p->readDWord (region_y_offset, (uint32_t &)regionY);
p->readDWord (region_z_offset, (uint32_t &)regionZ);
while(1){
int32_t cx1,cy1,cz1;
cx1 = -30000;
while(cx1 == -30000){
DF->ForceResume();
cout << "Set cursor at first position, then press any key";
cin.ignore();
DF->Suspend();
Pos->getCursorCoords(cx1,cy1,cz1);
}
uint32_t tx1,ty1,tz1;
tx1 = cx1/16;
ty1 = cy1/16;
tz1 = cz1;
int32_t cx2,cy2,cz2;
cx2 = -30000;
while(cx2 == -30000){
DF->Resume();
cout << "Set cursor at second position, then press any key";
cin.ignore();
DF->Suspend();
Pos->getCursorCoords(cx2,cy2,cz2);
}
uint32_t tx2,ty2,tz2;
tx2 = cx2/16;
ty2 = cy2/16;
tz2 = cz2;
sort(tx1,tx2);
sort(ty1,ty2);
sort(tz1,tz2);
sort(cx1,cx2);
sort(cy1,cy2);
sort(cz1,cz2);
vector <vector<vector<string> > >dig(cz2-cz1+1,vector<vector<string> >(cy2-cy1+1,vector<string>(cx2-cx1+1)));
vector <vector<vector<string> > >build(cz2-cz1+1,vector<vector<string> >(cy2-cy1+1,vector<string>(cx2-cx1+1)));
mapblock40d block;
DFHack::Maps *Maps = DF->getMaps();
Maps->Start();
for(uint32_t y = ty1;y<=ty2;y++)
{
for(uint32_t x = tx1;x<=tx2;x++)
{
for(uint32_t z = tz1;z<=tz2;z++)
{
if(Maps->isValidBlock(x,y,z))
{
if(Maps->ReadBlock40d(x,y,z,&block))
{
int ystart,yend,xstart,xend;
ystart=xstart=0;
yend=xend=15;
if(y == ty2)
{
yend = cy2 % 16;
}
if(y == ty1)
{
ystart = cy1 % 16;
}
if(x == tx2)
{
xend = cx2 % 16;
}
if(x == tx1)
{
xstart = cx1 % 16;
}
int zidx = z-tz1;
for(int yy = ystart; yy <= yend;yy++)
{
int yidx = yy+(16*(y-ty1)-(cy1%16));
for(int xx = xstart; xx <= xend;xx++)
{
int xidx = xx+(16*(x-tx1)-(cx1%16));
if(DFHack::isOpenTerrain(block.tiletypes[xx][yy]) || DFHack::isFloorTerrain(block.tiletypes[xx][yy])) {dig[zidx][yidx][xidx] = "d";}
else if(DFHack::STAIR_DOWN == DFHack::tileTypeTable[block.tiletypes[xx][yy]].c){ dig [zidx][yidx][xidx] = "j"; build [zidx][yidx][xidx] = "Cd";}
else if(DFHack::STAIR_UP == DFHack::tileTypeTable[block.tiletypes[xx][yy]].c){ dig [zidx][yidx][xidx] = "u"; build [zidx][yidx][xidx] = "Cu";}
else if(DFHack::STAIR_UPDOWN == DFHack::tileTypeTable[block.tiletypes[xx][yy]].c){ dig [zidx][yidx][xidx] = "i"; build [zidx][yidx][xidx] = "Cx";}
else if(DFHack::isRampTerrain(block.tiletypes[xx][yy])){dig [zidx][yidx][xidx] = "r";build [zidx][yidx][xidx] = "Cr";}
else if(DFHack::isWallTerrain(block.tiletypes[xx][yy])){build [zidx][yidx][xidx] = "Cw";}
}
yidx++;
}
}
}
}
}
}
DFHack::Buildings * Bld = DF->getBuildings();
std::map <uint32_t, std::string> custom_workshop_types;
uint32_t numBuildings;
if(Bld->Start(numBuildings))
{
Bld->ReadCustomWorkshopTypes(custom_workshop_types);
for(uint32_t i = 0; i < numBuildings; i++)
{
DFHack::t_building temp;
Bld->Read(i, temp);
if(temp.type != 0xFFFFFFFF) // check if type isn't invalid
{
std::string typestr;
mem->resolveClassIDToClassname(temp.type, typestr);
if(temp.z == cz1 && cx1 <= temp.x1 && cx2 >= temp.x2 && cy1 <= temp.y1 && cy2 >= temp.y2)
{
string currStr = build[temp.z-cz1][temp.y1-cy1][temp.x1-cx1];
stringstream stream;
string newStr = buildCommands[typestr];
if(temp.x1 != temp.x2)
{
stream << "(" << temp.x2-temp.x1+1 << "x" << temp.y2-temp.y1+1 << ")";
newStr += stream.str();
}
build[temp.z-cz1][temp.y1-cy1][temp.x1-cx1] = newStr + currStr;
}
}
}
}
// for testing purposes
//ofstream outfile("test.txt");
// printVecOfVec(outfile, dig,'\t');
// outfile << endl;
// printVecOfVec(outfile, build,'\t');
// outfile << endl;
// outfile.close();
int32_t cx3,cy3,cz3,cx4,cy4,cz4;
uint32_t tx3,ty3,tz3,tx4,ty4,tz4;
char result;
while(1){
cx3 = -30000;
while(cx3 == -30000){
DF->Resume();
cout << "Set cursor at new position, then press any key:";
result = cin.get();
DF->Suspend();
Pos->getCursorCoords(cx3,cy3,cz3);
}
if(result == 'q'){
break;
}
cx4 = cx3+cx2-cx1;
cy4 = cy3+cy2-cy1;
cz4 = cz3+cz2-cz1;
tx3=cx3/16;
ty3=cy3/16;
tz3=cz3;
tx4=cx4/16;
ty4=cy4/16;
tz4=cz4;
DFHack::WindowIO * Win = DF->getWindowIO();
designations40d designationBlock;
for(uint32_t y = ty3;y<=ty4;y++)
{
for(uint32_t x = tx3;x<=tx4;x++)
{
for(uint32_t z = tz3;z<=tz4;z++)
{
Maps->Start();
Maps->ReadBlock40d(x,y,z,&block);
Maps->ReadDesignations(x,y,z,&designationBlock);
int ystart,yend,xstart,xend;
ystart=xstart=0;
yend=xend=15;
if(y == ty4){
yend = cy4 % 16;
}
if(y == ty3){
ystart = cy3 % 16;
}
if(x == tx4){
xend = cx4 % 16;
}
if(x == tx3){
xstart = cx3 % 16;
}
int zidx = z-tz3;
for(int yy = ystart; yy <= yend;yy++){
int yidx = yy+(16*(y-ty3)-(cy3%16));
for(int xx = xstart; xx <= xend;xx++){
int xidx = xx+(16*(x-tx3)-(cx3%16));
if(dig[zidx][yidx][xidx] != ""){
char test = dig[zidx][yidx][xidx].c_str()[0];
switch (test){
case 'd':
designationBlock[xx][yy].bits.dig = DFHack::designation_default;
break;
case 'i':
designationBlock[xx][yy].bits.dig = DFHack::designation_ud_stair;
break;
case 'u':
designationBlock[xx][yy].bits.dig = DFHack::designation_u_stair;
break;
case 'j':
designationBlock[xx][yy].bits.dig = DFHack::designation_d_stair;
break;
case 'r':
designationBlock[xx][yy].bits.dig = DFHack::designation_ramp;
break;
}
}
}
yidx++;
}
Maps->Start();
Maps->WriteDesignations(x,y,z,&designationBlock);
}
}
}
}
}
DF->Detach();
#ifndef LINUX_BUILD
std::cout << "Done. Press any key to continue" << std::endl;
cin.ignore();
#endif
return 0;
}
/*
bool waitTillCursorState(DFHack::Context *DF, bool On)
{
DFHack::WindowIO * w = DF->getWindowIO();
DFHack::Position * p = DF->getPosition();
int32_t x,y,z;
int tryCount = 0;
DF->Suspend();
bool cursorResult = p->getCursorCoords(x,y,z);
while(tryCount < 50 && On && !cursorResult || !On && cursorResult)
{
DF->Resume();
w->TypeSpecial(DFHack::WAIT,1,WAIT_AMT);
tryCount++;
DF->Suspend();
cursorResult = p->getCursorCoords(x,y,z);
}
if(tryCount >= 50)
{
cerr << "Something went wrong, cursor at x: " << x << " y: " << y << " z: " << z << endl;
return false;
}
DF->Resume();
return true;
}
bool waitTillCursorPositionState(DFHack::Context *DF, int32_t x,int32_t y, int32_t z)
{
DFHack::WindowIO * w = DF->getWindowIO();
DFHack::Position * p = DF->getPosition();
int32_t x2,y2,z2;
int tryCount = 0;
DF->Suspend();
bool cursorResult = p->getCursorCoords(x2,y2,z2);
while(tryCount < 50 && (x != x2 || y != y2 || z != z2))
{
DF->Resume();
w->TypeSpecial(DFHack::WAIT,1,WAIT_AMT);
tryCount++;
DF->Suspend();
cursorResult = p->getCursorCoords(x2,y2,z2);
}
if(tryCount >= 50)
{
cerr << "Something went wrong, cursor at x: " << x2 << " y: " << y2 << " z: " << z2 << endl;
return false;
}
DF->Resume();
return true;
}*/

@ -181,12 +181,12 @@ bool getRanges(DFHack::Process * p, vector <DFHack::t_memrange>& selected_ranges
{
// empty input, assume default. observe the length of the memory range vector
// these are hardcoded values, intended for my convenience only
if(p->getDescriptor()->getOS() == DFHack::memory_info::OS_WINDOWS)
if(p->getDescriptor()->getOS() == DFHack::VersionInfo::OS_WINDOWS)
{
start = min(11, (int)ranges.size());
end = min(14, (int)ranges.size());
}
else if(p->getDescriptor()->getOS() == DFHack::memory_info::OS_LINUX)
else if(p->getDescriptor()->getOS() == DFHack::VersionInfo::OS_LINUX)
{
start = min(2, (int)ranges.size());
end = min(4, (int)ranges.size());
@ -482,6 +482,22 @@ void FindPtrVectorsByObjectAddress(DFHack::ContextManager & DFMgr, vector <DFHac
}
}
void FindStrBufs(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ranges)
{
vector <uint64_t> found;
string select;
while (Incremental(found,"buffer",select,"buffer","buffers"))
{
DFMgr.Refresh();
DFHack::Context * DF = DFMgr.getSingleContext();
DF->Attach();
SegmentedFinder sf(ranges,DF);
sf.Find< const char * ,uint32_t>(select.c_str(),1,found, findStrBuffer);
DF->Detach();
}
}
void FindStrings(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ranges)
{
@ -793,18 +809,19 @@ int main (void)
vector <DFHack::t_memrange> selected_ranges;
getRanges(p,selected_ranges);
DFHack::memory_info *minfo = DF->getMemoryInfo();
DFHack::memory_info::OSType os = minfo->getOS();
DFHack::VersionInfo *minfo = DF->getMemoryInfo();
DFHack::VersionInfo::OSType os = minfo->getOS();
string prompt =
"Select search type: 1=number(default), 2=vector by length, 3=vector>object>string,\n"
" 4=string, 5=automated offset search, 6=vector by address in its array,\n"
" 7=pointer vector by address of an object, 8=vector>first object>string\n";
" 7=pointer vector by address of an object, 8=vector>first object>string\n"
" 9=string buffers\n";
int mode;
do
{
getNumber(prompt,mode, 1, false);
} while (mode < 1 || mode > 8 );
} while (mode < 1 || mode > 9 );
switch (mode)
{
case 1:
@ -838,6 +855,10 @@ int main (void)
DF->Detach();
FindVectorByFirstObjectRawname(DFMgr, selected_ranges);
break;
case 9:
DF->Detach();
FindStrBufs(DFMgr, selected_ranges);
break;
default:
cout << "not implemented :(" << endl;
}

@ -6,7 +6,7 @@ using namespace std;
#include <DFHack.h>
DFHack::Materials * Materials;
DFHack::memory_info *mem;
DFHack::VersionInfo *mem;
vector< vector<string> > englishWords;
vector< vector<string> > foreignWords;

@ -64,7 +64,13 @@ TARGET_LINK_LIBRARIES(dfposition dfhack)
ADD_EXECUTABLE(dfdoffsets dumpoffsets.cpp)
TARGET_LINK_LIBRARIES(dfdoffsets dfhack)
# change the weather
ADD_EXECUTABLE(dfweather weather.cpp)
TARGET_LINK_LIBRARIES(dfweather dfhack)
IF(UNIX)
SET(VEINLOOK_BUILT "NO")
SET(CURSES_NEED_WIDE "YES")
SET(CURSES_NEED_NCURSES "NO")
find_package(Curses QUIET)
@ -114,11 +120,6 @@ dfexpbench
dfsuspend
dfflows
dfliquids
dfweather
RUNTIME DESTINATION bin
)
IF(UNIX)
install(TARGETS
dfveinlook
RUNTIME DESTINATION bin
)
ENDIF(UNIX)

@ -32,7 +32,7 @@ int main ()
return 1;
}
DFHack::memory_info * mem = DF->getMemoryInfo();
DFHack::VersionInfo * mem = DF->getMemoryInfo();
p = DF->getProcess();
uint32_t item_vec_offset = 0;
try

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

@ -43,12 +43,13 @@ int main (void)
string mode="magma";
string brush="point";
string flowmode="f+";
string setmode ="s.";
int amount = 7;
while(!end)
{
DF->Resume();
string command = "";
cout <<"[" << mode << ":" << amount << ":" << flowmode << "]# ";
cout <<"[" << mode << ":" << amount << ":" << flowmode << ":" << setmode << "]# ";
getline(cin, command);
if(command=="help")
{
@ -57,6 +58,10 @@ int main (void)
<< "w - switch to water" << endl
<< "o - make obsidian wall instead" << endl
<< "f - flow bits only" << endl
<< "Set-Modes:" << endl
<< "s+ - only add" << endl
<< "s. - set" << endl
<< "s- - only remove" << endl
<< "Properties:" << endl
<< "f+ - make the spawned liquid flow" << endl
<< "f. - don't change flow state (read state in flow mode)" << endl
@ -125,6 +130,18 @@ int main (void)
{
flowmode = "f.";
}
else if(command == "s+")
{
setmode = "s+";
}
else if(command == "s-")
{
setmode = "s-";
}
else if(command == "s.")
{
setmode = "s.";
}
// blah blah, bad code, bite me.
else if(command == "0")
amount = 0;
@ -185,7 +202,7 @@ int main (void)
}
}
// quick hack, do not use for serious stuff
/*
else if(mode == "starruby")
{
if(Maps->isValidBlock((x/16),(y/16),z))
@ -236,6 +253,7 @@ int main (void)
zzz --;
}
}
*/
else
{
// place the magma
@ -248,7 +266,21 @@ int main (void)
// fix temperatures so we don't produce lethal heat traps
if(amount == 0 || designations[x%16][y%16].bits.liquid_type == DFHack::liquid_magma && mode == "water")
temp1[x%16][y%16] = temp2[x%16][y%16] = 10015;
designations[x%16][y%16].bits.flow_size = amount;
DFHack::naked_designation & flow = designations[x%16][y%16].bits;
if(setmode == "s.")
{
flow.flow_size = amount;
}
else if(setmode == "s+")
{
if(flow.flow_size < amount)
flow.flow_size = amount;
}
else if(setmode == "s-")
{
if (flow.flow_size > amount)
flow.flow_size = amount;
}
}
if(mode == "magma")
designations[x%16][y%16].bits.liquid_type = DFHack::liquid_magma;
@ -264,7 +296,21 @@ int main (void)
// fix temperatures so we don't produce lethal heat traps
if(amount == 0 || designations[xx][yy].bits.liquid_type == DFHack::liquid_magma && mode == "water")
temp1[xx%16][yy%16] = temp2[xx%16][yy%16] = 10015;
designations[xx][yy].bits.flow_size = amount;
DFHack::naked_designation & flow= designations[xx][yy].bits;
if(setmode == "s.")
{
flow.flow_size = amount;
}
else if(setmode == "s+")
{
if(flow.flow_size < amount)
flow.flow_size = amount;
}
else if(setmode == "s-")
{
if (flow.flow_size > amount)
flow.flow_size = amount;
}
}
if(mode == "magma")
designations[xx][yy].bits.liquid_type = DFHack::liquid_magma;

@ -32,16 +32,22 @@ int main (int numargs, const char ** args)
}
DFHack::Position *Pos = DF->getPosition();
DFHack::memory_info* mem = DF->getMemoryInfo();
DFHack::VersionInfo* mem = DF->getMemoryInfo();
DFHack::Maps *Maps = DF->getMaps();
DFHack::Process * p = DF->getProcess();
uint32_t designatus = mem->getOffset("map_data_designation");
uint32_t block_feature1 = mem->getOffset("map_data_feature_local");
uint32_t block_feature2 = mem->getOffset("map_data_feature_global");
uint32_t region_x_offset = mem->getAddress("region_x");
uint32_t region_y_offset = mem->getAddress("region_y");
uint32_t region_z_offset = mem->getAddress("region_z");
uint32_t feature1_start_ptr = mem->getAddress("local_feature_start_ptr");
OffsetGroup *mapsg = mem->getGroup("Maps");
OffsetGroup *mapblockg = mapsg->getGroup("block");
OffsetGroup *localfeatg = mapsg->getGroup("features")->getGroup("local");
uint32_t region_x_offset = mapsg->getAddress("region_x");
uint32_t region_y_offset = mapsg->getAddress("region_y");
uint32_t region_z_offset = mapsg->getAddress("region_z");
uint32_t designatus = mapblockg->getOffset("designation");
uint32_t block_feature1 = mapblockg->getOffset("feature_local");
uint32_t block_feature2 = mapblockg->getOffset("feature_global");
uint32_t feature1_start_ptr = localfeatg->getAddress("start_ptr");
int32_t regionX, regionY, regionZ;
// read position of the region inside DF world
@ -78,14 +84,13 @@ int main (int numargs, const char ** args)
if(tileTypeTable[tiletype].name)
std::cout << " = " << tileTypeTable[tiletype].name;
std::cout << std::endl;
std::cout <<"temperature1: " << tmpb1[tileX][tileY] << " U" << std::endl;
std::cout <<"temperature2: " << tmpb2[tileX][tileY] << " U" << std::endl;
// biome, geolayer
std::cout << "biome: " << des.biome << std::endl;
std::cout << "geolayer: " << des.geolayer_index << std::endl;
// liquids
if(des.flow_size)
{

@ -313,6 +313,11 @@ int main (int argc, const char* argv[])
std::sort(matss.begin(), matss.end(), compare_pair_second<>());
for(int i = 0; i < matss.size();i++)
{
if(matss[i].first >= Mats->inorganic.size())
{
cerr << "Error, material out of bounds: " << matss[i].first << endl;
continue;
}
cout << Mats->inorganic[matss[i].first].id << " : " << matss[i].second << endl;
}
DF->Detach();

@ -6,6 +6,7 @@
using namespace std;
#include <DFHack.h>
#include <dfhack/modules/Gui.h>
struct hideblock
{
@ -37,6 +38,19 @@ int main (void)
}
DFHack::Maps *Maps =DF->getMaps();
DFHack::Gui *Gui =DF->getGui();
// walk the map, save the hide bits, reveal.
cout << "Pausing..." << endl;
// horrible hack to make sure the pause is really set
// preblem here is that we could be 'arriving' at the wrong time and DF could be in the middle of a frame.
// that could mean that revealing, even with suspending DF's thread, would mean unleashing hell *in the same frame*
// this here hack sets the pause state, resumes DF, waits a second for it to enter the pause (I know, BS value.) and suspends.
Gui->SetPauseState(true);
DF->Resume();
sleep(1);
DF->Suspend();
// init the map
if(!Maps->Start())
{
@ -47,10 +61,11 @@ int main (void)
return 1;
}
cout << "Revealing, please wait..." << endl;
Maps->getSize(x_max,y_max,z_max);
vector <hideblock> hidesaved;
// walk the map, save the hide bits, reveal.
cout << "Revealing... please wait." << endl;
for(uint32_t x = 0; x< x_max;x++)
{
for(uint32_t y = 0; y< y_max;y++)
@ -80,8 +95,10 @@ int main (void)
}
// FIXME: force game pause here!
DF->Detach();
cout << "Map revealed. Close window/force exit to keep it that way." << endl;
cout << "Press any key to unreveal. Don't close DF or unpause in that case!" << endl;
cout << "Map revealed. The game has been paused for you." << endl;
cout << "Unpausing can unleash the forces of hell!" << endl << endl;
cout << "Press any key to unreveal." << endl;
cout << "Close to keep the map revealed." << endl;
cin.ignore();
cout << "Unrevealing... please wait." << endl;
// FIXME: do some consistency checks here!

@ -723,6 +723,7 @@ main(int argc, char *argv[])
Maps->Start();
Mats->Start();
Mats->ReadInorganicMaterials();
Mats->ReadCreatureTypes();
uint32_t effectnum;
/*
if(DF.InitReadEffects(effectnum))

@ -0,0 +1,98 @@
// Just show some position data
#include <iostream>
#include <iomanip>
#include <climits>
#include <vector>
#include <sstream>
#include <ctime>
#include <cstdio>
#define DFHACK_WANT_MISCUTILS
#define DFHACK_WANT_TILETYPES
#include <DFHack.h>
using namespace DFHack;
void printWeather(DFHack::WeatherType current)
{
switch (current)
{
case CLEAR:
cout << "The sky is clear." << endl;
cout << "Options:" << endl;
cout << "'r' to make it rain." << endl;
cout << "'s' to make it snow." << endl;
break;
case RAINING:
cout << "It is raining." << endl;
cout << "Options:" << endl;
cout << "'c' to clear the sky." << endl;
cout << "'s' to make it snow." << endl;
break;
case SNOWING:
cout << "It is snowing." << endl;
cout << "Options:" << endl;
cout << "'c' to clear the sky." << endl;
cout << "'r' to make it rain." << endl;
break;
}
cout << "'q' to quit." << endl;
cout << "anything else to refresh" << endl;
cout << ">";
}
using namespace DFHack;
int main (int numargs, const char ** args)
{
DFHack::ContextManager DFMgr("Memory.xml");
DFHack::Context *DF = DFMgr.getSingleContext();
try
{
DF->Attach();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
return 1;
}
World *W = DF->getWorld();
W->Start();
bool end = false;
while(!end)
{
WeatherType current = (WeatherType) W->ReadCurrentWeather();
DF->Resume();
string command = "";
printWeather(current);
getline(cin, command);
DF->Suspend();
if(command == "c")
{
W->SetCurrentWeather(CLEAR);
}
else if(command == "r")
{
W->SetCurrentWeather(RAINING);
}
else if(command == "s")
{
W->SetCurrentWeather(SNOWING);
}
else if(command == "q")
{
end = true;
}
}
#ifndef LINUX_BUILD
std::cout << "Done. Press any key to continue" << std::endl;
cin.ignore();
#endif
DF->Detach();
return 0;
}