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 # a file generated by cmake
dfhack/include/config.h dfhack/include/config.h
library/private/config.h
# any build folders # any build folders
build*/ build*/

@ -4,6 +4,11 @@ cmake_minimum_required(VERSION 2.6)
SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/Modules) SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/Modules)
SET ( DFHACK_VERSION "0.4.1.0-dev" ) 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 # disable warning, autosearch
if(COMMAND cmake_policy) if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW) 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_PLAYGROUND "Build tools from the playground folder" OFF)
OPTION(BUILD_DFHACK_C_BINDIGS "Build the C portion of the library" ON) 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_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/include/)
include_directories (${CMAKE_SOURCE_DIR}/library/shm/) include_directories (${CMAKE_SOURCE_DIR}/library/shm/)
@ -35,12 +42,26 @@ include_directories (${CMAKE_SOURCE_DIR}/library/depends/argstream/)
add_subdirectory (library) add_subdirectory (library)
IF(BUILD_DFHACK_SUPPORTED)
add_subdirectory (tools/supported)
ENDIF(BUILD_DFHACK_SUPPORTED)
IF(BUILD_OFFSET_EDITOR) IF(BUILD_OFFSET_EDITOR)
add_subdirectory (offsetedit) add_subdirectory (offsetedit)
ENDIF(BUILD_OFFSET_EDITOR) ENDIF(BUILD_OFFSET_EDITOR)
add_subdirectory (library/shm) IF(BUILD_DFHACK_SHM)
add_subdirectory (tools/examples) add_subdirectory (library/shm)
add_subdirectory (tools/playground) ENDIF(BUILD_DFHACK_SHM)
add_subdirectory (tools/supported)
add_subdirectory (doc) 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="creature_vector">0x168E73C</Address>
<Address name="dwarf_race_index">0x014b9f1c</Address> <Address name="dwarf_race_index">0x014b9f1c</Address>
<Offset name="creature_soulskill_vector">0X1F4</Offset> <Offset name="creature_soulskill_vector">0X1F4</Offset>
<Offset name="creature_inventory_vector">0x2FC</Offset>
<Offset name="creature_physical">0x4AC</Offset> <Offset name="creature_physical">0x4AC</Offset>
<Offset name="creature_appearance_vector">0x64c</Offset> <!-- Maybe slightly wrong --> <Offset name="creature_appearance_vector">0x64c</Offset> <!-- Maybe slightly wrong -->
<Offset name="creature_artifact_name">0x71c</Offset> <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"> <Entry version="v0.31.12" os="windows" id="0.31.12" base="0.31.11">
<String name="md5">f0459165a426a9f2dd8d957e9fa7f01d</String> <String name="md5">f0459165a426a9f2dd8d957e9fa7f01d</String>
<HexValue name="pe_timestamp">0x4C4C32E7</HexValue> <HexValue name="pe_timestamp">0x4C4C32E7</HexValue>
<Address name="screen_tiles_pointer">0x18313D0</Address>
</Entry> </Entry>
.-"""-. .-"""-.
' \ ' \
@ -2359,6 +2361,7 @@ map_data_1b60_offset 0x1B9c
</Entry> </Entry>
<Entry version="v0.31.12" os="linux" id="30_12lin" base="30_11lin" rebase="-0x1000"> <Entry version="v0.31.12" os="linux" id="30_12lin" base="30_11lin" rebase="-0x1000">
<String name="md5">e79cead03187ecb692961b316b7cdcd4</String> <String name="md5">e79cead03187ecb692961b316b7cdcd4</String>
<Address name="screen_tiles_pointer">0x09487970</Address>
</Entry> </Entry>
</MemoryDescriptors> </MemoryDescriptors>
</DFExtractor> </DFExtractor>

@ -10,8 +10,6 @@
# http://tobias.rautenkranz.ch/cmake/doxygen/ # http://tobias.rautenkranz.ch/cmake/doxygen/
# but it is hard to understand... # but it is hard to understand...
IF (BUILD_DFHACK_DOCUMENTATION)
FIND_PACKAGE(Doxygen) FIND_PACKAGE(Doxygen)
IF(DOXYGEN_FOUND) IF(DOXYGEN_FOUND)
@ -64,5 +62,3 @@ IF(DOXYGEN_FOUND)
ELSE(DOXYGEN_FOUND) ELSE(DOXYGEN_FOUND)
MESSAGE (FATAL_ERROR "doxygen binary couldn't be found") MESSAGE (FATAL_ERROR "doxygen binary couldn't be found")
ENDIF(DOXYGEN_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/depends/argstream/)
include_directories (${CMAKE_SOURCE_DIR}/library/private/) include_directories (${CMAKE_SOURCE_DIR}/library/private/)
SET(PROJECT_HDRS_INTERNAL
private/ContextShared.h
private/Internal.h
)
SET(PROJECT_HDRS SET(PROJECT_HDRS
private/DFMemInfoManager.h include/DFHack.h
private/ContextShared.h include/dfhack/DFContext.h
private/Internal.h include/dfhack/DFContextManager.h
include/dfhack/DFError.h include/dfhack/DFError.h
include/dfhack/DFMemInfo.h include/dfhack/DFExport.h
include/dfhack/DFProcessEnumerator.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/DFProcess.h
include/dfhack/DFProcessEnumerator.h
include/dfhack/DFTileTypes.h include/dfhack/DFTileTypes.h
include/dfhack/DFTypes.h include/dfhack/DFTypes.h
include/dfhack/DFVector.h include/dfhack/DFVector.h
include/dfhack-c/DFTypes_C.h include/dfhack/VersionInfoFactory.h
include/dfhack-c/DFContext_C.h include/dfhack/VersionInfo.h
include/dfhack/DFIntegers.h
include/dfhack/modules/Buildings.h include/dfhack/modules/Buildings.h
include/dfhack/modules/Constructions.h include/dfhack/modules/Constructions.h
include/dfhack/modules/Creatures.h include/dfhack/modules/Creatures.h
@ -55,13 +64,26 @@ include/dfhack/modules/World.h
) )
SET(PROJECT_C_HDRS SET(PROJECT_C_HDRS
include/DFHack_C.h
include/dfhack-c/DFTypes_C.h include/dfhack-c/DFTypes_C.h
include/dfhack-c/DFContext_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 SET(PROJECT_SRCS
DFMemInfo.cpp VersionInfo.cpp
DFMemInfoManager.cpp VersionInfoFactory.cpp
DFContextManager.cpp DFContextManager.cpp
DFContext.cpp DFContext.cpp
DFProcessEnumerator.cpp DFProcessEnumerator.cpp
@ -134,10 +156,10 @@ ELSE(UNIX)
LIST(APPEND PROJECT_SRCS ${PROJECT_SRCS_WINDOWS}) LIST(APPEND PROJECT_SRCS ${PROJECT_SRCS_WINDOWS})
ENDIF(UNIX) ENDIF(UNIX)
IF(BUILD_DFHACK_C_BINDIGS) IF(BUILD_DFHACK_C_BINDINGS)
LIST(APPEND PROJECT_HDRS ${PROJECT_C_HDRS}) LIST(APPEND PROJECT_HDRS ${PROJECT_C_HDRS})
LIST(APPEND PROJECT_SRCS ${PROJECT_C_SRCS}) 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 ) 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 # So, $(TargetDir) is ignored by cmake, and replaced with the actual output directory by MSVC
ADD_CUSTOM_COMMAND(TARGET dfhack POST_BUILD 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 ADD_CUSTOM_COMMAND(TARGET dfhack POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/Compile.html $(TargetDir)/Compile.html 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 ADD_CUSTOM_COMMAND(TARGET dfhack POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/Readme.html $(TargetDir)/Readme.html 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) else(MSVC)
# Just put the file in the output directory on Linux and Mac # 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}/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}/Readme.html ${DATA_OUTPUT_PATH}/Readme.html COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/LICENSE ${DATA_OUTPUT_PATH}/LICENSE.txt COPYONLY)
endif(MSVC) endif(MSVC)
IF(UNIX) IF(UNIX)
install(TARGETS dfhack LIBRARY DESTINATION lib) install(TARGETS dfhack LIBRARY DESTINATION lib)
install(FILES ${CMAKE_SOURCE_DIR}/output/Memory.xml DESTINATION share/dfhack) 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) ENDIF(UNIX)

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

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

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

@ -23,7 +23,7 @@ distribution.
*/ */
#include "Internal.h" #include "Internal.h"
#include "dfhack/DFProcess.h" #include "dfhack/DFProcess.h"
#include "dfhack/DFMemInfo.h" #include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h" #include "dfhack/DFError.h"
#include <errno.h> #include <errno.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
@ -44,7 +44,7 @@ class WineProcess::Private
self = self_; self = self_;
}; };
~Private(){}; ~Private(){};
memory_info * my_descriptor; VersionInfo * my_descriptor;
Process * self; Process * self;
pid_t my_handle; pid_t my_handle;
uint32_t my_pid; uint32_t my_pid;
@ -53,10 +53,13 @@ class WineProcess::Private
bool attached; bool attached;
bool suspended; bool suspended;
bool identified; 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)) : d(new Private(this))
{ {
char dir_name [256]; char dir_name [256];
@ -124,12 +127,12 @@ bool WineProcess::isIdentified()
return d->identified; 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; md5wrapper md5;
// get hash of the running DF process // get hash of the running DF process
string hash = md5.getHashFromFile(exe_file); string hash = md5.getHashFromFile(exe_file);
vector<memory_info *>::iterator it; vector<VersionInfo *>::iterator it;
// iterate over the list of memory locations // iterate over the list of memory locations
for ( it=known_versions.begin() ; it < known_versions.end(); it++ ) 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; string thishash;
try try
{ {
thishash = (*it)->getString("md5"); thishash = (*it)->getMD5();
} }
catch (Error::MissingMemoryDefinition& e) catch (Error::MissingMemoryDefinition& e)
{ {
continue; continue;
} }
// are the md5 hashes the same? // 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 // 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; my_descriptor = m;
m->setParentProcess(dynamic_cast<Process *>( self )); m->setParentProcess(dynamic_cast<Process *>( self ));
my_handle = my_pid = pid; my_handle = my_pid = pid;
// tell WineProcess about the /proc/PID/mem file // tell WineProcess about the /proc/PID/mem file
memFile = mem_file; memFile = mem_file;
identified = true; 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; return true;
} }
} }
@ -173,7 +180,7 @@ WineProcess::~WineProcess()
delete d; delete d;
} }
memory_info * WineProcess::getDescriptor() VersionInfo * WineProcess::getDescriptor()
{ {
return d->my_descriptor; 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) size_t WineProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{ {
/* uint32_t start_offset = offset + d->STLSTR_buf_off;
MSVC++ string size_t length = readDWord(offset + d->STLSTR_size_off);
ptr allocator size_t capacity = readDWord(offset + d->STLSTR_cap_off);
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);
size_t read_real = min(length, bufcapacity-1);// keep space for null termination size_t read_real = min(length, bufcapacity-1);// keep space for null termination
// read data from inside the string structure // 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) const string WineProcess::readSTLString (uint32_t offset)
{ {
/* uint32_t start_offset = offset + d->STLSTR_buf_off;
MSVC++ string size_t length = readDWord(offset + d->STLSTR_size_off);
ptr allocator size_t capacity = readDWord(offset + d->STLSTR_cap_off);
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);
char * temp = new char[capacity+1]; char * temp = new char[capacity+1];
// read data from inside the string structure // read data from inside the string structure

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

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

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

@ -23,11 +23,11 @@ distribution.
*/ */
#include "Internal.h" #include "Internal.h"
#include "DFMemInfoManager.h"
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/DFProcessEnumerator.h" #include "dfhack/DFProcessEnumerator.h"
#include "dfhack/DFProcess.h" #include "dfhack/DFProcess.h"
#include "dfhack/DFMemInfo.h" #include "dfhack/VersionInfo.h"
using namespace DFHack; using namespace DFHack;
@ -39,7 +39,7 @@ class DFHack::ProcessEnumerator::Private
{ {
public: public:
Private(){}; Private(){};
MemInfoManager *meminfo; VersionInfoFactory *meminfo;
PROC_V Processes; PROC_V Processes;
PID2PROC ProcMap; PID2PROC ProcMap;
Process *GetProcessObject(ProcessID ID); Process *GetProcessObject(ProcessID ID);
@ -120,19 +120,19 @@ Process * BadProcesses::operator[](uint32_t index)
Process *ProcessEnumerator::Private::GetProcessObject(ProcessID ID) 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()) if(p1->isIdentified())
return p1; return p1;
else else
delete p1; delete p1;
Process *p2 = new NormalProcess(ID.pid,meminfo->meminfo); Process *p2 = new NormalProcess(ID.pid,meminfo->versions);
if(p2->isIdentified()) if(p2->isIdentified())
return p2; return p2;
else else
delete p2; delete p2;
#ifdef LINUX_BUILD #ifdef LINUX_BUILD
Process *p3 = new WineProcess(ID.pid,meminfo->meminfo); Process *p3 = new WineProcess(ID.pid,meminfo->versions);
if(p3->isIdentified()) if(p3->isIdentified())
return p3; return p3;
else else
@ -358,7 +358,7 @@ Process * ProcessEnumerator::operator[](uint32_t index)
ProcessEnumerator::ProcessEnumerator( string path_to_xml ) ProcessEnumerator::ProcessEnumerator( string path_to_xml )
: d(new Private()) : d(new Private())
{ {
d->meminfo = new MemInfoManager(path_to_xml); d->meminfo = new VersionInfoFactory(path_to_xml);
} }
void ProcessEnumerator::purge() 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_descriptor_buffer_callback)(t_descriptor_color*, uint32_t) = NULL;
int (*alloc_matgloss_other_buffer_callback)(t_matglossOther*, 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_customWorkshop_buffer_callback)(t_customWorkshop*, uint32_t) = NULL;
int (*alloc_t_material_buffer_callback)(t_material*, 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/DFError.h"
#include "dfhack/DFContextManager.h" #include "dfhack/DFContextManager.h"
#include "dfhack/DFContext.h" #include "dfhack/DFContext.h"
#include "dfhack/DFMemInfo.h" #include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h" #include "dfhack/DFProcess.h"
#include "dfhack/DFTypes.h" #include "dfhack/DFTypes.h"
@ -32,6 +32,7 @@
#include "dfhack/modules/Items.h" #include "dfhack/modules/Items.h"
#include "dfhack/modules/Vegetation.h" #include "dfhack/modules/Vegetation.h"
#include "dfhack/modules/Maps.h" #include "dfhack/modules/Maps.h"
#include "dfhack/modules/Gui.h"
/* /*
* This is a header full of ugly, volatile things. * This is a header full of ugly, volatile things.

@ -29,6 +29,7 @@ distribution.
#include "dfhack/DFTypes.h" #include "dfhack/DFTypes.h"
#include "dfhack/modules/Maps.h" #include "dfhack/modules/Maps.h"
#include "dfhack/modules/Materials.h" #include "dfhack/modules/Materials.h"
#include "dfhack/modules/Position.h"
#include "dfhack/DFTileTypes.h" #include "dfhack/DFTileTypes.h"
#ifdef __cplusplus #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_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_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 struct t_customWorkshop
{ {
uint32_t index; uint32_t index;

@ -54,16 +54,35 @@ Buffer Callback List
- alloc_ubyte_buffer_callback(uint8_t*, uint32_t) - alloc_ubyte_buffer_callback(uint8_t*, uint32_t)
- alloc_ushort_buffer_callback(uint16_t*, uint32_t) - alloc_ushort_buffer_callback(uint16_t*, uint32_t)
- alloc_uint_buffer_callback(uint32_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_matgloss_buffer_callback(t_matgloss*, uint32_t)
- alloc_descriptor_buffer_callback(t_descriptor_color*, uint32_t) - alloc_descriptor_buffer_callback(t_descriptor_color*, uint32_t)
- alloc_matgloss_other_buffer_callback(t_matglossOther*, uint32_t) - alloc_matgloss_other_buffer_callback(t_matglossOther*, uint32_t)
- alloc_vein_buffer_callback(t_vein*, 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_frozenliquidvein_buffer_callback(t_frozenliquidvein*, uint32_t)
- alloc_spattervein_buffer_callback(t_spattervein*, uint32_t) - alloc_spattervein_buffer_callback(t_spattervein*, uint32_t)
Templates Make My Life Harder 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 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_ReadPauseState(DFHackObject* gui);
DFHACK_EXPORT int Gui_ReadViewScreen(DFHackObject* gui, t_viewscreen* viewscreen); DFHACK_EXPORT int Gui_ReadViewScreen(DFHackObject* gui, t_viewscreen* viewscreen);
DFHACK_EXPORT int Gui_ReadMenuState(DFHackObject* gui, uint32_t* menuState);
#ifdef __cplusplus #ifdef __cplusplus
} }

@ -36,6 +36,8 @@ extern "C" {
DFHACK_EXPORT int Maps_Start(DFHackObject* maps); DFHACK_EXPORT int Maps_Start(DFHackObject* maps);
DFHACK_EXPORT int Maps_Finish(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 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); 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 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 const char* Materials_getDescription(DFHackObject* mat, t_material* material);
DFHACK_EXPORT int Materials_getInorganicSize(DFHackObject* mat); 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_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 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 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 #ifdef __cplusplus
} }
#endif #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_ReadCurrentMonth(DFHackObject* world, uint32_t* month);
DFHACK_EXPORT int World_ReadCurrentDay(DFHackObject* world, uint32_t* day); 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 #ifdef __cplusplus
} }
#endif #endif

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

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

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

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

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

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

@ -28,6 +28,7 @@ distribution.
#include "DFPragma.h" #include "DFPragma.h"
#include "DFExport.h" #include "DFExport.h"
#include "dfhack/DFTypes.h" #include "dfhack/DFTypes.h"
#include <sys/types.h>
namespace DFHack namespace DFHack
{ {
@ -35,23 +36,67 @@ namespace DFHack
* Stubs * Stubs
*/ */
class Process; class Process;
class XMLPP;
struct t_class; 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: private:
class Private; VersionInfoPrivate * d;
Private * d;
public: public:
enum OSType enum OSType
{ {
OS_WINDOWS, OS_WINDOWS,
OS_LINUX, OS_LINUX,
OS_APPLE,
OS_BAD OS_BAD
}; };
memory_info(); VersionInfo();
memory_info(const memory_info&); VersionInfo(const VersionInfo&);
~memory_info(); void copy(const DFHack::VersionInfo* old);
~VersionInfo();
void RebaseAddresses(const int32_t new_base); void RebaseAddresses(const int32_t new_base);
void RebaseAll(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 std::string&);
void setBase (const uint32_t); void setBase (const uint32_t);
int32_t getOffset (const std::string&); void setMD5 (const std::string & _md5);
uint32_t getAddress (const std::string&); std::string getMD5();
uint32_t getHexValue (const std::string&);
int32_t getOffset (const char *); void setPE (uint32_t PE_);
uint32_t getAddress (const char *); uint32_t getPE();
uint32_t getHexValue (const char *);
std::string getMood(const uint32_t moodID); std::string getMood(const uint32_t moodID);
std::string getString (const std::string&); std::string getString (const std::string&);
@ -75,6 +119,7 @@ namespace DFHack
std::string getTraitName(const uint32_t) const; std::string getTraitName(const uint32_t) const;
std::string getLabor (const uint32_t); std::string getLabor (const uint32_t);
std::vector< std::vector<std::string> > const& getAllTraits(); 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; DFHack::t_level getLevelInfo(const uint32_t level) const;
@ -87,21 +132,7 @@ namespace DFHack
void setOS(const OSType); void setOS(const OSType);
OSType getOS() const; OSType getOS() const;
void setOffset (const std::string &, const int32_t); void setProfession(const std::string & id, const std::string & name);
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 setJob(const std::string &, const std::string &); void setJob(const std::string &, const std::string &);
void setSkill(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 &, void setTrait(const std::string &, const std::string &, const std::string &,

@ -26,25 +26,33 @@ distribution.
#define MEMINFO_MANAGER_H_INCLUDED #define MEMINFO_MANAGER_H_INCLUDED
#include "dfhack/DFPragma.h" #include "dfhack/DFPragma.h"
#include "dfhack/DFExport.h"
class TiXmlElement; class TiXmlElement;
namespace DFHack namespace DFHack
{ {
class memory_info; class VersionInfo;
class MemInfoManager class DFHACK_EXPORT VersionInfoFactory
{ {
friend class ProcessEnumerator; friend class ProcessEnumerator;
public: public:
MemInfoManager(string path_to_xml); VersionInfoFactory(std::string path_to_xml);
~MemInfoManager(); ~VersionInfoFactory();
// memory info entries loaded from a file // 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;}; bool isInErrorState() const {return error;};
std::vector<memory_info*> meminfo; std::vector<VersionInfo*> versions;
private: private:
void ParseVTable(TiXmlElement* vtable, memory_info* mem); void ParseVTable(TiXmlElement* vtable, VersionInfo* mem);
void ParseEntry (TiXmlElement* entry, memory_info* mem, map <string ,TiXmlElement *>& knownEntries); 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; 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/DFExport.h"
#include "dfhack/DFModule.h" #include "dfhack/DFModule.h"
#include "dfhack/modules/Items.h"
namespace DFHack namespace DFHack
{ {
/* /*
@ -374,6 +375,8 @@ namespace DFHack
const uint16_t x2, const uint16_t y2,const uint16_t z2); const uint16_t x2, const uint16_t y2,const uint16_t z2);
bool ReadCreature(const int32_t index, t_creature & furball); bool ReadCreature(const int32_t index, t_creature & furball);
bool ReadJob(const t_creature * furball, std::vector<t_material> & mat); 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 */ /* Getters */
uint32_t GetDwarfRaceIndex ( void ); uint32_t GetDwarfRaceIndex ( void );

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

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

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

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

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

@ -25,7 +25,7 @@ distribution.
#include "Internal.h" #include "Internal.h"
#include "ContextShared.h" #include "ContextShared.h"
#include "dfhack/DFMemInfo.h" #include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h" #include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h" #include "dfhack/DFVector.h"
#include "dfhack/DFError.h" #include "dfhack/DFError.h"
@ -50,10 +50,16 @@ struct Creatures::Private
{ {
bool Inited; bool Inited;
bool Started; bool Started;
bool Ft_basic;
bool Ft_advanced;
bool Ft_jobs;
bool Ft_soul;
Creatures2010::creature_offsets creatures; Creatures2010::creature_offsets creatures;
uint32_t creature_module; uint32_t creature_module;
uint32_t dwarf_race_index_addr; uint32_t dwarf_race_index_addr;
uint32_t dwarf_civ_id_addr; uint32_t dwarf_civ_id_addr;
OffsetGroup * OG_jobs;
OffsetGroup * OG_job_mats;
DfVector <uint32_t> *p_cre; DfVector <uint32_t> *p_cre;
DFContextShared *d; DFContextShared *d;
Process *owner; Process *owner;
@ -67,67 +73,72 @@ Creatures::Creatures(DFContextShared* _d)
d->Inited = false; d->Inited = false;
d->Started = false; d->Started = false;
d->d->InitReadNames(); // throws on error 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 try
{ {
memory_info * minfo = d->d->offset_descriptor; // Creatures
Creatures2010::creature_offsets &creatures = d->creatures; creatures.vector = OG_Creatures->getAddress ("vector");
creatures.vector = minfo->getAddress ("creature_vector"); d->dwarf_race_index_addr = OG_Creatures->getAddress("current_race");
creatures.pos_offset = minfo->getOffset ("creature_position"); d->dwarf_civ_id_addr = OG_Creatures->getAddress("current_civ");
creatures.profession_offset = minfo->getOffset ("creature_profession"); // Creatures/creature
creatures.custom_profession_offset = minfo->getOffset ("creature_custom_profession"); creatures.name_offset = OG_creature->getOffset ("name");
creatures.race_offset = minfo->getOffset ("creature_race"); creatures.custom_profession_offset = OG_creature->getOffset ("custom_profession");
creatures.civ_offset = minfo->getOffset ("creature_civ"); creatures.profession_offset = OG_creature->getOffset ("profession");
creatures.flags1_offset = minfo->getOffset ("creature_flags1"); creatures.race_offset = OG_creature->getOffset ("race");
creatures.flags2_offset = minfo->getOffset ("creature_flags2"); creatures.pos_offset = OG_creature->getOffset ("position");
creatures.name_offset = minfo->getOffset ("creature_name"); creatures.flags1_offset = OG_creature->getOffset ("flags1");
creatures.sex_offset = minfo->getOffset ("creature_sex"); creatures.flags2_offset = OG_creature->getOffset ("flags2");
creatures.caste_offset = minfo->getOffset ("creature_caste"); creatures.sex_offset = OG_creature->getOffset ("sex");
creatures.id_offset = minfo->getOffset ("creature_id"); creatures.caste_offset = OG_creature->getOffset ("caste");
creatures.labors_offset = minfo->getOffset ("creature_labors"); creatures.id_offset = OG_creature->getOffset ("id");
creatures.happiness_offset = minfo->getOffset ("creature_happiness"); creatures.civ_offset = OG_creature->getOffset ("civ");
creatures.artifact_name_offset = minfo->getOffset("creature_artifact_name"); // name struct
creatures.soul_vector_offset = minfo->getOffset("creature_soul_vector"); creatures.name_firstname_offset = OG_name->getOffset("first");
creatures.default_soul_offset = minfo->getOffset("creature_default_soul"); creatures.name_nickname_offset = OG_name->getOffset("nick");
creatures.physical_offset = minfo->getOffset("creature_physical"); creatures.name_words_offset = OG_name->getOffset("second_words");
creatures.mood_offset = minfo->getOffset("creature_mood"); d->Ft_basic = true;
creatures.mood_skill_offset = minfo->getOffset("creature_mood_skill"); try
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))
{ {
// supply the module with offsets so it can work with them creatures.inventory_offset = OG_creature_ex->getOffset("inventory_vector");
memcpy(SHMDATA(Creatures2010::creature_offsets),&creatures,sizeof(Creatures2010::creature_offsets)); creatures.pickup_equipment_bit = OG_creature_ex->getOffset("pickup_equipment_bit");
const uint32_t cmd = Creatures2010::CREATURE_INIT + (d->creature_module << 16); creatures.mood_offset = OG_creature_ex->getOffset("mood");
p->SetAndWait(cmd); // 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&){};
d->Inited = true; try
} {
catch (Error::MissingMemoryDefinition&) creatures.soul_vector_offset = OG_creature_ex->getOffset("soul_vector");
{ creatures.default_soul_offset = OG_creature_ex->getOffset("current_soul");
d->Inited = false; creatures.soul_mental_offset = OG_soul->getOffset("mental");
throw; 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() Creatures::~Creatures()
@ -158,6 +169,7 @@ bool Creatures::Finish()
bool Creatures::ReadCreature (const int32_t index, t_creature & furball) bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
{ {
if(!d->Started) return false; if(!d->Started) return false;
memset(&furball, 0, sizeof(t_creature));
// SHM fast path // SHM fast path
Process * p = d->owner; Process * p = d->owner;
/* /*
@ -171,7 +183,7 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
} }
*/ */
// non-SHM slow path // non-SHM slow path
memory_info * minfo = d->d->offset_descriptor; VersionInfo * minfo = d->d->offset_descriptor;
// read pointer from vector at position // read pointer from vector at position
uint32_t temp = d->p_cre->at (index); uint32_t temp = d->p_cre->at (index);
@ -179,129 +191,120 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
Creatures2010::creature_offsets &offs = d->creatures; Creatures2010::creature_offsets &offs = d->creatures;
//read creature from memory //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);
furball.civ = p->readDWord (temp + offs.civ_offset);
p->readByte (temp + offs.sex_offset, furball.sex);
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);
// physical attributes
p->read(temp + offs.physical_offset,
sizeof(t_attrib) * NUM_CREATURE_PHYSICAL_ATTRIBUTES,
(uint8_t *)&furball.strength);
// mood stuff
furball.mood = (int16_t) p->readWord (temp + offs.mood_offset);
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; // name
furball.current_job.jobType = p->readByte (furball.current_job.occupationPtr + minfo->getOffset("job_type") ); d->d->readName(furball.name,temp + offs.name_offset);
furball.current_job.jobId = p->readDWord (furball.current_job.occupationPtr + minfo->getOffset("job_id") );
// basic stuff
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);
furball.civ = p->readDWord (temp + offs.civ_offset);
p->readByte (temp + offs.sex_offset, furball.sex);
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);
} }
else if(d->Ft_advanced)
{ {
furball.current_job.active = false;; // happiness
} p->readDWord (temp + offs.happiness_offset, furball.happiness);
furball.birth_year = p->readDWord (temp + offs.birth_year_offset ); // physical attributes
furball.birth_time = p->readDWord (temp + offs.birth_time_offset ); p->read(temp + offs.physical_offset,
sizeof(t_attrib) * NUM_CREATURE_PHYSICAL_ATTRIBUTES,
(uint8_t *)&furball.strength);
// mood stuff
furball.mood = (int16_t) p->readWord (temp + offs.mood_offset);
furball.mood_skill = p->readWord (temp + offs.mood_skill_offset);
d->d->readName(furball.artifact_name, temp + offs.artifact_name_offset);
// labors
p->read (temp + offs.labors_offset, NUM_CREATURE_LABORS, furball.labors);
furball.birth_year = p->readDWord (temp + offs.birth_year_offset );
furball.birth_time = p->readDWord (temp + offs.birth_time_offset );
/*
* p->readDWord(temp + offs.creature_pregnancy_offset, furball.pregnancy_timer);
*/
// current job HACK: the job object isn't cleanly represented here // appearance
/* DfVector <uint32_t> app(p, temp + offs.appearance_vector_offset);
uint32_t jobIdAddr = p->readDWord (temp + offs.creature_current_job_offset); furball.nbcolors = app.size();
if(furball.nbcolors>MAX_COLORS)
furball.nbcolors = MAX_COLORS;
for(uint32_t i = 0; i < furball.nbcolors; i++)
{
furball.color[i] = app[i];
}
if (jobIdAddr) //likes
{ /*
furball.current_job.active = true; DfVector <uint32_t> likes(d->p, temp + offs.creature_likes_offset);
furball.current_job.jobId = p->readByte (jobIdAddr + offs.creature_current_job_id_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]);
}*/
} }
else if(d->Ft_soul)
{ {
furball.current_job.active = false; /*
} // enum soul pointer vector
*/ DfVector <uint32_t> souls(p,temp + offs.creature_soul_vector_offset);
*/
uint32_t soul = p->readDWord(temp + offs.default_soul_offset);
furball.has_default_soul = false;
/* if(soul)
p->readDWord(temp + offs.creature_pregnancy_offset, furball.pregnancy_timer); {
*/ furball.has_default_soul = true;
// get first soul's skills
DfVector <uint32_t> skills(p, soul + offs.soul_skills_vector_offset);
furball.defaultSoul.numSkills = skills.size();
/* for (uint32_t i = 0; i < furball.defaultSoul.numSkills;i++)
// enum soul pointer vector {
DfVector <uint32_t> souls(p,temp + offs.creature_soul_vector_offset); uint32_t temp2 = skills[i];
*/ // a byte: this gives us 256 skills maximum.
uint32_t soul = p->readDWord(temp + offs.default_soul_offset); furball.defaultSoul.skills[i].id = p->readByte (temp2);
furball.has_default_soul = false; furball.defaultSoul.skills[i].rating =
p->readByte (temp2 + offsetof(t_skill, rating));
furball.defaultSoul.skills[i].experience =
p->readWord (temp2 + offsetof(t_skill, experience));
}
if(soul) // mental attributes are part of the soul
{ p->read(soul + offs.soul_mental_offset,
furball.has_default_soul = true; sizeof(t_attrib) * NUM_CREATURE_MENTAL_ATTRIBUTES,
// get first soul's skills (uint8_t *)&furball.defaultSoul.analytical_ability);
DfVector <uint32_t> skills(p, soul + offs.soul_skills_vector_offset);
furball.defaultSoul.numSkills = skills.size();
for (uint32_t i = 0; i < furball.defaultSoul.numSkills;i++) // traits as well
{ p->read(soul + offs.soul_traits_offset,
uint32_t temp2 = skills[i]; sizeof (uint16_t) * NUM_CREATURE_TRAITS,
// a byte: this gives us 256 skills maximum. (uint8_t *) &furball.defaultSoul.traits);
furball.defaultSoul.skills[i].id = p->readByte (temp2);
furball.defaultSoul.skills[i].rating =
p->readByte (temp2 + offsetof(t_skill, rating));
furball.defaultSoul.skills[i].experience =
p->readWord (temp2 + offsetof(t_skill, experience));
} }
// mental attributes are part of the soul
p->read(soul + offs.soul_mental_offset,
sizeof(t_attrib) * NUM_CREATURE_MENTAL_ATTRIBUTES,
(uint8_t *)&furball.defaultSoul.analytical_ability);
// traits as well
p->read(soul + offs.soul_traits_offset,
sizeof (uint16_t) * NUM_CREATURE_TRAITS,
(uint8_t *) &furball.defaultSoul.traits);
} }
if(d->Ft_jobs)
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.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") );
}
else
{
furball.current_job.active = false;;
}
} }
//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++)
{
uint32_t temp2 = *(uint32_t *) likes[i];
p->read(temp2,sizeof(t_like),(uint8_t *) &furball.likes[i]);
}*/
return true; return true;
} }
@ -521,21 +524,19 @@ bool Creatures::WriteMoodSkill(const uint32_t index, const uint16_t moodSkill)
bool Creatures::WriteJob(const t_creature * furball, std::vector<t_material> const& mat) bool Creatures::WriteJob(const t_creature * furball, std::vector<t_material> const& mat)
{ {
unsigned int i; unsigned int i;
if(!d->Inited) return false; if(!d->Inited) return false;
if(!furball->current_job.active) return false; if(!furball->current_job.active) return false;
Process * p = d->owner; Process * p = d->owner;
memory_info * minfo = d->d->offset_descriptor; DfVector <uint32_t> cmats(p, furball->current_job.occupationPtr + d->OG_jobs->getOffset("materials_vector"));
DfVector <uint32_t> cmats(p, furball->current_job.occupationPtr + minfo->getOffset("job_materials_vector"));
for(i=0;i<cmats.size();i++) for(i=0;i<cmats.size();i++)
{ {
p->writeWord(cmats[i] + minfo->getOffset("job_material_maintype"), mat[i].itemType); p->writeWord(cmats[i] + d->OG_job_mats->getOffset("maintype"), mat[i].itemType);
p->writeWord(cmats[i] + minfo->getOffset("job_material_sectype1"), mat[i].subType); p->writeWord(cmats[i] + d->OG_job_mats->getOffset("sectype1"), mat[i].subType);
p->writeWord(cmats[i] + minfo->getOffset("job_material_sectype2"), mat[i].subIndex); p->writeWord(cmats[i] + d->OG_job_mats->getOffset("sectype2"), mat[i].subIndex);
p->writeDWord(cmats[i] + minfo->getOffset("job_material_sectype3"), mat[i].index); p->writeDWord(cmats[i] + d->OG_job_mats->getOffset("sectype3"), mat[i].index);
p->writeDWord(cmats[i] + minfo->getOffset("job_material_flags"), mat[i].flags); p->writeDWord(cmats[i] + d->OG_job_mats->getOffset("flags"), mat[i].flags);
} }
return true; return true;
} }
@ -595,17 +596,40 @@ bool Creatures::ReadJob(const t_creature * furball, vector<t_material> & mat)
if(!d->Inited) return false; if(!d->Inited) return false;
if(!furball->current_job.active) return false; if(!furball->current_job.active) return false;
Process * p = d->owner; 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()); mat.resize(cmats.size());
for(i=0;i<cmats.size();i++) for(i=0;i<cmats.size();i++)
{ {
mat[i].itemType = p->readWord(cmats[i] + minfo->getOffset("job_material_maintype")); mat[i].itemType = p->readWord(cmats[i] + d->OG_job_mats->getOffset("maintype"));
mat[i].subType = p->readWord(cmats[i] + minfo->getOffset("job_material_sectype1")); mat[i].subType = p->readWord(cmats[i] + d->OG_job_mats->getOffset("sectype1"));
mat[i].subIndex = p->readWord(cmats[i] + minfo->getOffset("job_material_sectype2")); mat[i].subIndex = p->readWord(cmats[i] + d->OG_job_mats->getOffset("sectype2"));
mat[i].index = p->readDWord(cmats[i] + minfo->getOffset("job_material_sectype3")); mat[i].index = p->readDWord(cmats[i] + d->OG_job_mats->getOffset("sectype3"));
mat[i].flags = p->readDWord(cmats[i] + minfo->getOffset("job_material_flags")); mat[i].flags = p->readDWord(cmats[i] + d->OG_job_mats->getOffset("flags"));
} }
return true; 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 "ContextShared.h"
#include "dfhack/modules/Gui.h" #include "dfhack/modules/Gui.h"
#include "dfhack/DFProcess.h" #include "dfhack/DFProcess.h"
#include "dfhack/DFMemInfo.h" #include "dfhack/VersionInfo.h"
#include "dfhack/DFTypes.h" #include "dfhack/DFTypes.h"
using namespace DFHack; using namespace DFHack;
struct Gui::Private struct Gui::Private
{ {
bool Inited; Private()
{
Started = PauseInited = ViewScreeInited = MenuStateInited = false;
}
bool Started; bool Started;
uint32_t pause_state_offset; uint32_t pause_state_offset;
bool PauseInited;
uint32_t view_screen_offset; uint32_t view_screen_offset;
uint32_t current_cursor_creature_offset; bool ViewScreeInited;
uint32_t current_menu_state_offset; uint32_t current_menu_state_offset;
bool MenuStateInited;
DFContextShared *d; DFContextShared *d;
Process * owner; Process * owner;
}; };
@ -49,13 +54,26 @@ Gui::Gui(DFContextShared * _d)
d = new Private; d = new Private;
d->d = _d; d->d = _d;
d->owner = _d->p; d->owner = _d->p;
d->Inited = d->Started = true; OffsetGroup * OG_Gui = d->d->offset_descriptor->getGroup("GUI");
try
memory_info * mem = d->d->offset_descriptor; {
d->current_menu_state_offset = mem->getAddress("current_menu_state"); d->current_menu_state_offset = OG_Gui->getAddress("current_menu_state");
d->pause_state_offset = mem->getAddress ("pause_state"); d->MenuStateInited = true;
d->view_screen_offset = mem->getAddress ("view_screen"); }
d->Inited = d->Started = 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() Gui::~Gui()
@ -75,23 +93,29 @@ bool Gui::Finish()
bool Gui::ReadPauseState() bool Gui::ReadPauseState()
{ {
// replace with an exception if(!d->PauseInited) return false;
if(!d->Inited) return false;
uint32_t pauseState = d->owner->readDWord (d->pause_state_offset); uint32_t pauseState = d->owner->readDWord (d->pause_state_offset);
return pauseState & 1; 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() uint32_t Gui::ReadMenuState()
{ {
if(d->Inited) if(d->MenuStateInited)
return(d->owner->readDWord(d->current_menu_state_offset)); return(d->owner->readDWord(d->current_menu_state_offset));
return false; return false;
} }
bool Gui::ReadViewScreen (t_viewscreen &screen) bool Gui::ReadViewScreen (t_viewscreen &screen)
{ {
if (!d->Inited) return false; if (!d->ViewScreeInited) return false;
Process * p = d->owner; Process * p = d->owner;
uint32_t last = p->readDWord (d->view_screen_offset); 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 Gui_ReadViewScreen(DFHackObject* gui, t_viewscreen* viewscreen)
{ {
//int result;
if(gui != NULL) if(gui != NULL)
{ {
return ((DFHack::Gui*)gui)->ReadViewScreen(*viewscreen); return ((DFHack::Gui*)gui)->ReadViewScreen(*viewscreen);
@ -70,6 +68,18 @@ int Gui_ReadViewScreen(DFHackObject* gui, t_viewscreen* viewscreen)
return -1; return -1;
} }
int Gui_ReadMenuState(DFHackObject* gui, uint32_t* menuState)
{
if(gui != NULL)
{
*menuState = ((DFHack::Gui*)gui)->ReadMenuState();
return 1;
}
return -1;
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

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

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

@ -54,6 +54,37 @@ int Maps_Finish(DFHackObject* maps)
return -1; 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) void Maps_getSize(DFHackObject* maps, uint32_t* x, uint32_t* y, uint32_t* z)
{ {
if(maps != NULL) if(maps != NULL)

@ -26,9 +26,10 @@ distribution.
#include "ContextShared.h" #include "ContextShared.h"
#include "dfhack/DFTypes.h" #include "dfhack/DFTypes.h"
#include "dfhack/modules/Materials.h" #include "dfhack/modules/Materials.h"
#include "dfhack/DFMemInfo.h" #include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h" #include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h" #include "dfhack/DFVector.h"
#include <dfhack/DFError.h>
using namespace DFHack; using namespace DFHack;
@ -37,6 +38,13 @@ class Materials::Private
public: public:
DFContextShared *d; DFContextShared *d;
Process * owner; 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 Inited;
bool Started; bool Started;
@ -48,6 +56,14 @@ Materials::Materials(DFContextShared * d_)
d = new Private; d = new Private;
d->d = d_; d->d = d_;
d->owner = d_->p; 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() Materials::~Materials()
{ {
@ -56,6 +72,7 @@ Materials::~Materials()
bool Materials::Finish() bool Materials::Finish()
{ {
/*
inorganic.clear(); inorganic.clear();
organic.clear(); organic.clear();
tree.clear(); tree.clear();
@ -65,6 +82,7 @@ bool Materials::Finish()
color.clear(); color.clear();
other.clear(); other.clear();
alldesc.clear(); alldesc.clear();
*/
return true; return true;
} }
@ -216,7 +234,7 @@ inline bool ReadNamesOnly(Process* p, uint32_t address, vector<t_matgloss> & nam
bool Materials::ReadInorganicMaterials (void) bool Materials::ReadInorganicMaterials (void)
{ {
Process * p = d->owner; 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(); uint32_t size = p_matgloss.size();
inorganic.clear(); inorganic.clear();
inorganic.reserve (size); inorganic.reserve (size);
@ -237,29 +255,29 @@ bool Materials::ReadInorganicMaterials (void)
bool Materials::ReadOrganicMaterials (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) 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) 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) 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; return true;
} }
bool Materials::ReadOthers(void) bool Materials::ReadOthers(void)
{ {
Process * p = d->owner; 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 i = 0;
uint32_t ptr; uint32_t ptr;
@ -281,7 +299,8 @@ bool Materials::ReadOthers(void)
bool Materials::ReadDescriptorColors (void) bool Materials::ReadDescriptorColors (void)
{ {
Process * p = d->owner; 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(); uint32_t size = p_colors.size();
color.clear(); color.clear();
@ -291,43 +310,70 @@ bool Materials::ReadDescriptorColors (void)
for (uint32_t i = 0; i < size;i++) for (uint32_t i = 0; i < size;i++)
{ {
t_descriptor_color col; t_descriptor_color col;
p->readSTLString (p_colors[i] + p->getDescriptor()->getOffset ("descriptor_rawname"), col.id, 128); p->readSTLString (p_colors[i] + OG_Descriptors->getOffset ("rawname"), col.id, 128);
p->readSTLString (p_colors[i] + p->getDescriptor()->getOffset ("descriptor_name"), col.name, 128); p->readSTLString (p_colors[i] + OG_Descriptors->getOffset ("name"), col.name, 128);
col.r = p->readFloat( p_colors[i] + p->getDescriptor()->getOffset ("descriptor_color_r") ); col.r = p->readFloat( p_colors[i] + OG_Descriptors->getOffset ("color_r") );
col.v = p->readFloat( p_colors[i] + p->getDescriptor()->getOffset ("descriptor_color_v") ); col.v = p->readFloat( p_colors[i] + OG_Descriptors->getOffset ("color_v") );
col.b = p->readFloat( p_colors[i] + p->getDescriptor()->getOffset ("descriptor_color_b") ); col.b = p->readFloat( p_colors[i] + OG_Descriptors->getOffset ("color_b") );
color.push_back(col); 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; return true;
} }
bool Materials::ReadCreatureTypesEx (void) bool Materials::ReadCreatureTypesEx (void)
{ {
Process *p = d->owner; Process *p = d->owner;
memory_info *mem = d->owner->getDescriptor(); VersionInfo *mem = p->getDescriptor();
DfVector <uint32_t> p_races (p, mem->getAddress ("creature_type_vector")); OffsetGroup * OG_string = mem->getGroup("string");
uint32_t castes_vector_offset = mem->getOffset ("creature_type_caste_vector"); uint32_t sizeof_string = OG_string->getHexValue ("sizeof");
uint32_t extract_vector_offset = mem->getOffset ("creature_type_extract_vector");
uint32_t sizeof_string = mem->getHexValue ("sizeof_string"); OffsetGroup * OG_Mats = mem->getGroup("Materials");
uint32_t caste_colormod_offset = mem->getOffset ("caste_color_modifiers"); DfVector <uint32_t> p_races (p, OG_Mats->getAddress ("creature_type_vector"));
uint32_t caste_bodypart_offset = mem->getOffset ("caste_bodypart_vector");
uint32_t caste_attributes_offset = mem->getOffset ("caste_attributes"); OffsetGroup * OG_Creature = OG_Mats->getGroup("creature");
uint32_t bodypart_id_offset = mem->getOffset ("bodypart_id"); uint32_t castes_vector_offset = OG_Creature->getOffset ("caste_vector");
uint32_t bodypart_category_offset = mem->getOffset ("bodypart_category"); uint32_t extract_vector_offset = OG_Creature->getOffset ("extract_vector");
uint32_t bodypart_layers_offset = mem->getOffset ("bodypart_layers_vector"); uint32_t tile_offset = OG_Creature->getOffset ("tile");
uint32_t bodypart_singular_offset = mem->getOffset ("bodypart_singular_vector"); // unused uint32_t tile_color_offset = OG_Creature->getOffset ("tile_color");
uint32_t bodypart_plural_offset = mem->getOffset ("bodypart_plural_vector"); // unused
uint32_t color_modifier_part_offset = mem->getOffset ("color_modifier_part"); bool have_advanced = false;
uint32_t color_modifier_startdate_offset = mem->getOffset ("color_modifier_startdate"); uint32_t caste_colormod_offset;
uint32_t color_modifier_enddate_offset = mem->getOffset ("color_modifier_enddate"); 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 size = p_races.size();
uint32_t sizecas = 0; uint32_t sizecas = 0;
uint32_t sizecolormod; uint32_t sizecolormod;
uint32_t sizecolorlist; uint32_t sizecolorlist;
uint32_t sizebp; uint32_t sizebp;
uint32_t tile_offset = mem->getOffset ("creature_tile");
uint32_t tile_color_offset = mem->getOffset ("creature_tile_color");
raceEx.clear(); raceEx.clear();
raceEx.reserve (size); raceEx.reserve (size);
for (uint32_t i = 0; i < size;i++) for (uint32_t i = 0; i < size;i++)
@ -356,38 +402,36 @@ bool Materials::ReadCreatureTypesEx (void)
p->readSTLString (caste_start + sizeof_string, caste.singular, sizeof(caste.singular)); 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 + 2 * sizeof_string, caste.plural, sizeof(caste.plural));
p->readSTLString (caste_start + 3 * sizeof_string, caste.adjective, sizeof(caste.adjective)); 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();
caste.ColorModifier.resize(sizecolormod);
for(uint32_t k = 0; k < sizecolormod;k++)
{
DfVector <uint32_t> p_colorlist(p, p_colormod[k]);
sizecolorlist = p_colorlist.size();
caste.ColorModifier[k].colorlist.resize(sizecolorlist);
for(uint32_t l = 0; l < sizecolorlist; l++)
caste.ColorModifier[k].colorlist[l] = p_colorlist[l];
p->readSTLString( p_colormod[k] + color_modifier_part_offset, caste.ColorModifier[k].part, sizeof(caste.ColorModifier[k].part));
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();
sizebp = p_bodypart.size();
for(uint32_t k = 0; k < sizebp; k++)
{ {
t_bodypart part; /* color mod reading */
p->readSTLString (p_bodypart[k] + bodypart_id_offset, part.id, sizeof(part.id)); DfVector <uint32_t> p_colormod(p, caste_start + caste_colormod_offset);
p->readSTLString (p_bodypart[k] + bodypart_category_offset, part.category, sizeof(part.category)); sizecolormod = p_colormod.size();
caste.bodypart.push_back(part); caste.ColorModifier.resize(sizecolormod);
for(uint32_t k = 0; k < sizecolormod;k++)
{
DfVector <uint32_t> p_colorlist(p, p_colormod[k]);
sizecolorlist = p_colorlist.size();
caste.ColorModifier[k].colorlist.resize(sizecolorlist);
for(uint32_t l = 0; l < sizecolorlist; l++)
caste.ColorModifier[k].colorlist[l] = p_colorlist[l];
p->readSTLString( p_colormod[k] + color_modifier_part_offset, caste.ColorModifier[k].part, sizeof(caste.ColorModifier[k].part));
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();
sizebp = p_bodypart.size();
for(uint32_t k = 0; k < sizebp; k++)
{
t_bodypart part;
p->readSTLString (p_bodypart[k] + bodypart_id_offset, part.id, sizeof(part.id));
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);
} }
p->read(caste_start + caste_attributes_offset, sizeof(t_attrib) * (6+11), (uint8_t *)&caste.strength);
mat.castes.push_back(caste); mat.castes.push_back(caste);
} }
DfVector <uint32_t> p_extract(p, p_races[i] + extract_vector_offset); DfVector <uint32_t> p_extract(p, p_races[i] + extract_vector_offset);
@ -411,7 +455,7 @@ void Materials::ReadAllMaterials(void)
this->ReadCreatureTypes(); this->ReadCreatureTypes();
this->ReadCreatureTypesEx(); this->ReadCreatureTypesEx();
this->ReadDescriptorColors(); this->ReadDescriptorColors();
this->ReadOthers(); //this->ReadOthers();
} }
std::string Materials::getDescription(t_material & mat) 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) const char* Materials_getDescription(DFHackObject* mat, t_material* material)
{ {
if(mat != NULL) if(mat != NULL)

@ -25,8 +25,9 @@ distribution.
#include "Internal.h" #include "Internal.h"
#include "ContextShared.h" #include "ContextShared.h"
#include "dfhack/modules/Position.h" #include "dfhack/modules/Position.h"
#include "dfhack/DFMemInfo.h" #include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h" #include "dfhack/DFProcess.h"
#include "dfhack/DFError.h"
using namespace DFHack; using namespace DFHack;
struct Position::Private struct Position::Private
@ -59,33 +60,36 @@ Position::Position(DFContextShared * d_)
d->owner = d_->p; d->owner = d_->p;
d->Inited = true; d->Inited = true;
d->StartedHotkeys = d->Started = d->StartedScreen = false; 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 try
{ {
mem = d->d->offset_descriptor; OG_Position = mem->getGroup("Position");
d->window_x_offset = mem->getAddress ("window_x"); d->window_x_offset = OG_Position->getAddress ("window_x");
d->window_y_offset = mem->getAddress ("window_y"); d->window_y_offset = OG_Position->getAddress ("window_y");
d->window_z_offset = mem->getAddress ("window_z"); d->window_z_offset = OG_Position->getAddress ("window_z");
d->cursor_xyz_offset = mem->getAddress ("cursor_xyz"); d->cursor_xyz_offset = OG_Position->getAddress ("cursor_xyz");
d->window_dims_offset = mem->getAddress ("window_dims"); d->window_dims_offset = OG_Position->getAddress ("window_dims");
d->Started = true; d->Started = true;
} }
catch(exception &){}; catch(Error::All &){};
try try
{ {
d->hotkey_start = mem->getAddress("hotkey_start"); OffsetGroup * OG_Hotkeys = mem->getGroup("Hotkeys");
d->hotkey_mode_offset = mem->getOffset ("hotkey_mode"); d->hotkey_start = OG_Hotkeys->getAddress("start");
d->hotkey_xyz_offset = mem->getOffset("hotkey_xyz"); d->hotkey_mode_offset = OG_Hotkeys->getOffset ("mode");
d->hotkey_size = mem->getHexValue("hotkey_size"); d->hotkey_xyz_offset = OG_Hotkeys->getOffset("coords");
d->hotkey_size = OG_Hotkeys->getHexValue("size");
d->StartedHotkeys = true; d->StartedHotkeys = true;
} }
catch(exception &){}; catch(Error::All &){};
try 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; d->StartedScreen = true;
} }
catch(exception &){}; catch(Error::All &){};
} }
Position::~Position() 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->Inited) return false;
if(!d->StartedScreen) return false; if(!d->StartedScreen) return false;
uint32_t screen_addr; uint32_t screen_addr = d->owner->readDWord(d->screen_tiles_ptr_offset);
d->owner->read (d->screen_tiles_ptr_offset, sizeof(uint32_t), (uint8_t *) screen_addr);
uint8_t* tiles = new uint8_t[width*height*4/* + 80 + width*height*4*/]; 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); 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++) for(int32_t ix=0; ix<width; ix++)
{ {
screen[ix + iy*width].symbol = tiles[iy + ix*height*4 +0]; 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].foreground = tiles[(iy + ix*height)*4 +1];
screen[ix + iy*width].background = tiles[iy + ix*height*4 +2]; 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].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].gtile = tiles[width*height*4 + 80 + iy + ix*height +0];
//screen[ix + iy*width].grayscale = tiles[width*height*4 + 80 + iy + ix*height +1]; //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. distribution.
*/ */
#include "dfhack-c/DFTypes_C.h"
#include "dfhack-c/modules/Position_C.h" #include "dfhack-c/modules/Position_C.h"
#ifdef __cplusplus #ifdef __cplusplus
@ -97,6 +98,28 @@ int Position_setCursorCoords(DFHackObject* pos, int32_t x, int32_t y, int32_t z)
return -1; 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) int Position_getWindowSize(DFHackObject* pos, int32_t* width, int32_t* height)
{ {
if(pos != NULL) if(pos != NULL)
@ -117,6 +140,26 @@ int Position_getWindowSize(DFHackObject* pos, int32_t* width, int32_t* height)
return -1; 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 #ifdef __cplusplus
} }
#endif #endif

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

@ -25,7 +25,7 @@ distribution.
#include "Internal.h" #include "Internal.h"
#include "ContextShared.h" #include "ContextShared.h"
#include "dfhack/DFMemInfo.h" #include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h" #include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h" #include "dfhack/DFVector.h"
#include "dfhack/DFTypes.h" #include "dfhack/DFTypes.h"
@ -53,9 +53,9 @@ Vegetation::Vegetation(DFContextShared * d_)
d->owner = d_->p; d->owner = d_->p;
d->d = d_; d->d = d_;
d->Inited = d->Started = false; d->Inited = d->Started = false;
memory_info * mem = d->d->offset_descriptor; OffsetGroup * OG_Veg = d->d->offset_descriptor->getGroup("Vegetation");
d->vegetation_vector = mem->getAddress ("vegetation_vector"); d->vegetation_vector = OG_Veg->getAddress ("vector");
d->tree_desc_offset = mem->getOffset ("tree_desc_offset"); d->tree_desc_offset = OG_Veg->getOffset ("tree_desc_offset");
d->Inited = true; d->Inited = true;
} }
@ -68,6 +68,8 @@ Vegetation::~Vegetation()
bool Vegetation::Start(uint32_t & numplants) bool Vegetation::Start(uint32_t & numplants)
{ {
if(!d->Inited)
return false;
d->p_veg = new DfVector <uint32_t> (d->owner, d->vegetation_vector); d->p_veg = new DfVector <uint32_t> (d->owner, d->vegetation_vector);
numplants = d->p_veg->size(); numplants = d->p_veg->size();
d->Started = true; 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 "ContextShared.h"
#include "dfhack/modules/World.h" #include "dfhack/modules/World.h"
#include "dfhack/DFProcess.h" #include "dfhack/DFProcess.h"
#include "dfhack/DFMemInfo.h" #include "dfhack/VersionInfo.h"
#include "dfhack/DFTypes.h" #include "dfhack/DFTypes.h"
#include "dfhack/DFError.h"
using namespace DFHack; using namespace DFHack;
struct World::Private struct World::Private
{ {
bool Inited; bool Inited;
bool Started; bool StartedTime;
bool StartedWeather;
uint32_t year_offset; uint32_t year_offset;
uint32_t tick_offset; uint32_t tick_offset;
uint32_t weather_offset;
DFContextShared *d; DFContextShared *d;
Process * owner; Process * owner;
}; };
@ -59,11 +62,23 @@ World::World(DFContextShared * _d)
d = new Private; d = new Private;
d->d = _d; d->d = _d;
d->owner = _d->p; d->owner = _d->p;
d->Inited = d->StartedTime = d->StartedWeather = false;
memory_info * mem = d->d->offset_descriptor;
d->year_offset = mem->getAddress( "current_year" ); OffsetGroup * OG_World = d->d->offset_descriptor->getGroup("World");
d->tick_offset = mem->getAddress( "current_tick" ); try
d->Inited = d->Started = true; {
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() World::~World()
@ -83,14 +98,14 @@ bool World::Finish()
uint32_t World::ReadCurrentYear() uint32_t World::ReadCurrentYear()
{ {
if(d->Inited) if(d->Inited && d->StartedTime)
return(d->owner->readDWord(d->year_offset)); return(d->owner->readDWord(d->year_offset));
return 0; return 0;
} }
uint32_t World::ReadCurrentTick() uint32_t World::ReadCurrentTick()
{ {
if(d->Inited) if(d->Inited && d->StartedTime)
return(d->owner->readDWord(d->tick_offset)); return(d->owner->readDWord(d->tick_offset));
return 0; return 0;
} }
@ -114,3 +129,26 @@ uint32_t World::ReadCurrentDay()
{ {
return ((this->ReadCurrentTick() / 1200) % 28) + 1; 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; 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 #ifdef __cplusplus
} }
#endif #endif

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

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

@ -1,8 +1,5 @@
# don't use this file directly. use the one in the root folder of the project # 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. # this is required to ensure we use the right configuration for the system.
IF(UNIX) IF(UNIX)
add_definitions(-DLINUX_BUILD) add_definitions(-DLINUX_BUILD)
@ -62,4 +59,3 @@ dfspatterdump
dfprocessenum dfprocessenum
RUNTIME DESTINATION bin RUNTIME DESTINATION bin
) )
ENDIF (BUILD_DFHACK_EXAMPLES)

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

@ -19,7 +19,7 @@ enum likeType
}; };
DFHack::Materials * Materials; DFHack::Materials * Materials;
DFHack::memory_info *mem; DFHack::VersionInfo *mem;
vector< vector<string> > englishWords; vector< vector<string> > englishWords;
vector< vector<string> > foreignWords; vector< vector<string> > foreignWords;
DFHack::Creatures * Creatures = NULL; 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) void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature)
{ {
uint32_t dayoflife; 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].tile_character
<< "," << Materials->raceEx[creature.race].tilecolor.fore << "," << Materials->raceEx[creature.race].tilecolor.fore
<< "," << Materials->raceEx[creature.race].tilecolor.back << "," << 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::Translation *Tran = DF->getTranslation();
DFHack::memory_info *mem = DF->getMemoryInfo(); DFHack::VersionInfo *mem = DF->getMemoryInfo();
string transName = Tran->TranslateName(creature.name,false); string transName = Tran->TranslateName(creature.name,false);
if(!transName.empty()) if(!transName.empty())
@ -172,7 +172,7 @@ void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature)
if(creature.civ) if(creature.civ)
{ {
cout << "civilization: " << creature.civ; cout << ", civilization: " << creature.civ;
addendl = true; addendl = true;
} }
@ -191,7 +191,7 @@ void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature)
cout << endl; cout << endl;
addendl = false; 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]) 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) if(creature.pregnancy_timer > 0)
cout << "gives birth in " << creature.pregnancy_timer/1200 << " days. "; cout << "gives birth in " << creature.pregnancy_timer/1200 << " days. ";
@ -439,7 +453,13 @@ int main (int numargs, char ** args)
} }
mem = DF->getMemoryInfo(); mem = DF->getMemoryInfo();
Materials->ReadAllMaterials(); Materials->ReadInorganicMaterials();
Materials->ReadOrganicMaterials();
Materials->ReadWoodMaterials();
Materials->ReadPlantMaterials();
Materials->ReadCreatureTypes();
Materials->ReadCreatureTypesEx();
Materials->ReadDescriptorColors();
if(!Tran->Start()) if(!Tran->Start())
{ {
@ -450,6 +470,7 @@ int main (int numargs, char ** args)
//DF.InitViewAndCursor(); //DF.InitViewAndCursor();
for(uint32_t i = 0; i < numCreatures; i++) for(uint32_t i = 0; i < numCreatures; i++)
{ {
printf("%d/%d\n", i, numCreatures);
DFHack::t_creature temp; DFHack::t_creature temp;
Creatures->ReadCreature(i,temp); Creatures->ReadCreature(i,temp);
if(check.empty() || string(Materials->raceEx[temp.race].rawname) == check) if(check.empty() || string(Materials->raceEx[temp.race].rawname) == check)
@ -459,6 +480,7 @@ int main (int numargs, char ** args)
printCreature(DF,temp); printCreature(DF,temp);
addrs.push_back(temp.origin); addrs.push_back(temp.origin);
} }
printf("!\n");
} }
if(addrs.size() <= 10) if(addrs.size() <= 10)
{ {
@ -473,6 +495,7 @@ int main (int numargs, char ** args)
DF.ReadCreature(currentIdx, currentCreature); DF.ReadCreature(currentIdx, currentCreature);
printCreature(DF,currentCreature); printCreature(DF,currentCreature);
*/ */
Creatures->Finish(); Creatures->Finish();
DF->Detach(); DF->Detach();
#ifndef LINUX_BUILD #ifndef LINUX_BUILD

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

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

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

@ -56,7 +56,7 @@ int main (void)
{ {
cout << "Testing ProcessEnumerator" << endl; cout << "Testing ProcessEnumerator" << endl;
ProcessEnumerator Penum("Memory.xml"); ProcessEnumerator Penum("Memory.xml");
memory_info * mem; VersionInfo * mem;
do do
{ {
// make the ProcessEnumerator update its list of Processes // make the ProcessEnumerator update its list of Processes
@ -90,7 +90,7 @@ int main (void)
{ {
cout << "Testing ContextManager" << endl; cout << "Testing ContextManager" << endl;
ContextManager Cman("Memory.xml"); ContextManager Cman("Memory.xml");
memory_info * mem; VersionInfo * mem;
do do
{ {
// make the ContextManager update its list of Contexts // 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::Process* p = DF->getProcess();
DFHack::memory_info* mem = DF->getMemoryInfo(); DFHack::VersionInfo* mem = DF->getMemoryInfo();
DFHack::Position * pos = DF->getPosition(); DFHack::Position * pos = DF->getPosition();
DFHack::Vegetation * v = DF->getVegetation(); DFHack::Vegetation * v = DF->getVegetation();
DFHack::Materials * mat = DF->getMaterials(); 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 # 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. # this is required to ensure we use the right configuration for the system.
IF(UNIX) IF(UNIX)
add_definitions(-DLINUX_BUILD) add_definitions(-DLINUX_BUILD)
@ -56,8 +53,15 @@ TARGET_LINK_LIBRARIES(dfcatsplosion dfhack)
#ADD_EXECUTABLE(dfrenamer renamer.cpp) #ADD_EXECUTABLE(dfrenamer renamer.cpp)
#TARGET_LINK_LIBRARIES(dfrenamer dfhack) #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 # this needs the C bindings
IF(BUILD_DFHACK_C_BINDIGS) IF(BUILD_DFHACK_C_BINDINGS)
# for trying out some 'stuff' # for trying out some 'stuff'
ADD_EXECUTABLE(dftest test.cpp) ADD_EXECUTABLE(dftest test.cpp)
TARGET_LINK_LIBRARIES(dftest dfhack) TARGET_LINK_LIBRARIES(dftest dfhack)
@ -65,7 +69,7 @@ IF(BUILD_DFHACK_C_BINDIGS)
dftest dftest
RUNTIME DESTINATION bin RUNTIME DESTINATION bin
) )
ENDIF(BUILD_DFHACK_C_BINDIGS) ENDIF(BUILD_DFHACK_C_BINDINGS)
install(TARGETS install(TARGETS
dfmoodump dfmoodump
@ -80,4 +84,3 @@ IF(UNIX)
RUNTIME DESTINATION bin RUNTIME DESTINATION bin
) )
ENDIF(UNIX) ENDIF(UNIX)
ENDIF (BUILD_DFHACK_PLAYGROUND)

@ -311,4 +311,11 @@ bool findString (SegmentedFinder* s, uint32_t *addr, const char * compare )
return false; 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 #endif // SEGMENTED_FINDER_H

@ -21,7 +21,7 @@ using namespace DFHack;
int main ( int argc, char** argv ) int main ( int argc, char** argv )
{ {
DFHack::memory_info *mem; DFHack::VersionInfo *mem;
DFHack::Process *proc; DFHack::Process *proc;
uint32_t creature_pregnancy_offset; 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 // empty input, assume default. observe the length of the memory range vector
// these are hardcoded values, intended for my convenience only // 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()); start = min(11, (int)ranges.size());
end = min(14, (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()); start = min(2, (int)ranges.size());
end = min(4, (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) void FindStrings(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ranges)
{ {
@ -793,18 +809,19 @@ int main (void)
vector <DFHack::t_memrange> selected_ranges; vector <DFHack::t_memrange> selected_ranges;
getRanges(p,selected_ranges); getRanges(p,selected_ranges);
DFHack::memory_info *minfo = DF->getMemoryInfo(); DFHack::VersionInfo *minfo = DF->getMemoryInfo();
DFHack::memory_info::OSType os = minfo->getOS(); DFHack::VersionInfo::OSType os = minfo->getOS();
string prompt = string prompt =
"Select search type: 1=number(default), 2=vector by length, 3=vector>object>string,\n" "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" " 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; int mode;
do do
{ {
getNumber(prompt,mode, 1, false); getNumber(prompt,mode, 1, false);
} while (mode < 1 || mode > 8 ); } while (mode < 1 || mode > 9 );
switch (mode) switch (mode)
{ {
case 1: case 1:
@ -838,6 +855,10 @@ int main (void)
DF->Detach(); DF->Detach();
FindVectorByFirstObjectRawname(DFMgr, selected_ranges); FindVectorByFirstObjectRawname(DFMgr, selected_ranges);
break; break;
case 9:
DF->Detach();
FindStrBufs(DFMgr, selected_ranges);
break;
default: default:
cout << "not implemented :(" << endl; cout << "not implemented :(" << endl;
} }

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

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

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

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

@ -43,12 +43,13 @@ int main (void)
string mode="magma"; string mode="magma";
string brush="point"; string brush="point";
string flowmode="f+"; string flowmode="f+";
string setmode ="s.";
int amount = 7; int amount = 7;
while(!end) while(!end)
{ {
DF->Resume(); DF->Resume();
string command = ""; string command = "";
cout <<"[" << mode << ":" << amount << ":" << flowmode << "]# "; cout <<"[" << mode << ":" << amount << ":" << flowmode << ":" << setmode << "]# ";
getline(cin, command); getline(cin, command);
if(command=="help") if(command=="help")
{ {
@ -57,6 +58,10 @@ int main (void)
<< "w - switch to water" << endl << "w - switch to water" << endl
<< "o - make obsidian wall instead" << endl << "o - make obsidian wall instead" << endl
<< "f - flow bits only" << endl << "f - flow bits only" << endl
<< "Set-Modes:" << endl
<< "s+ - only add" << endl
<< "s. - set" << endl
<< "s- - only remove" << endl
<< "Properties:" << endl << "Properties:" << endl
<< "f+ - make the spawned liquid flow" << endl << "f+ - make the spawned liquid flow" << endl
<< "f. - don't change flow state (read state in flow mode)" << endl << "f. - don't change flow state (read state in flow mode)" << endl
@ -125,6 +130,18 @@ int main (void)
{ {
flowmode = "f."; 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. // blah blah, bad code, bite me.
else if(command == "0") else if(command == "0")
amount = 0; amount = 0;
@ -185,7 +202,7 @@ int main (void)
} }
} }
// quick hack, do not use for serious stuff // quick hack, do not use for serious stuff
/*
else if(mode == "starruby") else if(mode == "starruby")
{ {
if(Maps->isValidBlock((x/16),(y/16),z)) if(Maps->isValidBlock((x/16),(y/16),z))
@ -236,6 +253,7 @@ int main (void)
zzz --; zzz --;
} }
} }
*/
else else
{ {
// place the magma // place the magma
@ -248,7 +266,21 @@ int main (void)
// fix temperatures so we don't produce lethal heat traps // 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") 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; 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") if(mode == "magma")
designations[x%16][y%16].bits.liquid_type = DFHack::liquid_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 // fix temperatures so we don't produce lethal heat traps
if(amount == 0 || designations[xx][yy].bits.liquid_type == DFHack::liquid_magma && mode == "water") 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; 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") if(mode == "magma")
designations[xx][yy].bits.liquid_type = DFHack::liquid_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::Position *Pos = DF->getPosition();
DFHack::memory_info* mem = DF->getMemoryInfo(); DFHack::VersionInfo* mem = DF->getMemoryInfo();
DFHack::Maps *Maps = DF->getMaps(); DFHack::Maps *Maps = DF->getMaps();
DFHack::Process * p = DF->getProcess(); DFHack::Process * p = DF->getProcess();
uint32_t designatus = mem->getOffset("map_data_designation"); OffsetGroup *mapsg = mem->getGroup("Maps");
uint32_t block_feature1 = mem->getOffset("map_data_feature_local"); OffsetGroup *mapblockg = mapsg->getGroup("block");
uint32_t block_feature2 = mem->getOffset("map_data_feature_global"); OffsetGroup *localfeatg = mapsg->getGroup("features")->getGroup("local");
uint32_t region_x_offset = mem->getAddress("region_x");
uint32_t region_y_offset = mem->getAddress("region_y"); uint32_t region_x_offset = mapsg->getAddress("region_x");
uint32_t region_z_offset = mem->getAddress("region_z"); uint32_t region_y_offset = mapsg->getAddress("region_y");
uint32_t feature1_start_ptr = mem->getAddress("local_feature_start_ptr"); 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; int32_t regionX, regionY, regionZ;
// read position of the region inside DF world // read position of the region inside DF world
@ -78,14 +84,13 @@ int main (int numargs, const char ** args)
if(tileTypeTable[tiletype].name) if(tileTypeTable[tiletype].name)
std::cout << " = " << tileTypeTable[tiletype].name; std::cout << " = " << tileTypeTable[tiletype].name;
std::cout << std::endl; std::cout << std::endl;
std::cout <<"temperature1: " << tmpb1[tileX][tileY] << " U" << std::endl; std::cout <<"temperature1: " << tmpb1[tileX][tileY] << " U" << std::endl;
std::cout <<"temperature2: " << tmpb2[tileX][tileY] << " U" << std::endl; std::cout <<"temperature2: " << tmpb2[tileX][tileY] << " U" << std::endl;
// biome, geolayer // biome, geolayer
std::cout << "biome: " << des.biome << std::endl; std::cout << "biome: " << des.biome << std::endl;
std::cout << "geolayer: " << des.geolayer_index << std::endl; std::cout << "geolayer: " << des.geolayer_index << std::endl;
// liquids // liquids
if(des.flow_size) if(des.flow_size)
{ {

@ -313,6 +313,11 @@ int main (int argc, const char* argv[])
std::sort(matss.begin(), matss.end(), compare_pair_second<>()); std::sort(matss.begin(), matss.end(), compare_pair_second<>());
for(int i = 0; i < matss.size();i++) 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; cout << Mats->inorganic[matss[i].first].id << " : " << matss[i].second << endl;
} }
DF->Detach(); DF->Detach();

@ -6,6 +6,7 @@
using namespace std; using namespace std;
#include <DFHack.h> #include <DFHack.h>
#include <dfhack/modules/Gui.h>
struct hideblock struct hideblock
{ {
@ -37,6 +38,19 @@ int main (void)
} }
DFHack::Maps *Maps =DF->getMaps(); 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 // init the map
if(!Maps->Start()) if(!Maps->Start())
{ {
@ -47,10 +61,11 @@ int main (void)
return 1; return 1;
} }
cout << "Revealing, please wait..." << endl;
Maps->getSize(x_max,y_max,z_max); Maps->getSize(x_max,y_max,z_max);
vector <hideblock> hidesaved; 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 x = 0; x< x_max;x++)
{ {
for(uint32_t y = 0; y< y_max;y++) for(uint32_t y = 0; y< y_max;y++)
@ -80,8 +95,10 @@ int main (void)
} }
// FIXME: force game pause here! // FIXME: force game pause here!
DF->Detach(); DF->Detach();
cout << "Map revealed. Close window/force exit to keep it that way." << endl; cout << "Map revealed. The game has been paused for you." << endl;
cout << "Press any key to unreveal. Don't close DF or unpause in that case!" << 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(); cin.ignore();
cout << "Unrevealing... please wait." << endl; cout << "Unrevealing... please wait." << endl;
// FIXME: do some consistency checks here! // FIXME: do some consistency checks here!

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