diff --git a/.gitignore b/.gitignore
index 5abcc3138..356bf6399 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@ output/*
# a file generated by cmake
dfhack/include/config.h
+library/private/config.h
# any build folders
build*/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a03f7d6cc..b794b7143 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,6 +4,11 @@ cmake_minimum_required(VERSION 2.6)
SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/Modules)
SET ( DFHACK_VERSION "0.4.1.0-dev" )
+# Set this to project source dir. When dfhack is used
+# as a submodule, CMAKE_SOURCE_DIR is not pointing to
+# the root where this particular CMakeLists.txt file sits.
+SET(CMAKE_SOURCE_DIR ${PROJECT_SOURCE_DIR})
+
# disable warning, autosearch
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
@@ -26,6 +31,8 @@ OPTION(BUILD_DFHACK_EXAMPLES "Build example tools" OFF)
OPTION(BUILD_DFHACK_PLAYGROUND "Build tools from the playground folder" OFF)
OPTION(BUILD_DFHACK_C_BINDIGS "Build the C portion of the library" ON)
OPTION(BUILD_OFFSET_EDITOR "Build the Offset GUI editor (not ready for use)." OFF)
+OPTION(BUILD_DFHACK_SUPPORTED "Build the supported toold." ON)
+OPTION(BUILD_DFHACK_SHM "Build the SHM." OFF)
include_directories (${CMAKE_SOURCE_DIR}/library/include/)
include_directories (${CMAKE_SOURCE_DIR}/library/shm/)
@@ -35,12 +42,26 @@ include_directories (${CMAKE_SOURCE_DIR}/library/depends/argstream/)
add_subdirectory (library)
+IF(BUILD_DFHACK_SUPPORTED)
+ add_subdirectory (tools/supported)
+ENDIF(BUILD_DFHACK_SUPPORTED)
+
IF(BUILD_OFFSET_EDITOR)
add_subdirectory (offsetedit)
ENDIF(BUILD_OFFSET_EDITOR)
-add_subdirectory (library/shm)
-add_subdirectory (tools/examples)
-add_subdirectory (tools/playground)
-add_subdirectory (tools/supported)
-add_subdirectory (doc)
\ No newline at end of file
+IF(BUILD_DFHACK_SHM)
+ add_subdirectory (library/shm)
+ENDIF(BUILD_DFHACK_SHM)
+
+IF(BUILD_DFHACK_EXAMPLES)
+ add_subdirectory (tools/examples)
+ENDIF(BUILD_DFHACK_EXAMPLES)
+
+IF(BUILD_DFHACK_PLAYGROUND)
+ add_subdirectory (tools/playground)
+ENDIF(BUILD_DFHACK_PLAYGROUND)
+
+IF(BUILD_DFHACK_DOCUMENTATION)
+ add_subdirectory (doc)
+ENDIF(BUILD_DFHACK_DOCUMENTATION)
diff --git a/build/build-MinGW32-release-trace.bat b/build/build-MinGW32-release-trace.bat
index f75da5ff8..ca7df86d3 100644
--- a/build/build-MinGW32-release-trace.bat
+++ b/build/build-MinGW32-release-trace.bat
@@ -1,6 +1,6 @@
-mkdir build-real
-cd build-real
-cmake ..\.. -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE:string=Release --trace > trace-stdout.txt 2> trace-stderr.txt
-mingw32-make 2> log.txt
-pause
+mkdir build-real
+cd build-real
+cmake ..\.. -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE:string=Release --trace > trace-stdout.txt 2> trace-stderr.txt
+mingw32-make 2> log.txt
+pause
dir file.xxx
\ No newline at end of file
diff --git a/build/generate-MSVC-2010.bat b/build/generate-MSVC-2010.bat
index 588051bc6..50828f7ea 100644
--- a/build/generate-MSVC-2010.bat
+++ b/build/generate-MSVC-2010.bat
@@ -1,4 +1,4 @@
-mkdir build-real
-cd build-real
-cmake ..\.. -G"Visual Studio 10"
+mkdir build-real
+cd build-real
+cmake ..\.. -G"Visual Studio 10"
pause
\ No newline at end of file
diff --git a/data/Memory-ng.xml b/data/Memory-ng.xml
index 294886988..fdb84d2b1 100644
--- a/data/Memory-ng.xml
+++ b/data/Memory-ng.xml
@@ -144,363 +144,216 @@
- TODO: Parse this and turn it into Job tags
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -813,20 +666,242 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ vector
+ vector
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ List of offsets in the VTable :
+
+
+
+
+
+
+
+
+
+ (in the vtable)
+
+
+
+
+
@@ -879,6 +954,11 @@
+
+
+
+
+
@@ -963,7 +1043,7 @@
-
+
@@ -1009,11 +1089,11 @@
seems to be just like the old occupations
- like mood materials, 0=bars, 4=stone, 5=wood, 57=cloth, 54=leather ...
- subsubtype ?
- subtype ?
- index of material (for example, 2 is for silver)
- set only for shell / bone mood requirements ?
+ like mood materials, 0=bars, 4=stone, 5=wood, 57=cloth, 54=leather ...
+ subsubtype ?
+ subtype ?
+ index of material (for example, 2 is for silver)
+ set only for shell / bone mood requirements ?
@@ -1057,7 +1137,7 @@
-
+
@@ -1145,7 +1225,7 @@
-
+
@@ -1157,12 +1237,12 @@
-
-
-
-
-
+
+
+
+
+
@@ -1214,21 +1294,22 @@
-
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
@@ -1257,7 +1338,7 @@
-
+
@@ -1266,10 +1347,10 @@
-
+
-
+
@@ -1348,10 +1429,11 @@
-
+
+
@@ -1383,8 +1465,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0x01482874 - current race
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 31.13 WEATHER_START 0147E94E
.-"""-.
' \
|,. ,-. | _________________________
@@ -1407,7 +1651,7 @@
-
+
@@ -1438,9 +1682,6 @@
-
-
-
@@ -1462,8 +1703,8 @@
-
-
+
+
@@ -1488,11 +1729,11 @@
vector
- vector
+ vector
-
+
@@ -1500,7 +1741,7 @@
-
+
@@ -1508,8 +1749,8 @@
- CHMOD
- VERIFY!
+ CHMOD
+ VERIFY!
chmod
@@ -1523,26 +1764,29 @@
-
+
+
@@ -1555,6 +1799,8 @@
+
@@ -1584,26 +1831,18 @@
-
-
-
-
-
-
-
-
-
+
@@ -1618,18 +1857,36 @@
0x92d7a10
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CHMOD
+
+
+
+
-
+
@@ -1647,18 +1904,104 @@
-
+
- VERIFIED
- VERIFIED
- VERIFIED
- VERIFIED
+
+ VERIFIED
+ VERIFIED
+ VERIFIED
+ VERIFIED
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/Memory.xml b/data/Memory.xml
index fd0072623..381e39708 100644
--- a/data/Memory.xml
+++ b/data/Memory.xml
@@ -1698,6 +1698,7 @@ map_data_1b60_offset 0x1B9c
0x168E73C
0x014b9f1c
0X1F4
+ 0x2FC
0x4AC
0x64c
0x71c
@@ -1721,6 +1722,7 @@ map_data_1b60_offset 0x1B9c
f0459165a426a9f2dd8d957e9fa7f01d
0x4C4C32E7
+ 0x18313D0
.-"""-.
' \
@@ -2359,6 +2361,7 @@ map_data_1b60_offset 0x1B9c
e79cead03187ecb692961b316b7cdcd4
+ 0x09487970
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index 1ced1fd7b..c1f2cdaca 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -10,8 +10,6 @@
# http://tobias.rautenkranz.ch/cmake/doxygen/
# but it is hard to understand...
-IF (BUILD_DFHACK_DOCUMENTATION)
-
FIND_PACKAGE(Doxygen)
IF(DOXYGEN_FOUND)
@@ -63,6 +61,4 @@ IF(DOXYGEN_FOUND)
ELSE(DOXYGEN_FOUND)
MESSAGE (FATAL_ERROR "doxygen binary couldn't be found")
-ENDIF(DOXYGEN_FOUND)
-
-ENDIF (BUILD_DFHACK_DOCUMENTATION)
\ No newline at end of file
+ENDIF(DOXYGEN_FOUND)
\ No newline at end of file
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 8e09a2203..813d356dc 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -26,20 +26,29 @@ include_directories (${CMAKE_SOURCE_DIR}/library/depends/tinyxml/)
include_directories (${CMAKE_SOURCE_DIR}/library/depends/argstream/)
include_directories (${CMAKE_SOURCE_DIR}/library/private/)
+SET(PROJECT_HDRS_INTERNAL
+ private/ContextShared.h
+ private/Internal.h
+)
+
SET(PROJECT_HDRS
-private/DFMemInfoManager.h
-private/ContextShared.h
-private/Internal.h
+include/DFHack.h
+include/dfhack/DFContext.h
+include/dfhack/DFContextManager.h
include/dfhack/DFError.h
-include/dfhack/DFMemInfo.h
-include/dfhack/DFProcessEnumerator.h
+include/dfhack/DFExport.h
+include/dfhack/DFGlobal.h
+include/dfhack/DFIntegers.h
+include/dfhack/DFMiscUtils.h
+include/dfhack/DFModule.h
+include/dfhack/DFPragma.h
include/dfhack/DFProcess.h
+include/dfhack/DFProcessEnumerator.h
include/dfhack/DFTileTypes.h
include/dfhack/DFTypes.h
include/dfhack/DFVector.h
-include/dfhack-c/DFTypes_C.h
-include/dfhack-c/DFContext_C.h
-include/dfhack/DFIntegers.h
+include/dfhack/VersionInfoFactory.h
+include/dfhack/VersionInfo.h
include/dfhack/modules/Buildings.h
include/dfhack/modules/Constructions.h
include/dfhack/modules/Creatures.h
@@ -55,13 +64,26 @@ include/dfhack/modules/World.h
)
SET(PROJECT_C_HDRS
+include/DFHack_C.h
include/dfhack-c/DFTypes_C.h
include/dfhack-c/DFContext_C.h
+include/dfhack-c/modules/Buildings_C.h
+include/dfhack-c/modules/Constructions_C.h
+include/dfhack-c/modules/Creatures_C.h
+include/dfhack-c/modules/Gui_C.h
+include/dfhack-c/modules/Items_C.h
+include/dfhack-c/modules/Maps_C.h
+include/dfhack-c/modules/Materials_C.h
+include/dfhack-c/modules/Position_C.h
+include/dfhack-c/modules/Translation_C.h
+include/dfhack-c/modules/Vegetation_C.h
+include/dfhack-c/modules/WindowIO_C.h
+include/dfhack-c/modules/World_C.h
)
SET(PROJECT_SRCS
-DFMemInfo.cpp
-DFMemInfoManager.cpp
+VersionInfo.cpp
+VersionInfoFactory.cpp
DFContextManager.cpp
DFContext.cpp
DFProcessEnumerator.cpp
@@ -134,10 +156,10 @@ ELSE(UNIX)
LIST(APPEND PROJECT_SRCS ${PROJECT_SRCS_WINDOWS})
ENDIF(UNIX)
-IF(BUILD_DFHACK_C_BINDIGS)
+IF(BUILD_DFHACK_C_BINDINGS)
LIST(APPEND PROJECT_HDRS ${PROJECT_C_HDRS})
LIST(APPEND PROJECT_SRCS ${PROJECT_C_SRCS})
-ENDIF(BUILD_DFHACK_C_BINDIGS)
+ENDIF(BUILD_DFHACK_C_BINDINGS)
SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE )
@@ -147,7 +169,7 @@ SET( MEMXML_DATA_PATH . CACHE PATH "search path for Memory.xml")
# OPTION( VARIABLE "Description" Initial state)
#OPTION( WITH_FOO "Enable FOO support" ON )
#OPTION( WITH_BAR "Enable BAR component" OFF )
-
+
# Are we 64bit? (Damn you, ptrace()!)
IF( CMAKE_SIZEOF_VOID_P MATCHES 4 )
SET( HAVE_64_BIT 0 )
@@ -165,7 +187,7 @@ IF(UNIX)
find_library(X11_LIBRARY X11)
SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall")
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden")
-
+
SET(PROJECT_LIBS ${X11_LIBRARY} rt ) #dfhack-md5 dfhack-tixml
ELSE(UNIX)
SET(PROJECT_LIBS psapi)
@@ -184,7 +206,7 @@ if(MSVC)
#
# So, $(TargetDir) is ignored by cmake, and replaced with the actual output directory by MSVC
ADD_CUSTOM_COMMAND(TARGET dfhack POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/data/Memory.xml $(TargetDir)/Memory.xml
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/data/Memory-ng.xml $(TargetDir)/Memory.xml
)
ADD_CUSTOM_COMMAND(TARGET dfhack POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/Compile.html $(TargetDir)/Compile.html
@@ -192,14 +214,19 @@ if(MSVC)
ADD_CUSTOM_COMMAND(TARGET dfhack POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/Readme.html $(TargetDir)/Readme.html
)
+ ADD_CUSTOM_COMMAND(TARGET dfhack POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/LICENSE $(TargetDir)/LICENSE.txt
+ )
else(MSVC)
# Just put the file in the output directory on Linux and Mac
- configure_file(${CMAKE_SOURCE_DIR}/data/Memory.xml ${DATA_OUTPUT_PATH}/Memory.xml COPYONLY)
+ configure_file(${CMAKE_SOURCE_DIR}/data/Memory-ng.xml ${DATA_OUTPUT_PATH}/Memory.xml COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/Compile.html ${DATA_OUTPUT_PATH}/Compile.html COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/Readme.html ${DATA_OUTPUT_PATH}/Readme.html COPYONLY)
+ configure_file(${CMAKE_SOURCE_DIR}/LICENSE ${DATA_OUTPUT_PATH}/LICENSE.txt COPYONLY)
endif(MSVC)
IF(UNIX)
install(TARGETS dfhack LIBRARY DESTINATION lib)
install(FILES ${CMAKE_SOURCE_DIR}/output/Memory.xml DESTINATION share/dfhack)
+ install(DIRECTORY ${CMAKE_SOURCE_DIR}/library/include/ DESTINATION include FILES_MATCHING PATTERN "*.h")
ENDIF(UNIX)
diff --git a/library/ContextShared.cpp b/library/ContextShared.cpp
index cf49a489b..62ca3fff1 100644
--- a/library/ContextShared.cpp
+++ b/library/ContextShared.cpp
@@ -4,7 +4,7 @@
#include
#include
#include "private/ContextShared.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/modules/Materials.h"
@@ -40,9 +40,10 @@ DFContextShared::~DFContextShared()
bool DFContextShared::InitReadNames()
{
- name_firstname_offset = offset_descriptor->getOffset("name_firstname");
- name_nickname_offset = offset_descriptor->getOffset("name_nickname");
- name_words_offset = offset_descriptor->getOffset("name_words");
+ OffsetGroup * OG = offset_descriptor->getGroup("name");
+ name_firstname_offset = OG->getOffset("first");
+ name_nickname_offset = OG->getOffset("nick");
+ name_words_offset = OG->getOffset("second_words");
return true;
}
diff --git a/library/DFContext.cpp b/library/DFContext.cpp
index d46302426..8b67f193f 100644
--- a/library/DFContext.cpp
+++ b/library/DFContext.cpp
@@ -199,7 +199,7 @@ void Context::WriteRaw (const uint32_t offset, const uint32_t size, uint8_t *sou
d->p->write (offset, size, source);
}
-memory_info *Context::getMemoryInfo()
+VersionInfo *Context::getMemoryInfo()
{
return d->offset_descriptor;
}
diff --git a/library/DFContextManager.cpp b/library/DFContextManager.cpp
index 46814d90e..f338ce6ee 100644
--- a/library/DFContextManager.cpp
+++ b/library/DFContextManager.cpp
@@ -23,8 +23,8 @@ distribution.
*/
#include "Internal.h"
-#include "DFMemInfoManager.h"
+#include "dfhack/VersionInfoFactory.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFProcessEnumerator.h"
#include "dfhack/DFError.h"
@@ -142,7 +142,7 @@ ContextManager::~ContextManager()
uint32_t ContextManager::Refresh( BadContexts* bad_contexts )
{
- // handle expired processes, remove stale Contexts
+ // handle expired processes, remove stale Contexts
{
BadProcesses expired;
// get new list od living and expired Process objects
diff --git a/library/DFMemInfo.cpp b/library/DFMemInfo.cpp
deleted file mode 100644
index ca7c58d03..000000000
--- a/library/DFMemInfo.cpp
+++ /dev/null
@@ -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 subs;
- };
-}
-/*
- * Private data
- */
-class memory_info::Private
-{
- public:
- map addresses;
- map offsets;
- map hexvals;
- map strings;
-
- vector professions;
- vector jobs;
- vector skills;
- vector levels;
- vector< vector > traits;
- vector moods;
- map labors;
-
- // storage for class and multiclass
- vector classes;
-
- // cache for faster name lookup, indexed by classID
- vector classnames;
- // map between vptr and class id, needs further type id lookup for multi-classes, not inherited
- map 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; iclasses.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 & vec = parent->subs;
- for (uint32_t i=0; iclassname == 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::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 & 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 * memory_info::getClassIDMapping()
-{
- return &d->classnames;
-}
-
-
-// change base of all addresses
-void memory_info::RebaseAddresses(const int32_t new_base)
-{
- map::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::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::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 ::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 ::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 ::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 ::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 ::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 ::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 ::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 > 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 << "" << endl;
- switch (getOS())
- {
- case OS_LINUX:
- ss << "" << endl;
- break;
- case OS_WINDOWS:
- ss << "" << endl;
- ss << "" << endl;
- break;
- default:
- ss << " UNKNOWN" << endl;
- }
- ss << "" << endl;
- map::const_iterator iter;
- for(iter = d->addresses.begin(); iter != d->addresses.end(); iter++)
- {
- ss << " " << endl;
- }
- map::const_iterator iter2;
- for(iter2 = d->offsets.begin(); iter2 != d->offsets.end(); iter2++)
- {
- ss << " " << endl;
- }
- for(iter = d->hexvals.begin(); iter != d->hexvals.end(); iter++)
- {
- ss << " " << endl;
- }
- map::const_iterator iter3;
- for(iter3 = d->strings.begin(); iter3 != d->strings.end(); iter3++)
- {
- ss << " " << endl;
- }
- ss << "" << endl;
- ss << "" << endl;
- return ss.str();
-}
\ No newline at end of file
diff --git a/library/DFMemInfoManager.cpp b/library/DFMemInfoManager.cpp
deleted file mode 100644
index cc4c5de4a..000000000
--- a/library/DFMemInfoManager.cpp
+++ /dev/null
@@ -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 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 & 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 map_pNamedEntries;
- vector 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;
-}
diff --git a/library/DFProcess-linux-SHM.cpp b/library/DFProcess-linux-SHM.cpp
index acf519ecf..ace2dacf8 100644
--- a/library/DFProcess-linux-SHM.cpp
+++ b/library/DFProcess-linux-SHM.cpp
@@ -23,7 +23,7 @@ distribution.
*/
#include "Internal.h"
#include "dfhack/DFProcess.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include
@@ -63,7 +63,7 @@ class SHMProcess::Private
self = self_;
};
~Private(){};
- memory_info * memdescriptor;
+ VersionInfo * memdescriptor;
Process * self;
pid_t process_ID;
char *shm_addr;
@@ -79,7 +79,7 @@ class SHMProcess::Private
bool identified;
bool useYield;
- bool validate(std::vector< memory_info* >& known_versions);
+ bool validate(std::vector< VersionInfo* >& known_versions);
bool Aux_Core_Attach(bool & versionOK, pid_t & PID);
//bool waitWhile (uint32_t state);
@@ -159,7 +159,7 @@ uint32_t OS_getAffinity()
bool SHMProcess::Private::AreLocksOk()
{
// both locks are inited (we hold our lock)
- if(client_lock != -1 && server_lock != -1)
+ if(client_lock != -1 && server_lock != -1)
{
if(lockf(server_lock,F_TEST,0) == -1) // and server holds its lock
{
@@ -204,7 +204,7 @@ bool SHMProcess::Private::GetLocks()
// cerr << "can't open sv lock" << endl;
return false;
}
-
+
if(lockf( server_lock, F_TEST, 0 ) != -1)
{
cerr << "sv lock not locked" << endl;
@@ -212,7 +212,7 @@ bool SHMProcess::Private::GetLocks()
server_lock = -1;
return false;
}
-
+
for(int i = 0; i < SHM_MAX_CLIENTS; i++)
{
// open the client suspend locked
@@ -258,7 +258,7 @@ bool SHMProcess::Private::GetLocks()
return false;
}
-SHMProcess::SHMProcess(uint32_t PID, vector< memory_info* >& known_versions)
+SHMProcess::SHMProcess(uint32_t PID, vector< VersionInfo* >& known_versions)
: d(new Private(this))
{
d->process_ID = PID;
@@ -282,7 +282,7 @@ SHMProcess::SHMProcess(uint32_t PID, vector< memory_info* >& known_versions)
detach();
throw Error::SHMVersionMismatch();
}
-
+
// try to identify the DF version (md5 the binary, compare with known versions)
d->validate(known_versions);
// detach
@@ -303,7 +303,7 @@ bool SHMProcess::isIdentified()
return d->identified;
}
-bool SHMProcess::Private::validate(vector & known_versions)
+bool SHMProcess::Private::validate(vector & known_versions)
{
char exe_link_name [256];
char target_name[1024];
@@ -319,19 +319,19 @@ bool SHMProcess::Private::validate(vector & known_versions)
// make sure we have a null terminated string...
// see http://www.opengroup.org/onlinepubs/000095399/functions/readlink.html
target_name[target_result] = 0;
-
+
md5wrapper md5;
// get hash of the running DF process
string hash = md5.getHashFromFile(target_name);
- vector::iterator it;
+ vector::iterator it;
// cerr << exe_file << " " << hash << endl;
// iterate over the list of memory locations
for ( it=known_versions.begin() ; it < known_versions.end(); it++ )
{
try{
- if(hash == (*it)->getString("md5")) // are the md5 hashes the same?
+ if(hash == (*it)->getMD5()) // are the md5 hashes the same?
{
- memory_info *m = new memory_info(**it);
+ VersionInfo *m = new VersionInfo(**it);
memdescriptor = m;
m->setParentProcess(dynamic_cast( self ));
identified = true;
@@ -358,7 +358,7 @@ SHMProcess::~SHMProcess()
delete d;
}
-memory_info * SHMProcess::getDescriptor()
+VersionInfo * SHMProcess::getDescriptor()
{
return d->memdescriptor;
}
@@ -385,11 +385,11 @@ void SHMProcess::getMemRanges( vector & ranges )
{
char buffer[1024];
char permissions[5]; // r/-, w/-, x/-, p/s, 0
-
+
sprintf(buffer, "/proc/%lu/maps", d->process_ID);
FILE *mapFile = ::fopen(buffer, "r");
uint64_t offset, device1, device2, node;
-
+
while (fgets(buffer, 1024, mapFile))
{
t_memrange temp;
@@ -417,7 +417,7 @@ bool SHMProcess::suspend()
{
return true;
}
-
+
// FIXME: this should be controlled on the server side
// FIXME: IF server got CORE_RUN in this frame, interpret CORE_SUSPEND as CORE_STEP
// did we just resume a moment ago?
@@ -546,7 +546,7 @@ bool SHMProcess::attach()
cerr << "can't find segment" << endl; // FIXME: throw
return false;
}
-
+
/*
* Attach the segment
*/
@@ -592,7 +592,7 @@ bool SHMProcess::detach()
void SHMProcess::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
// normal read under 1MB
if(size <= SHM_BODY)
{
@@ -629,7 +629,7 @@ void SHMProcess::read (uint32_t src_address, uint32_t size, uint8_t *target_buff
uint8_t SHMProcess::readByte (const uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
gcc_barrier
d->SetAndWait(CORE_READ_BYTE);
@@ -639,7 +639,7 @@ uint8_t SHMProcess::readByte (const uint32_t offset)
void SHMProcess::readByte (const uint32_t offset, uint8_t &val )
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
gcc_barrier
d->SetAndWait(CORE_READ_BYTE);
@@ -649,7 +649,7 @@ void SHMProcess::readByte (const uint32_t offset, uint8_t &val )
uint16_t SHMProcess::readWord (const uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
gcc_barrier
d->SetAndWait(CORE_READ_WORD);
@@ -659,7 +659,7 @@ uint16_t SHMProcess::readWord (const uint32_t offset)
void SHMProcess::readWord (const uint32_t offset, uint16_t &val)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
gcc_barrier
d->SetAndWait(CORE_READ_WORD);
@@ -669,7 +669,7 @@ void SHMProcess::readWord (const uint32_t offset, uint16_t &val)
uint32_t SHMProcess::readDWord (const uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
gcc_barrier
d->SetAndWait(CORE_READ_DWORD);
@@ -678,7 +678,7 @@ uint32_t SHMProcess::readDWord (const uint32_t offset)
void SHMProcess::readDWord (const uint32_t offset, uint32_t &val)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
gcc_barrier
d->SetAndWait(CORE_READ_DWORD);
@@ -688,7 +688,7 @@ void SHMProcess::readDWord (const uint32_t offset, uint32_t &val)
uint64_t SHMProcess::readQuad (const uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
gcc_barrier
d->SetAndWait(CORE_READ_QUAD);
@@ -697,7 +697,7 @@ uint64_t SHMProcess::readQuad (const uint32_t offset)
void SHMProcess::readQuad (const uint32_t offset, uint64_t &val)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
gcc_barrier
d->SetAndWait(CORE_READ_QUAD);
@@ -707,7 +707,7 @@ void SHMProcess::readQuad (const uint32_t offset, uint64_t &val)
float SHMProcess::readFloat (const uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
gcc_barrier
d->SetAndWait(CORE_READ_DWORD);
@@ -716,7 +716,7 @@ float SHMProcess::readFloat (const uint32_t offset)
void SHMProcess::readFloat (const uint32_t offset, float &val)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
gcc_barrier
d->SetAndWait(CORE_READ_DWORD);
@@ -730,7 +730,7 @@ void SHMProcess::readFloat (const uint32_t offset, float &val)
void SHMProcess::writeQuad (const uint32_t offset, const uint64_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
D_SHMHDR->Qvalue = data;
gcc_barrier
@@ -740,7 +740,7 @@ void SHMProcess::writeQuad (const uint32_t offset, const uint64_t data)
void SHMProcess::writeDWord (uint32_t offset, uint32_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
gcc_barrier
@@ -751,7 +751,7 @@ void SHMProcess::writeDWord (uint32_t offset, uint32_t data)
void SHMProcess::writeWord (uint32_t offset, uint16_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
gcc_barrier
@@ -761,7 +761,7 @@ void SHMProcess::writeWord (uint32_t offset, uint16_t data)
void SHMProcess::writeByte (uint32_t offset, uint8_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
gcc_barrier
@@ -771,7 +771,7 @@ void SHMProcess::writeByte (uint32_t offset, uint8_t data)
void SHMProcess::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
// normal write under 1MB
if(size <= SHM_BODY)
{
@@ -809,7 +809,7 @@ void SHMProcess::write (uint32_t dst_address, uint32_t size, uint8_t *source_buf
const std::string SHMProcess::readCString (uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
std::string temp;
char temp_c[256];
int counter = 0;
@@ -828,7 +828,7 @@ const std::string SHMProcess::readCString (uint32_t offset)
const std::string SHMProcess::readSTLString(uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_STL_STRING);
@@ -838,7 +838,7 @@ const std::string SHMProcess::readSTLString(uint32_t offset)
size_t SHMProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_STL_STRING);
@@ -852,7 +852,7 @@ size_t SHMProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapa
void SHMProcess::writeSTLString(const uint32_t address, const std::string writeString)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = address;
strncpy(D_SHMDATA(char),writeString.c_str(),writeString.length()+1); // length + 1 for the null terminator
full_barrier
@@ -862,7 +862,7 @@ void SHMProcess::writeSTLString(const uint32_t address, const std::string writeS
string SHMProcess::readClassName (uint32_t vptr)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
int typeinfo = readDWord(vptr - 0x4);
int typestring = readDWord(typeinfo + 0x4);
string raw = readCString(typestring);
@@ -875,13 +875,13 @@ string SHMProcess::readClassName (uint32_t vptr)
bool SHMProcess::getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
modulelookup * payload = D_SHMDATA(modulelookup);
payload->version = version;
-
+
strncpy(payload->name,name,255);
payload->name[255] = 0;
-
+
if(!SetAndWait(CORE_ACQUIRE_MODULE))
{
return false; // FIXME: throw a fatal exception instead
@@ -898,14 +898,14 @@ bool SHMProcess::getModuleIndex (const char * name, const uint32_t version, uint
char * SHMProcess::getSHMStart (void)
{
if(!d->locked) return 0; //THROW HERE!
-
+
return /*d->shm_addr_with_cl_idx*/ d->shm_addr;
}
bool SHMProcess::Private::Aux_Core_Attach(bool & versionOK, pid_t & PID)
{
if(!locked) throw Error::MemoryAccessDenied();
-
+
SHMDATA(coreattach)->cl_affinity = OS_getAffinity();
if(!SetAndWait(CORE_ATTACH)) return false;
/*
diff --git a/library/DFProcess-linux-wine.cpp b/library/DFProcess-linux-wine.cpp
index b71e2266f..891a4f820 100644
--- a/library/DFProcess-linux-wine.cpp
+++ b/library/DFProcess-linux-wine.cpp
@@ -23,7 +23,7 @@ distribution.
*/
#include "Internal.h"
#include "dfhack/DFProcess.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include
#include
@@ -44,7 +44,7 @@ class WineProcess::Private
self = self_;
};
~Private(){};
- memory_info * my_descriptor;
+ VersionInfo * my_descriptor;
Process * self;
pid_t my_handle;
uint32_t my_pid;
@@ -53,10 +53,13 @@ class WineProcess::Private
bool attached;
bool suspended;
bool identified;
- bool validate(char * exe_file, uint32_t pid, char * mem_file, vector & 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 & known_versions);
};
-WineProcess::WineProcess(uint32_t pid, vector & known_versions)
+WineProcess::WineProcess(uint32_t pid, vector & known_versions)
: d(new Private(this))
{
char dir_name [256];
@@ -66,16 +69,16 @@ WineProcess::WineProcess(uint32_t pid, vector & known_versions)
char cmdline_name [256];
char target_name[1024];
int target_result;
-
+
d->identified = false;
d->my_descriptor = 0;
-
+
sprintf(dir_name,"/proc/%d/", pid);
sprintf(exe_link_name,"/proc/%d/exe", pid);
sprintf(mem_name,"/proc/%d/mem", pid);
sprintf(cwd_name,"/proc/%d/cwd", pid);
sprintf(cmdline_name,"/proc/%d/cmdline", pid);
-
+
// resolve /proc/PID/exe link
target_result = readlink(exe_link_name, target_name, sizeof(target_name)-1);
if (target_result == -1)
@@ -84,7 +87,7 @@ WineProcess::WineProcess(uint32_t pid, vector & known_versions)
}
// make sure we have a null terminated string...
target_name[target_result] = 0;
-
+
// FIXME: this fails when the wine process isn't started from the 'current working directory'. strip path data from cmdline
// is this windows version of Df running in wine?
if(strstr(target_name, "wine-preloader")!= NULL)
@@ -92,7 +95,7 @@ WineProcess::WineProcess(uint32_t pid, vector & known_versions)
// get working directory
target_result = readlink(cwd_name, target_name, sizeof(target_name)-1);
target_name[target_result] = 0;
-
+
// got path to executable, do the same for its name
ifstream ifs ( cmdline_name , ifstream::in );
string cmdline;
@@ -102,7 +105,7 @@ WineProcess::WineProcess(uint32_t pid, vector & known_versions)
char exe_link[1024];
// put executable name and path together
sprintf(exe_link,"%s/%s",target_name,cmdline.c_str());
-
+
// create wine process, add it to the vector
d->identified = d->validate(exe_link,pid,mem_name,known_versions);
return;
@@ -124,37 +127,41 @@ bool WineProcess::isIdentified()
return d->identified;
}
-bool WineProcess::Private::validate(char* exe_file, uint32_t pid, char* mem_file, std::vector< memory_info* >& known_versions)
+bool WineProcess::Private::validate(char* exe_file, uint32_t pid, char* mem_file, std::vector< VersionInfo* >& known_versions)
{
md5wrapper md5;
// get hash of the running DF process
string hash = md5.getHashFromFile(exe_file);
- vector::iterator it;
-
+ vector::iterator it;
+
// iterate over the list of memory locations
for ( it=known_versions.begin() ; it < known_versions.end(); it++ )
{
string thishash;
try
{
- thishash = (*it)->getString("md5");
+ thishash = (*it)->getMD5();
}
catch (Error::MissingMemoryDefinition& e)
{
continue;
}
// are the md5 hashes the same?
- if(memory_info::OS_WINDOWS == (*it)->getOS() && hash == thishash)
+ if(VersionInfo::OS_WINDOWS == (*it)->getOS() && hash == thishash)
{
-
+
// keep track of created memory_info object so we can destroy it later
- memory_info *m = new memory_info(**it);
+ VersionInfo *m = new VersionInfo(**it);
my_descriptor = m;
m->setParentProcess(dynamic_cast( self ));
my_handle = my_pid = pid;
// tell WineProcess about the /proc/PID/mem file
memFile = mem_file;
identified = true;
+ OffsetGroup * strGrp = m->getGroup("string")->getGroup("MSVC");
+ STLSTR_buf_off = strGrp->getOffset("buffer");
+ STLSTR_size_off = strGrp->getOffset("size");
+ STLSTR_cap_off = strGrp->getOffset("capacity");
return true;
}
}
@@ -173,7 +180,7 @@ WineProcess::~WineProcess()
delete d;
}
-memory_info * WineProcess::getDescriptor()
+VersionInfo * WineProcess::getDescriptor()
{
return d->my_descriptor;
}
@@ -194,11 +201,11 @@ void WineProcess::getMemRanges( vector & ranges )
{
char buffer[1024];
char permissions[5]; // r/-, w/-, x/-, p/s, 0
-
+
sprintf(buffer, "/proc/%lu/maps", d->my_pid);
FILE *mapFile = ::fopen(buffer, "r");
uint64_t offset, device1, device2, node;
-
+
while (fgets(buffer, 1024, mapFile))
{
t_memrange temp;
@@ -310,7 +317,7 @@ bool WineProcess::attach()
}
}
d->suspended = true;
-
+
int proc_pid_mem = open(d->memFile.c_str(),O_RDONLY);
if(proc_pid_mem == -1)
{
@@ -323,7 +330,7 @@ bool WineProcess::attach()
else
{
d->attached = true;
-
+
d->memFileHandle = proc_pid_mem;
return true; // we are attached
}
@@ -365,7 +372,7 @@ bool WineProcess::detach()
void WineProcess::read (const uint32_t offset, const uint32_t size, uint8_t *target)
{
if(size == 0) return;
-
+
ssize_t result;
ssize_t total = 0;
ssize_t remaining = size;
@@ -563,23 +570,12 @@ const std::string WineProcess::readCString (uint32_t offset)
size_t WineProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
- /*
- MSVC++ string
- ptr allocator
- union
- {
- char[16] start;
- char * start_ptr
- }
- Uint32 length
- Uint32 capacity
- */
- uint32_t start_offset = offset + 4;
- size_t length = readDWord(offset + 20);
-
- size_t capacity = readDWord(offset + 24);
+ uint32_t start_offset = offset + d->STLSTR_buf_off;
+ size_t length = readDWord(offset + d->STLSTR_size_off);
+ size_t capacity = readDWord(offset + d->STLSTR_cap_off);
+
size_t read_real = min(length, bufcapacity-1);// keep space for null termination
-
+
// read data from inside the string structure
if(capacity < 16)
{
@@ -590,29 +586,19 @@ size_t WineProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcap
start_offset = readDWord(start_offset);// dereference the start offset
read(start_offset, read_real, (uint8_t *)buffer);
}
-
+
buffer[read_real] = 0;
return read_real;
}
const string WineProcess::readSTLString (uint32_t offset)
{
- /*
- MSVC++ string
- ptr allocator
- union
- {
- char[16] start;
- char * start_ptr
- }
- Uint32 length
- Uint32 capacity
- */
- uint32_t start_offset = offset + 4;
- uint32_t length = readDWord(offset + 20);
- uint32_t capacity = readDWord(offset + 24);
+ uint32_t start_offset = offset + d->STLSTR_buf_off;
+ size_t length = readDWord(offset + d->STLSTR_size_off);
+ size_t capacity = readDWord(offset + d->STLSTR_cap_off);
+
char * temp = new char[capacity+1];
-
+
// read data from inside the string structure
if(capacity < 16)
{
@@ -623,7 +609,7 @@ const string WineProcess::readSTLString (uint32_t offset)
start_offset = readDWord(start_offset);// dereference the start offset
read(start_offset, capacity, (uint8_t *)temp);
}
-
+
temp[length] = 0;
string ret = temp;
delete temp;
diff --git a/library/DFProcess-linux.cpp b/library/DFProcess-linux.cpp
index 25dfa0d8c..164834543 100644
--- a/library/DFProcess-linux.cpp
+++ b/library/DFProcess-linux.cpp
@@ -23,7 +23,7 @@ distribution.
*/
#include "Internal.h"
#include "dfhack/DFProcess.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include
#include
@@ -44,7 +44,7 @@ class NormalProcess::Private
};
~Private(){};
Window* my_window;
- memory_info * my_descriptor;
+ VersionInfo * my_descriptor;
pid_t my_handle;
uint32_t my_pid;
string memFile;
@@ -53,10 +53,10 @@ class NormalProcess::Private
bool suspended;
bool identified;
Process * self;
- bool validate(char * exe_file, uint32_t pid, char * mem_file, vector & known_versions);
+ bool validate(char * exe_file, uint32_t pid, char * mem_file, vector & known_versions);
};
-NormalProcess::NormalProcess(uint32_t pid, vector< memory_info* >& known_versions)
+NormalProcess::NormalProcess(uint32_t pid, vector< VersionInfo* >& known_versions)
: d(new Private(this))
{
char dir_name [256];
@@ -66,16 +66,16 @@ NormalProcess::NormalProcess(uint32_t pid, vector< memory_info* >& known_version
char cmdline_name [256];
char target_name[1024];
int target_result;
-
+
d->identified = false;
d->my_descriptor = 0;
-
+
sprintf(dir_name,"/proc/%d/", pid);
sprintf(exe_link_name,"/proc/%d/exe", pid);
sprintf(mem_name,"/proc/%d/mem", pid);
sprintf(cwd_name,"/proc/%d/cwd", pid);
sprintf(cmdline_name,"/proc/%d/cmdline", pid);
-
+
// resolve /proc/PID/exe link
target_result = readlink(exe_link_name, target_name, sizeof(target_name)-1);
if (target_result == -1)
@@ -84,7 +84,7 @@ NormalProcess::NormalProcess(uint32_t pid, vector< memory_info* >& known_version
}
// make sure we have a null terminated string...
target_name[target_result] = 0;
-
+
// is this the regular linux DF?
if (strstr(target_name, "dwarfort.exe") != 0 || strstr(target_name,"Dwarf_Fortress") != 0)
{
@@ -108,24 +108,25 @@ bool NormalProcess::isIdentified()
return d->identified;
}
-bool NormalProcess::Private::validate(char * exe_file,uint32_t pid, char * memFile, vector & known_versions)
+bool NormalProcess::Private::validate(char * exe_file,uint32_t pid, char * memFile, vector & known_versions)
{
md5wrapper md5;
// get hash of the running DF process
string hash = md5.getHashFromFile(exe_file);
- vector::iterator it;
-
+ vector::iterator it;
+
// iterate over the list of memory locations
for ( it=known_versions.begin() ; it < known_versions.end(); it++ )
{
try
{
- if(hash == (*it)->getString("md5")) // are the md5 hashes the same?
+ //cout << hash << " ?= " << (*it)->getMD5() << endl;
+ if(hash == (*it)->getMD5()) // are the md5 hashes the same?
{
- memory_info * m = *it;
- if (memory_info::OS_LINUX == m->getOS())
+ VersionInfo * m = *it;
+ if (VersionInfo::OS_LINUX == m->getOS())
{
- memory_info *m2 = new memory_info(*m);
+ VersionInfo *m2 = new VersionInfo(*m);
my_descriptor = m2;
m2->setParentProcess(dynamic_cast( self ));
my_handle = my_pid = pid;
@@ -161,7 +162,7 @@ NormalProcess::~NormalProcess()
delete d;
}
-memory_info * NormalProcess::getDescriptor()
+VersionInfo * NormalProcess::getDescriptor()
{
return d->my_descriptor;
}
@@ -182,11 +183,11 @@ void NormalProcess::getMemRanges( vector & ranges )
{
char buffer[1024];
char permissions[5]; // r/-, w/-, x/-, p/s, 0
-
+
sprintf(buffer, "/proc/%lu/maps", d->my_pid);
FILE *mapFile = ::fopen(buffer, "r");
uint64_t offset, device1, device2, node;
-
+
while (fgets(buffer, 1024, mapFile))
{
t_memrange temp;
@@ -298,7 +299,7 @@ bool NormalProcess::attach()
}
}
d->suspended = true;
-
+
int proc_pid_mem = open(d->memFile.c_str(),O_RDONLY);
if(proc_pid_mem == -1)
{
@@ -310,7 +311,7 @@ bool NormalProcess::attach()
else
{
d->attached = true;
-
+
d->memFileHandle = proc_pid_mem;
return true; // we are attached
}
@@ -352,7 +353,7 @@ bool NormalProcess::detach()
void NormalProcess::read (const uint32_t offset, const uint32_t size, uint8_t *target)
{
if(size == 0) return;
-
+
ssize_t result;
result = pread(d->memFileHandle, target,size,offset);
if(result != size)
@@ -564,10 +565,10 @@ size_t NormalProcess::readSTLString (uint32_t offset, char * buffer, size_t bufc
const string NormalProcess::readSTLString (uint32_t offset)
{
_Rep_base header;
-
+
offset = readDWord(offset);
read(offset - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header);
-
+
// FIXME: use char* everywhere, avoid string
char * temp = new char[header._M_length+1];
read(offset,header._M_length+1,(uint8_t * )temp);
diff --git a/library/DFProcess-windows-SHM.cpp b/library/DFProcess-windows-SHM.cpp
index 5bb100e34..9742ceeca 100644
--- a/library/DFProcess-windows-SHM.cpp
+++ b/library/DFProcess-windows-SHM.cpp
@@ -23,7 +23,7 @@ distribution.
*/
#include "Internal.h"
#include "dfhack/DFProcess.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include "shms.h"
#include "mod-core.h"
@@ -48,7 +48,7 @@ class SHMProcess::Private
attachmentIdx = -1;
};
~Private(){};
- memory_info * memdescriptor;
+ VersionInfo * memdescriptor;
SHMProcess * self;
uint32_t process_ID;
char *shm_addr;
@@ -56,14 +56,14 @@ class SHMProcess::Private
HANDLE DFCLMutex;
HANDLE DFCLSuspendMutex;
int attachmentIdx;
-
+
bool attached;
bool locked;
bool identified;
bool useYield;
-
- bool validate(std::vector< memory_info* >& known_versions);
-
+
+ bool validate(std::vector< VersionInfo* >& known_versions);
+
bool Aux_Core_Attach(bool & versionOK, uint32_t & PID);
bool SetAndWait (uint32_t state);
bool GetLocks();
@@ -91,7 +91,7 @@ bool SHMProcess::Private::SetAndWait (uint32_t state)
uint32_t cnt = 0;
if(!attached) return false;
SHMCMD = state;
-
+
while (SHMCMD == state)
{
// yield the CPU, only on single-core CPUs
@@ -176,7 +176,7 @@ bool SHMProcess::Private::GetLocks()
DFSVMutex = 0;
return false;
}
-
+
for(int i = 0; i < SHM_MAX_CLIENTS; i++)
{
// open the client suspend locked
@@ -190,7 +190,7 @@ bool SHMProcess::Private::GetLocks()
}
// open the client lock, try to lock it
-
+
sprintf(name,"DFCLMutex-%d-%d",process_ID,i);
DFCLMutex = OpenMutex(SYNCHRONIZE,0,name);
if(DFCLMutex == 0)
@@ -226,7 +226,7 @@ bool SHMProcess::Private::GetLocks()
bool SHMProcess::Private::AreLocksOk()
{
// both locks are inited (we hold our lock)
- if(DFCLMutex != 0 && DFSVMutex != 0)
+ if(DFCLMutex != 0 && DFSVMutex != 0)
{
// try if CL mutex is free
switch (WaitForSingleObject(DFSVMutex,0))
@@ -241,7 +241,7 @@ bool SHMProcess::Private::AreLocksOk()
{
// mutex is held by DF
return true;
- }
+ }
default:
case WAIT_FAILED:
{
@@ -257,10 +257,10 @@ bool SHMProcess::Private::AreLocksOk()
/*
char svmutexname [256];
-
+
char clmutexname [256];
sprintf(clmutexname,"DFCLMutex-%d",PID);
-
+
// get server and client mutex
d->DFSVMutex = OpenMutex(SYNCHRONIZE,false, svmutexname);
if(d->DFSVMutex == 0)
@@ -274,7 +274,7 @@ bool SHMProcess::Private::AreLocksOk()
}
*/
-SHMProcess::SHMProcess(uint32_t PID, vector & known_versions)
+SHMProcess::SHMProcess(uint32_t PID, vector & known_versions)
: d(new Private())
{
d->process_ID = PID;
@@ -314,7 +314,7 @@ bool SHMProcess::isIdentified()
{
return d->identified;
}
-bool SHMProcess::Private::validate(vector & known_versions)
+bool SHMProcess::Private::validate(vector & known_versions)
{
// try to identify the DF version
IMAGE_NT_HEADERS32 pe_header;
@@ -324,11 +324,11 @@ bool SHMProcess::Private::validate(vector & known_versions)
HANDLE hProcess;
bool found = false;
identified = false;
- // open process, we only need the process open
+ // open process, we only need the process open
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, process_ID );
if (NULL == hProcess)
return false;
-
+
// try getting the first module of the process
if(EnumProcessModules(hProcess, &hmod, 1 * sizeof(HMODULE), &junk) == 0)
{
@@ -338,20 +338,20 @@ bool SHMProcess::Private::validate(vector & known_versions)
}
// got base ;)
uint32_t base = (uint32_t)hmod;
-
+
// read from this process
uint32_t pe_offset = self->readDWord(base+0x3C);
self->read(base + pe_offset , sizeof(pe_header), (uint8_t *)&pe_header);
self->read(base + pe_offset+ sizeof(pe_header), sizeof(sections) , (uint8_t *)§ions );
-
+
// iterate over the list of memory locations
- vector::iterator it;
+ vector::iterator it;
for ( it=known_versions.begin() ; it < known_versions.end(); it++ )
{
uint32_t pe_timestamp;
try
{
- pe_timestamp = (*it)->getHexValue("pe_timestamp");
+ pe_timestamp = (*it)->getPE();
}
catch(Error::MissingMemoryDefinition&)
{
@@ -359,7 +359,7 @@ bool SHMProcess::Private::validate(vector & known_versions)
}
if (pe_timestamp == pe_header.FileHeader.TimeDateStamp)
{
- memory_info *m = new memory_info(**it);
+ VersionInfo *m = new VersionInfo(**it);
m->RebaseAll(base);
memdescriptor = m;
m->setParentProcess(self);
@@ -385,7 +385,7 @@ SHMProcess::~SHMProcess()
delete d;
}
-memory_info * SHMProcess::getDescriptor()
+VersionInfo * SHMProcess::getDescriptor()
{
return d->memdescriptor;
}
@@ -397,30 +397,30 @@ int SHMProcess::getPID()
bool SHMProcess::getThreadIDs(vector & threads )
{
- HANDLE AllThreads = INVALID_HANDLE_VALUE;
+ HANDLE AllThreads = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;
-
- AllThreads = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
- if( AllThreads == INVALID_HANDLE_VALUE )
+
+ AllThreads = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
+ if( AllThreads == INVALID_HANDLE_VALUE )
{
- return false;
+ return false;
}
- te32.dwSize = sizeof(THREADENTRY32 );
-
- if( !Thread32First( AllThreads, &te32 ) )
+ te32.dwSize = sizeof(THREADENTRY32 );
+
+ if( !Thread32First( AllThreads, &te32 ) )
{
CloseHandle( AllThreads );
return false;
}
-
- do
- {
+
+ do
+ {
if( te32.th32OwnerProcessID == d->process_ID )
{
threads.push_back(te32.th32ThreadID);
}
- } while( Thread32Next(AllThreads, &te32 ) );
-
+ } while( Thread32Next(AllThreads, &te32 ) );
+
CloseHandle( AllThreads );
return true;
}
@@ -430,9 +430,9 @@ void SHMProcess::getMemRanges( vector & ranges )
{
// code here is taken from hexsearch by Silas Dunmore.
// As this IMHO isn't a 'sunstantial portion' of anything, I'm not including the MIT license here
-
+
// I'm faking this, because there's no way I'm using VirtualQuery
-
+
t_memrange temp;
uint32_t base = d->memdescriptor->getBase();
temp.start = base + 0x1000; // more fakery.
@@ -591,7 +591,7 @@ bool SHMProcess::attach()
return false; // we couldn't lock it
}
*/
-
+
/*
* Locate the segment.
*/
@@ -613,12 +613,12 @@ bool SHMProcess::attach()
{
CloseHandle(shmHandle);
//ReleaseMutex(d->DFCLMutex);
- d->FreeLocks();
+ d->FreeLocks();
return false; // we couldn't attach the mapping // FIXME: throw
}
// we close the handle right here - it's not needed anymore
CloseHandle(shmHandle);
-
+
d->attached = true;
if(!suspend())
{
@@ -653,7 +653,7 @@ bool SHMProcess::detach()
void SHMProcess::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
// normal read under 1MB
if(size <= SHM_BODY)
{
@@ -690,7 +690,7 @@ void SHMProcess::read (uint32_t src_address, uint32_t size, uint8_t *target_buff
uint8_t SHMProcess::readByte (const uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_BYTE);
@@ -700,7 +700,7 @@ uint8_t SHMProcess::readByte (const uint32_t offset)
void SHMProcess::readByte (const uint32_t offset, uint8_t &val )
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_BYTE);
@@ -710,7 +710,7 @@ void SHMProcess::readByte (const uint32_t offset, uint8_t &val )
uint16_t SHMProcess::readWord (const uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_WORD);
@@ -720,7 +720,7 @@ uint16_t SHMProcess::readWord (const uint32_t offset)
void SHMProcess::readWord (const uint32_t offset, uint16_t &val)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_WORD);
@@ -730,7 +730,7 @@ void SHMProcess::readWord (const uint32_t offset, uint16_t &val)
uint32_t SHMProcess::readDWord (const uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_DWORD);
@@ -739,7 +739,7 @@ uint32_t SHMProcess::readDWord (const uint32_t offset)
void SHMProcess::readDWord (const uint32_t offset, uint32_t &val)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_DWORD);
@@ -749,7 +749,7 @@ void SHMProcess::readDWord (const uint32_t offset, uint32_t &val)
float SHMProcess::readFloat (const uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_DWORD);
@@ -758,7 +758,7 @@ float SHMProcess::readFloat (const uint32_t offset)
void SHMProcess::readFloat (const uint32_t offset, float &val)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_DWORD);
@@ -767,7 +767,7 @@ void SHMProcess::readFloat (const uint32_t offset, float &val)
uint64_t SHMProcess::readQuad (const uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_QUAD);
@@ -776,7 +776,7 @@ uint64_t SHMProcess::readQuad (const uint32_t offset)
void SHMProcess::readQuad (const uint32_t offset, uint64_t &val)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_QUAD);
@@ -790,7 +790,7 @@ void SHMProcess::readQuad (const uint32_t offset, uint64_t &val)
void SHMProcess::writeQuad (uint32_t offset, uint64_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
D_SHMHDR->Qvalue = data;
full_barrier
@@ -801,7 +801,7 @@ void SHMProcess::writeQuad (uint32_t offset, uint64_t data)
void SHMProcess::writeDWord (uint32_t offset, uint32_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
full_barrier
@@ -812,7 +812,7 @@ void SHMProcess::writeDWord (uint32_t offset, uint32_t data)
void SHMProcess::writeWord (uint32_t offset, uint16_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
full_barrier
@@ -822,7 +822,7 @@ void SHMProcess::writeWord (uint32_t offset, uint16_t data)
void SHMProcess::writeByte (uint32_t offset, uint8_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
full_barrier
@@ -832,7 +832,7 @@ void SHMProcess::writeByte (uint32_t offset, uint8_t data)
void SHMProcess::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
// normal write under 1MB
if(size <= SHM_BODY)
{
@@ -870,7 +870,7 @@ void SHMProcess::write (uint32_t dst_address, uint32_t size, uint8_t *source_buf
const std::string SHMProcess::readCString (uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
std::string temp;
char temp_c[256];
int counter = 0;
@@ -889,7 +889,7 @@ const std::string SHMProcess::readCString (uint32_t offset)
const std::string SHMProcess::readSTLString(uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_STL_STRING);
@@ -899,7 +899,7 @@ const std::string SHMProcess::readSTLString(uint32_t offset)
size_t SHMProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_STL_STRING);
@@ -913,7 +913,7 @@ size_t SHMProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapa
void SHMProcess::writeSTLString(const uint32_t address, const std::string writeString)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
D_SHMHDR->address = address;
strncpy(D_SHMDATA(char),writeString.c_str(),writeString.length()+1); // length + 1 for the null terminator
full_barrier
@@ -933,13 +933,13 @@ string SHMProcess::readClassName (uint32_t vptr)
bool SHMProcess::getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT)
{
if(!d->locked) throw Error::MemoryAccessDenied();
-
+
modulelookup * payload = D_SHMDATA(modulelookup);
payload->version = version;
-
+
strncpy(payload->name,name,255);
payload->name[255] = 0;
-
+
if(!SetAndWait(CORE_ACQUIRE_MODULE))
{
return false; // FIXME: throw a fatal exception instead
@@ -962,7 +962,7 @@ char * SHMProcess::getSHMStart (void)
bool SHMProcess::Private::Aux_Core_Attach(bool & versionOK, uint32_t & PID)
{
if(!locked) throw Error::MemoryAccessDenied();
-
+
SHMDATA(coreattach)->cl_affinity = OS_getAffinity();
if(!SetAndWait(CORE_ATTACH)) return false;
/*
diff --git a/library/DFProcess-windows.cpp b/library/DFProcess-windows.cpp
index dad67b135..0b3d7959d 100644
--- a/library/DFProcess-windows.cpp
+++ b/library/DFProcess-windows.cpp
@@ -23,7 +23,7 @@ distribution.
*/
#include "Internal.h"
#include "dfhack/DFProcess.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
using namespace DFHack;
@@ -40,7 +40,7 @@ class NormalProcess::Private
suspended = false;
};
~Private(){};
- memory_info * my_descriptor;
+ VersionInfo * my_descriptor;
HANDLE my_handle;
HANDLE my_main_thread;
uint32_t my_pid;
@@ -48,16 +48,19 @@ class NormalProcess::Private
bool attached;
bool suspended;
bool identified;
+ uint32_t STLSTR_buf_off;
+ uint32_t STLSTR_size_off;
+ uint32_t STLSTR_cap_off;
};
-NormalProcess::NormalProcess(uint32_t pid, vector & known_versions)
+NormalProcess::NormalProcess(uint32_t pid, vector & known_versions)
: d(new Private())
{
HMODULE hmod = NULL;
DWORD junk;
HANDLE hProcess;
bool found = false;
-
+
IMAGE_NT_HEADERS32 pe_header;
IMAGE_SECTION_HEADER sections[16];
d->identified = false;
@@ -65,7 +68,7 @@ NormalProcess::NormalProcess(uint32_t pid, vector & known_versio
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid );
if (NULL == hProcess)
return;
-
+
// try getting the first module of the process
if(EnumProcessModules(hProcess, &hmod, 1 * sizeof(HMODULE), &junk) == 0)
{
@@ -73,10 +76,10 @@ NormalProcess::NormalProcess(uint32_t pid, vector & known_versio
// cout << "EnumProcessModules fail'd" << endl;
return; //if enumprocessModules fails, give up
}
-
+
// got base ;)
uint32_t base = (uint32_t)hmod;
-
+
// temporarily assign this to allow some checks
d->my_handle = hProcess;
d->my_main_thread = 0;
@@ -94,19 +97,19 @@ NormalProcess::NormalProcess(uint32_t pid, vector & known_versio
d->my_handle = 0;
return;
}
-
+
// see if there's a version entry that matches this process
- vector::iterator it;
+ vector::iterator it;
for ( it=known_versions.begin() ; it < known_versions.end(); it++ )
{
// filter by OS
- if(memory_info::OS_WINDOWS != (*it)->getOS())
+ if(VersionInfo::OS_WINDOWS != (*it)->getOS())
continue;
uint32_t pe_timestamp;
// filter by timestamp, skip entries without a timestamp
try
{
- pe_timestamp = (*it)->getHexValue("pe_timestamp");
+ pe_timestamp = (*it)->getPE();
}
catch(Error::MissingMemoryDefinition&)
{
@@ -114,13 +117,13 @@ NormalProcess::NormalProcess(uint32_t pid, vector & known_versio
}
if (pe_timestamp != pe_header.FileHeader.TimeDateStamp)
continue;
-
+
// all went well
{
printf("Match found! Using version %s.\n", (*it)->getVersion().c_str());
d->identified = true;
// give the process a data model and memory layout fixed for the base of first module
- memory_info *m = new memory_info(**it);
+ VersionInfo *m = new VersionInfo(**it);
m->RebaseAll(base);
// keep track of created memory_info object so we can destroy it later
d->my_descriptor = m;
@@ -129,12 +132,15 @@ NormalProcess::NormalProcess(uint32_t pid, vector & known_versio
d->my_pid = pid;
d->my_handle = hProcess;
d->identified = true;
-
+
// TODO: detect errors in thread enumeration
vector threads;
getThreadIDs( threads );
d->my_main_thread = OpenThread(THREAD_ALL_ACCESS, FALSE, (DWORD) threads[0]);
-
+ OffsetGroup * strGrp = m->getGroup("string")->getGroup("MSVC");
+ d->STLSTR_buf_off = strGrp->getOffset("buffer");
+ d->STLSTR_size_off = strGrp->getOffset("size");
+ d->STLSTR_cap_off = strGrp->getOffset("capacity");
found = true;
break; // break the iterator loop
}
@@ -167,7 +173,7 @@ NormalProcess::~NormalProcess()
delete d;
}
-memory_info * NormalProcess::getDescriptor()
+VersionInfo * NormalProcess::getDescriptor()
{
return d->my_descriptor;
}
@@ -257,30 +263,30 @@ bool NormalProcess::detach()
bool NormalProcess::getThreadIDs(vector & threads )
{
- HANDLE AllThreads = INVALID_HANDLE_VALUE;
+ HANDLE AllThreads = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;
-
- AllThreads = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
- if( AllThreads == INVALID_HANDLE_VALUE )
+
+ AllThreads = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
+ if( AllThreads == INVALID_HANDLE_VALUE )
{
- return false;
+ return false;
}
- te32.dwSize = sizeof(THREADENTRY32 );
-
- if( !Thread32First( AllThreads, &te32 ) )
+ te32.dwSize = sizeof(THREADENTRY32 );
+
+ if( !Thread32First( AllThreads, &te32 ) )
{
CloseHandle( AllThreads );
return false;
}
-
- do
- {
+
+ do
+ {
if( te32.th32OwnerProcessID == d->my_pid )
{
threads.push_back(te32.th32ThreadID);
}
- } while( Thread32Next(AllThreads, &te32 ) );
-
+ } while( Thread32Next(AllThreads, &te32 ) );
+
CloseHandle( AllThreads );
return true;
}
@@ -290,9 +296,9 @@ void NormalProcess::getMemRanges( vector & ranges )
{
// code here is taken from hexsearch by Silas Dunmore.
// As this IMHO isn't a 'sunstantial portion' of anything, I'm not including the MIT license here
-
+
// I'm faking this, because there's no way I'm using VirtualQuery
-
+
t_memrange temp;
uint32_t base = d->my_descriptor->getBase();
temp.start = base + 0x1000; // more fakery.
@@ -430,23 +436,11 @@ const string NormalProcess::readCString (const uint32_t offset)
size_t NormalProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
- /*
- MSVC++ string
- ptr allocator
- union
- {
- char[16] start;
- char * start_ptr
-}
-Uint32 length
-Uint32 capacity
-*/
- uint32_t start_offset = offset + 4;
- size_t length = readDWord(offset + 20);
-
- size_t capacity = readDWord(offset + 24);
+ uint32_t start_offset = offset + d->STLSTR_buf_off;
+ size_t length = readDWord(offset + d->STLSTR_size_off);
+ size_t capacity = readDWord(offset + d->STLSTR_cap_off);
size_t read_real = min(length, bufcapacity-1);// keep space for null termination
-
+
// read data from inside the string structure
if(capacity < 16)
{
@@ -457,29 +451,18 @@ Uint32 capacity
start_offset = readDWord(start_offset);// dereference the start offset
read(start_offset, read_real, (uint8_t *)buffer);
}
-
+
buffer[read_real] = 0;
return read_real;
}
const string NormalProcess::readSTLString (uint32_t offset)
{
- /*
- MSVC++ string
- ptr allocator
- union
- {
- char[16] start;
- char * start_ptr
- }
- Uint32 length
- Uint32 capacity
- */
- uint32_t start_offset = offset + 4;
- uint32_t length = readDWord(offset + 20);
- uint32_t capacity = readDWord(offset + 24);
+ uint32_t start_offset = offset + d->STLSTR_buf_off;
+ size_t length = readDWord(offset + d->STLSTR_size_off);
+ size_t capacity = readDWord(offset + d->STLSTR_cap_off);
char * temp = new char[capacity+1];
-
+
// read data from inside the string structure
if(capacity < 16)
{
@@ -490,7 +473,7 @@ const string NormalProcess::readSTLString (uint32_t offset)
start_offset = readDWord(start_offset);// dereference the start offset
read(start_offset, capacity, (uint8_t *)temp);
}
-
+
temp[length] = 0;
string ret = temp;
delete temp;
diff --git a/library/DFProcessEnumerator.cpp b/library/DFProcessEnumerator.cpp
index c060d2182..b790cb0dd 100644
--- a/library/DFProcessEnumerator.cpp
+++ b/library/DFProcessEnumerator.cpp
@@ -23,11 +23,11 @@ distribution.
*/
#include "Internal.h"
-#include "DFMemInfoManager.h"
+#include "dfhack/VersionInfoFactory.h"
#include "dfhack/DFProcessEnumerator.h"
#include "dfhack/DFProcess.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
using namespace DFHack;
@@ -39,7 +39,7 @@ class DFHack::ProcessEnumerator::Private
{
public:
Private(){};
- MemInfoManager *meminfo;
+ VersionInfoFactory *meminfo;
PROC_V Processes;
PID2PROC ProcMap;
Process *GetProcessObject(ProcessID ID);
@@ -119,20 +119,20 @@ Process * BadProcesses::operator[](uint32_t index)
//FIXME: wasteful
Process *ProcessEnumerator::Private::GetProcessObject(ProcessID ID)
{
-
- Process *p1 = new SHMProcess(ID.pid,meminfo->meminfo);
+
+ Process *p1 = new SHMProcess(ID.pid,meminfo->versions);
if(p1->isIdentified())
return p1;
else
delete p1;
-
- Process *p2 = new NormalProcess(ID.pid,meminfo->meminfo);
+
+ Process *p2 = new NormalProcess(ID.pid,meminfo->versions);
if(p2->isIdentified())
return p2;
else
delete p2;
#ifdef LINUX_BUILD
- Process *p3 = new WineProcess(ID.pid,meminfo->meminfo);
+ Process *p3 = new WineProcess(ID.pid,meminfo->versions);
if(p3->isIdentified())
return p3;
else
@@ -358,7 +358,7 @@ Process * ProcessEnumerator::operator[](uint32_t index)
ProcessEnumerator::ProcessEnumerator( string path_to_xml )
: d(new Private())
{
- d->meminfo = new MemInfoManager(path_to_xml);
+ d->meminfo = new VersionInfoFactory(path_to_xml);
}
void ProcessEnumerator::purge()
diff --git a/library/DFTypes_C.cpp b/library/DFTypes_C.cpp
index 9957ef0a1..9677ae9f1 100644
--- a/library/DFTypes_C.cpp
+++ b/library/DFTypes_C.cpp
@@ -57,6 +57,10 @@ int (*alloc_matgloss_buffer_callback)(t_matgloss*, uint32_t) = NULL;
int (*alloc_descriptor_buffer_callback)(t_descriptor_color*, uint32_t) = NULL;
int (*alloc_matgloss_other_buffer_callback)(t_matglossOther*, uint32_t) = NULL;
+int (*alloc_t_feature_buffer_callback)(t_feature*, uint32_t) = NULL;
+int (*alloc_t_hotkey_buffer_callback)(t_hotkey*, uint32_t) = NULL;
+int (*alloc_t_screen_buffer_callback)(t_screen*, uint32_t) = NULL;
+
int (*alloc_t_customWorkshop_buffer_callback)(t_customWorkshop*, uint32_t) = NULL;
int (*alloc_t_material_buffer_callback)(t_material*, uint32_t) = NULL;
diff --git a/library/VersionInfo.cpp b/library/VersionInfo.cpp
new file mode 100644
index 000000000..c0a3477af
--- /dev/null
+++ b/library/VersionInfo.cpp
@@ -0,0 +1,1051 @@
+/*
+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/VersionInfo.h"
+#include "dfhack/DFError.h"
+#include "dfhack/DFProcess.h"
+
+//Inital amount of space in levels vector (since we usually know the number, efficient!)
+#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 subs;
+ };
+ class indentr
+ {
+ public:
+ friend std::basic_ostream& operator <<(std::basic_ostream&, const indentr &);
+ indentr(int ns = 0, int size = 4)
+ {
+ numspaces = ns;
+ step = size;
+ }
+ void indent ()
+ {
+ numspaces += step;
+ if (numspaces < 0) numspaces = 0;
+ }
+ void unindent ()
+ {
+ numspaces -= step;
+ if (numspaces < 0) numspaces = 0;
+ }
+ int get ()
+ {
+ return numspaces;
+ }
+ void set (int ns)
+ {
+ numspaces = ns;
+ if (numspaces < 0) numspaces = 0;
+ }
+ private:
+ int step;
+ int numspaces;
+ };
+ std::basic_ostream& operator<< (std::basic_ostream& os, const indentr & idtr)
+ {
+ for(int i = 0; i < idtr.numspaces ;i++)
+ {
+ os << ' ';
+ }
+ return os;
+ }
+};
+
+/*
+ * Private data
+ */
+namespace DFHack
+{
+ typedef pair nullableUint32;
+ typedef map ::iterator uint32_Iter;
+ typedef pair nullableInt32;
+ typedef map ::iterator int32_Iter;
+ typedef pair nullableString;
+ typedef map ::iterator strings_Iter;
+ typedef map ::iterator groups_Iter;
+ class OffsetGroupPrivate
+ {
+ public:
+ map addresses;
+ map hexvals;
+ map offsets;
+ map strings;
+ map groups;
+ std::string name;
+ OffsetGroup * parent;
+ };
+}
+
+void OffsetGroup::createOffset(const string & key)
+{
+ OGd->offsets[key] = nullableInt32(false, 0);
+}
+
+void OffsetGroup::createAddress(const string & key)
+{
+ OGd->addresses[key] = nullableUint32(false, 0);
+}
+
+void OffsetGroup::createHexValue(const string & key)
+{
+ OGd->hexvals[key] = nullableUint32(false, 0);
+}
+
+void OffsetGroup::createString(const string & key)
+{
+ OGd->strings[key] = nullableString(false, std::string());
+}
+
+void OffsetGroup::setOffset (const string & key, const string & value)
+{
+ int32_Iter it = OGd->offsets.find(key);
+ if(it != OGd->offsets.end())
+ {
+ int32_t offset = strtol(value.c_str(), NULL, 16);
+ (*it).second.second = offset;
+ (*it).second.first = true;
+ }
+ else throw Error::MissingMemoryDefinition("offset", getFullName() + key);
+}
+
+
+void OffsetGroup::setAddress (const string & key, const string & value)
+{
+ uint32_Iter it = OGd->addresses.find(key);
+ if(it != OGd->addresses.end())
+ {
+ int32_t address = strtol(value.c_str(), NULL, 16);
+ (*it).second.second = address;
+ (*it).second.first = true;
+ }
+ else throw Error::MissingMemoryDefinition("address", getFullName() + key);
+}
+
+
+void OffsetGroup::setHexValue (const string & key, const string & value)
+{
+ uint32_Iter it = OGd->hexvals.find(key);
+ if(it != OGd->hexvals.end())
+ {
+ (*it).second.second = strtol(value.c_str(), NULL, 16);
+ (*it).second.first = true;
+ }
+ else throw Error::MissingMemoryDefinition("hexvalue", getFullName() + key);
+}
+
+
+void OffsetGroup::setString (const string & key, const string & value)
+{
+ strings_Iter it = OGd->strings.find(key);
+ if(it != OGd->strings.end())
+ {
+ (*it).second.second = value;
+ (*it).second.first = true;
+ }
+ else throw Error::MissingMemoryDefinition("string", getFullName() + key);
+}
+
+
+// Get named address
+uint32_t OffsetGroup::getAddress (const string & key)
+{
+ uint32_Iter iter = OGd->addresses.find(key);
+
+ if(iter != OGd->addresses.end())
+ {
+ if((*iter).second.first)
+ return (*iter).second.second;
+ throw Error::UnsetMemoryDefinition("address", getFullName() + key);
+ }
+ throw Error::MissingMemoryDefinition("address", getFullName() + key);
+}
+
+
+// Get named offset
+int32_t OffsetGroup::getOffset (const string & key)
+{
+ int32_Iter iter = OGd->offsets.find(key);
+ if(iter != OGd->offsets.end())
+ {
+ if((*iter).second.first)
+ return (*iter).second.second;
+ throw Error::UnsetMemoryDefinition("offset", getFullName() + key);
+ }
+ throw Error::MissingMemoryDefinition("offset", getFullName() + key);
+}
+
+
+// Get named numerical value
+uint32_t OffsetGroup::getHexValue (const string & key)
+{
+ uint32_Iter iter = OGd->hexvals.find(key);
+ if(iter != OGd->hexvals.end())
+ {
+ if((*iter).second.first)
+ return (*iter).second.second;
+ throw Error::UnsetMemoryDefinition("hexvalue", getFullName() + key);
+ }
+ throw Error::MissingMemoryDefinition("hexvalue", getFullName() + key);
+}
+
+// Get named string
+std::string OffsetGroup::getString (const string &key)
+{
+ strings_Iter iter = OGd->strings.find(key);
+ if(iter != OGd->strings.end())
+ {
+ if((*iter).second.first)
+ return (*iter).second.second;
+ throw Error::UnsetMemoryDefinition("string", getFullName() + key);
+ }
+ throw Error::MissingMemoryDefinition("string", getFullName() + key);
+}
+
+OffsetGroup * OffsetGroup::getGroup(const std::string &name)
+{
+ groups_Iter iter = OGd->groups.find(name);
+ if(iter != OGd->groups.end())
+ return ((*iter).second);
+ return 0;
+}
+
+OffsetGroup * OffsetGroup::createGroup(const std::string &name)
+{
+ OffsetGroup * ret = getGroup(name);
+ if(ret)
+ return ret;
+ ret = new OffsetGroup(name, this);
+ OGd->groups[name] = ret;
+ return ret;
+}
+
+void OffsetGroup::RebaseAddresses(int32_t offset)
+{
+ for(uint32_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++)
+ {
+ if(iter->second.first)
+ OGd->addresses[iter->first].second = iter->second.second + offset;
+ }
+ for(groups_Iter iter = OGd->groups.begin(); iter != OGd->groups.end(); iter++)
+ {
+ (*iter).second->RebaseAddresses(offset);
+ }
+}
+
+OffsetGroup::OffsetGroup()
+{
+ OGd = new OffsetGroupPrivate();
+ OGd->name = "";
+ OGd->parent = 0;
+}
+
+OffsetGroup::OffsetGroup(const std::string & name, OffsetGroup * parent)
+{
+ OGd = new OffsetGroupPrivate();
+ OGd->name = name;
+ OGd->parent = parent;
+}
+
+OffsetGroup::~OffsetGroup()
+{
+ for(groups_Iter it = OGd->groups.begin();it != OGd->groups.end();it++)
+ {
+ delete (*it).second;
+ }
+ OGd->groups.clear();
+ delete OGd;
+}
+
+std::string OffsetGroup::getName()
+{
+ return OGd->name;
+}
+
+OffsetGroup * OffsetGroup::getParent()
+{
+ return OGd->parent;
+}
+
+std::string OffsetGroup::getFullName()
+{
+ string temp, accum;
+ OffsetGroup * curr = this;
+ while(curr)
+ {
+ temp = curr->getName() + string("/") + accum;
+ accum = temp;
+ curr = curr->getParent();
+ }
+ return accum;
+}
+
+std::string OffsetGroup::PrintOffsets(int indentation)
+{
+ uint32_Iter iter;
+ ostringstream ss;
+ indentr i(indentation);
+ for(iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++)
+ {
+ ss << i << "";
+ if(!(*iter).second.first)
+ ss << " MISSING!";
+ ss << endl;
+ }
+ int32_Iter iter2;
+ for(iter2 = OGd->offsets.begin(); iter2 != OGd->offsets.end(); iter2++)
+ {
+ ss << i << "";
+ if(!(*iter2).second.first)
+ ss << " MISSING!";
+ ss << endl;
+ }
+ for(iter = OGd->hexvals.begin(); iter != OGd->hexvals.end(); iter++)
+ {
+ ss << i << "";
+ if(!(*iter).second.first)
+ ss << " MISSING!";
+ ss << endl;
+ }
+ strings_Iter iter3;
+ for(iter3 = OGd->strings.begin(); iter3 != OGd->strings.end(); iter3++)
+ {
+ ss << i << "";
+ if(!(*iter3).second.first)
+ ss << " MISSING!";
+ ss << endl;
+ }
+ groups_Iter iter4;
+ for(iter4 = OGd->groups.begin(); iter4 != OGd->groups.end(); iter4++)
+ {
+ ss << i << "" << endl;
+ i.indent();
+ ss <<(*iter4).second->PrintOffsets(i.get());
+ i.unindent();
+ ss << i << "" << endl;
+ }
+ return ss.str();
+}
+
+/*
+ * Private data
+ */
+namespace DFHack
+{
+ class VersionInfoPrivate
+ {
+ public:
+ vector professions;
+ vector jobs;
+ vector skills;
+ vector levels;
+ vector< vector > traits;
+ vector moods;
+ map labors;
+
+ // storage for class and multiclass
+ vector classes;
+
+ // cache for faster name lookup, indexed by classID
+ vector classnames;
+ // map between vptr and class id, needs further type id lookup for multi-classes, not inherited
+ map classIDs;
+
+ // index for the next added class
+ uint32_t classindex;
+
+ int32_t base;
+ Process * p; // the process this belongs to
+
+ string version;
+ VersionInfo::OSType OS;
+ std::string md5;
+ uint32_t PE_timestamp;
+ };
+}
+
+
+// normal constructor
+VersionInfo::VersionInfo()
+:d(new VersionInfoPrivate)
+{
+ d->base = 0;
+ d->p = 0;
+ d->classindex = 0;
+ d->levels.reserve(NUM_RESERVE_LVLS);
+ d->moods.reserve(NUM_RESERVE_MOODS);
+ d->md5 = "invalid";
+ d->PE_timestamp = 0;
+ OffsetGroup();
+}
+
+
+// copy constructor
+VersionInfo::VersionInfo(const VersionInfo &old)
+:d(new VersionInfoPrivate)
+{
+ copy(&old);
+}
+
+void OffsetGroup::copy(const OffsetGroup * old)
+{
+ OGd->addresses = old->OGd->addresses;
+ OGd->offsets = old->OGd->offsets;
+ OGd->hexvals = old->OGd->hexvals;
+ OGd->strings = old->OGd->strings;
+ for(groups_Iter it = old->OGd->groups.begin(); it != old->OGd->groups.end(); it++)
+ {
+ OffsetGroup * ogn = new OffsetGroup((*it).first, this);
+ ogn->copy((*it).second);
+ OGd->groups[(*it).first] = ogn;
+ }
+}
+
+void VersionInfo::copy(const VersionInfo * old)
+{
+ d->version = old->d->version;
+ d->OS = old->d->OS;
+ d->md5 = old->d->md5;
+ d->PE_timestamp = old->d->PE_timestamp;
+ 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;
+ OffsetGroup::copy(reinterpret_cast(old));
+}
+
+void VersionInfo::setParentProcess(Process * _p)
+{
+ d->p = _p;
+}
+
+
+// destructor
+VersionInfo::~VersionInfo()
+{
+ // delete the vtables
+ for(uint32_t i = 0; i < d->classes.size();i++)
+ {
+ delete d->classes[i];
+ }
+ // delete our data
+ delete d;
+}
+
+
+void VersionInfo::setVersion(const char * v)
+{
+ d->version = v;
+}
+
+
+void VersionInfo::setVersion(const string &v)
+{
+ d->version = v;
+}
+
+
+string VersionInfo::getVersion()
+{
+ return d->version;
+}
+
+void VersionInfo::setMD5(const string &v)
+{
+ d->md5 = v;
+}
+
+string VersionInfo::getMD5()
+{
+ return d->md5;
+}
+
+void VersionInfo::setPE(uint32_t v)
+{
+ d->PE_timestamp = v;
+}
+
+uint32_t VersionInfo::getPE()
+{
+ return d->PE_timestamp;
+}
+
+void VersionInfo::setOS(const char *os)
+{
+ string oss = os;
+ if(oss == "windows")
+ d->OS = OS_WINDOWS;
+ else if(oss == "linux")
+ d->OS = OS_LINUX;
+ else if(oss == "apple")
+ d->OS = OS_APPLE;
+ else
+ d->OS = OS_BAD;
+}
+
+
+void VersionInfo::setOS(const string &os)
+{
+ if(os == "windows")
+ d->OS = OS_WINDOWS;
+ else if(os == "linux")
+ d->OS = OS_LINUX;
+ else if(os == "apple")
+ d->OS = OS_APPLE;
+ else
+ d->OS = OS_BAD;
+}
+
+
+void VersionInfo::setOS(OSType os)
+{
+ if(os >= OS_WINDOWS && os < OS_BAD)
+ {
+ d->OS = os;
+ return;
+ }
+ d->OS = OS_BAD;
+}
+
+
+VersionInfo::OSType VersionInfo::getOS() const
+{
+ return d->OS;
+}
+
+uint32_t VersionInfo::getBase () const
+{
+ return d->base;
+}
+
+
+void VersionInfo::setBase (const string &s)
+{
+ d->base = strtol(s.c_str(), NULL, 16);
+}
+
+
+void VersionInfo::setBase (const uint32_t b)
+{
+ d->base = b;
+}
+
+
+void VersionInfo::setLabor(const string & key, const string & value)
+{
+ uint32_t keyInt = strtol(key.c_str(), NULL, 10);
+ d->labors[keyInt] = value;
+}
+
+
+void VersionInfo::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 VersionInfo::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 VersionInfo::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 VersionInfo::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 VersionInfo::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 VersionInfo::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 * VersionInfo::setClass (const char * name, uint32_t vtable, uint32_t typeoffset)
+{
+ if(name == 0)
+ return 0;
+ for (uint32_t i=0; iclasses.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 VersionInfo::setClassChild (t_class * parent, const char * name, const char * type)
+{
+ vector & vec = parent->subs;
+ for (uint32_t i=0; iclassname == 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 VersionInfo::resolveObjectToClassID(const uint32_t address, int32_t & classid)
+{
+ uint32_t vtable = d->p->readDWord(address);
+ // try to find the vtable in our cache
+ map::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 & 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 VersionInfo::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 VersionInfo::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 VersionInfo::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 * VersionInfo::getClassIDMapping()
+{
+ return &d->classnames;
+}
+
+
+// change base of all addresses
+void VersionInfo::RebaseAddresses(const int32_t new_base)
+{
+ OffsetGroup::RebaseAddresses(- (int32_t)d->base + new_base);
+}
+
+
+// change base of all addresses *and* vtable entries
+void VersionInfo::RebaseAll(int32_t new_base)
+{
+ RebaseAddresses(new_base);
+ int32_t rebase = - (int32_t)d->base + new_base;
+ RebaseVTable(rebase);
+}
+
+
+// change all vtable entries by offset
+void VersionInfo::RebaseVTable(int32_t offset)
+{
+ vector::iterator iter;
+ for(iter = d->classes.begin(); iter != d->classes.end(); iter++)
+ {
+ (*iter)->vtable += offset;
+ }
+}
+
+
+// Get Profession
+string VersionInfo::getProfession (const uint32_t key) const
+{
+ if(d->professions.size() > key)
+ {
+ return d->professions[key];
+ }
+ throw Error::MissingMemoryDefinition("profession", key);
+}
+
+
+// Get Job
+string VersionInfo::getJob (const uint32_t key) const
+{
+ if(d->jobs.size() > key)
+
+ {
+ return d->jobs[key];
+ }
+ throw Error::MissingMemoryDefinition("job", key);
+}
+
+
+string VersionInfo::getSkill (const uint32_t key) const
+{
+ if(d->skills.size() > key)
+ {
+ return d->skills[key];
+ }
+ throw Error::MissingMemoryDefinition("skill", key);
+}
+
+
+DFHack::t_level VersionInfo::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 VersionInfo::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 VersionInfo::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 > const& VersionInfo::getAllTraits()
+{
+ return d->traits;
+}
+
+std:: map const& VersionInfo::getAllLabours()
+{
+ return d->labors;
+}
+
+string VersionInfo::getLabor (const uint32_t laborIdx)
+{
+ if(d->labors.count(laborIdx))
+ {
+ return d->labors[laborIdx];
+ }
+ throw Error::MissingMemoryDefinition("labor", laborIdx);
+}
+
+
+std::string VersionInfo::getMood(const uint32_t moodID)
+{
+ if(d->moods.size() > moodID)
+ {
+ return d->moods[moodID];
+ }
+ throw Error::MissingMemoryDefinition("Mood", moodID);
+}
+
+std::string VersionInfo::PrintOffsets()
+{
+ ostringstream ss;
+ indentr i;
+ ss << i << "" << endl;
+ i.indent();
+ switch (getOS())
+ {
+ case OS_LINUX:
+ ss << i << "" << endl;
+ break;
+ case OS_WINDOWS:
+ ss << i << "" << endl;
+ ss << i << "" << endl;
+ break;
+ default:
+ ss << i << " UNKNOWN" << endl;
+ }
+ ss << i << "" << endl;
+ i.indent();
+ ss << OffsetGroup::PrintOffsets(i.get());
+ i.unindent();
+ ss << i << "" << endl;
+ i.unindent();
+ ss << i << "" << endl;
+ ss << endl;
+ return ss.str();
+}
\ No newline at end of file
diff --git a/library/VersionInfoFactory.cpp b/library/VersionInfoFactory.cpp
new file mode 100644
index 000000000..83102648e
--- /dev/null
+++ b/library/VersionInfoFactory.cpp
@@ -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
+
+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 , look at the children
+ pEntry = parent->FirstChildElement();
+ if(!pEntry)
+ return;
+
+ OffsetGroup * currentGroup = reinterpret_cast (target);
+ breadcrumbs.push_back(groupPair(pEntry,currentGroup));
+ }
+
+ // work variables
+ OffsetGroup * currentGroup = 0;
+ TiXmlElement * currentElem = 0;
+ //cerr << ""<< 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 << "" << 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 << "" << 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 << ""<< 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 map_pNamedEntries;
+ vector 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;
+}
diff --git a/library/include/DFHack.h b/library/include/DFHack.h
index 3ccaf0b83..95f39729a 100644
--- a/library/include/DFHack.h
+++ b/library/include/DFHack.h
@@ -17,7 +17,7 @@
#include "dfhack/DFError.h"
#include "dfhack/DFContextManager.h"
#include "dfhack/DFContext.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFTypes.h"
@@ -32,6 +32,7 @@
#include "dfhack/modules/Items.h"
#include "dfhack/modules/Vegetation.h"
#include "dfhack/modules/Maps.h"
+#include "dfhack/modules/Gui.h"
/*
* This is a header full of ugly, volatile things.
diff --git a/library/include/dfhack-c/DFTypes_C.h b/library/include/dfhack-c/DFTypes_C.h
index 112e195d4..49bd54dc9 100644
--- a/library/include/dfhack-c/DFTypes_C.h
+++ b/library/include/dfhack-c/DFTypes_C.h
@@ -29,6 +29,7 @@ distribution.
#include "dfhack/DFTypes.h"
#include "dfhack/modules/Maps.h"
#include "dfhack/modules/Materials.h"
+#include "dfhack/modules/Position.h"
#include "dfhack/DFTileTypes.h"
#ifdef __cplusplus
@@ -49,6 +50,10 @@ DFHACK_EXPORT extern int (*alloc_matgloss_buffer_callback)(t_matgloss*, uint32_t
DFHACK_EXPORT extern int (*alloc_descriptor_buffer_callback)(t_descriptor_color*, uint32_t);
DFHACK_EXPORT extern int (*alloc_matgloss_other_buffer_callback)(t_matglossOther*, uint32_t);
+DFHACK_EXPORT extern int (*alloc_t_feature_buffer_callback)(t_feature*, uint32_t);
+DFHACK_EXPORT extern int (*alloc_t_hotkey_buffer_callback)(t_hotkey*, uint32_t);
+DFHACK_EXPORT extern int (*alloc_t_screen_buffer_callback)(t_screen*, uint32_t);
+
struct t_customWorkshop
{
uint32_t index;
diff --git a/library/include/dfhack-c/README_C.txt b/library/include/dfhack-c/README_C.rst
similarity index 73%
rename from library/include/dfhack-c/README_C.txt
rename to library/include/dfhack-c/README_C.rst
index 3b785cf54..7a5b69a54 100644
--- a/library/include/dfhack-c/README_C.txt
+++ b/library/include/dfhack-c/README_C.rst
@@ -54,17 +54,36 @@ Buffer Callback List
- alloc_ubyte_buffer_callback(uint8_t*, uint32_t)
- alloc_ushort_buffer_callback(uint16_t*, uint32_t)
- alloc_uint_buffer_callback(uint32_t*, uint32_t)
+- alloc_char_buffer_callback(char* uint32_t)
- alloc_matgloss_buffer_callback(t_matgloss*, uint32_t)
- alloc_descriptor_buffer_callback(t_descriptor_color*, uint32_t)
- alloc_matgloss_other_buffer_callback(t_matglossOther*, uint32_t)
- alloc_vein_buffer_callback(t_vein*, uint32_t)
+- alloc_t_feature_buffer_callback(t_feature*, uint32_t)
+- alloc_t_hotkey_buffer_callback(t_hotkey*, uint32_t)
+- alloc_t_screen_buffer_callback(t_screen*, uint32_t)
- alloc_frozenliquidvein_buffer_callback(t_frozenliquidvein*, uint32_t)
- alloc_spattervein_buffer_callback(t_spattervein*, uint32_t)
Templates Make My Life Harder
-------------------------------
-Three dfhack structures (t_colormodifier, t_creaturecaste, and t_creaturetype) contain vectors, which (obviously) don't work in C. Therefore, these structures have C versions that replace the vector with a buffer and length, but are otherwise identical to their C++ counterparts. For each structure, there are three associated callbacks. One initializes an empty instance of the structure, one initializes an instance with values passed in, and one allocates a buffer in the same manner as the other allocators.
-
+Several dfhack structures contain vectors, which (obviously) don't work in C. Therefore, these structures have C versions that replace the vector with a buffer and length, but are otherwise identical to their C++ counterparts. For each structure, there are three associated callbacks. One initializes an empty instance of the structure (*alloc_empty_colormodifier_callback*, for instance), one initializes an instance with values passed in (*alloc_colormodifier_callback*), and one allocates a buffer in the same manner as the other allocators (*alloc_colormodifier_buffer_callback*).
+
+The replaced structures and their callbacks are as follows.
+
+- c_colormodifier
+ * alloc_empty_colormodifier_callback(c_colormodifier*)
+ * alloc_colormodifier_callback(c_colormodifier*, const char*, uint32_t)
+ * alloc_colormodifier_buffer_callback(c_colormodifier*, uint32_t)
+- c_creaturecaste
+ * alloc_empty_creaturecaste_callback(c_creaturecaste*)
+ * alloc_creaturecaste_callback(c_creaturecaste*, const char*, const char*, const char*, const char*, uint32_t, uint32_t)
+ * alloc_creaturecaste_buffer_callback(c_creaturecaste*, uint32_t)
+- c_creaturetype
+ * alloc_empty_creaturetype_callback(c_creaturetype*)
+ * alloc_creaturetype_callback(c_creaturetype*, const char*, uint32_t, uint32_t, uint8_t, uint16_t, uint16_t, uint16_t)
+ * alloc_creaturetype_buffer_callback(c_creaturetype*, uint32_t)
+
A Small Callback Example In Python
-------------------------------------
The Python bindings for dfhack implement the unsigned integer allocator callback like this:
diff --git a/library/include/dfhack-c/modules/Gui_C.h b/library/include/dfhack-c/modules/Gui_C.h
index 2373d458d..8cc737f78 100644
--- a/library/include/dfhack-c/modules/Gui_C.h
+++ b/library/include/dfhack-c/modules/Gui_C.h
@@ -38,6 +38,7 @@ DFHACK_EXPORT int Gui_Finish(DFHackObject* gui);
DFHACK_EXPORT int Gui_ReadPauseState(DFHackObject* gui);
DFHACK_EXPORT int Gui_ReadViewScreen(DFHackObject* gui, t_viewscreen* viewscreen);
+DFHACK_EXPORT int Gui_ReadMenuState(DFHackObject* gui, uint32_t* menuState);
#ifdef __cplusplus
}
diff --git a/library/include/dfhack-c/modules/Maps_C.h b/library/include/dfhack-c/modules/Maps_C.h
index d1bad823e..fdbfdf1be 100644
--- a/library/include/dfhack-c/modules/Maps_C.h
+++ b/library/include/dfhack-c/modules/Maps_C.h
@@ -36,6 +36,8 @@ extern "C" {
DFHACK_EXPORT int Maps_Start(DFHackObject* maps);
DFHACK_EXPORT int Maps_Finish(DFHackObject* maps);
+DFHACK_EXPORT t_feature* Maps_ReadGlobalFeatures(DFHackObject* maps);
+
DFHACK_EXPORT void Maps_getSize(DFHackObject* maps, uint32_t* x, uint32_t* y, uint32_t* z);
DFHACK_EXPORT int Maps_isValidBlock(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z);
diff --git a/library/include/dfhack-c/modules/Materials_C.h b/library/include/dfhack-c/modules/Materials_C.h
index 888978a50..82f426ca7 100644
--- a/library/include/dfhack-c/modules/Materials_C.h
+++ b/library/include/dfhack-c/modules/Materials_C.h
@@ -44,6 +44,7 @@ DFHACK_EXPORT int Materials_ReadOthers(DFHackObject* mat);
DFHACK_EXPORT void Materials_ReadAllMaterials(DFHackObject* mat);
+DFHACK_EXPORT const char* Materials_getType(DFHackObject* mat, t_material* material);
DFHACK_EXPORT const char* Materials_getDescription(DFHackObject* mat, t_material* material);
DFHACK_EXPORT int Materials_getInorganicSize(DFHackObject* mat);
diff --git a/library/include/dfhack-c/modules/Position_C.h b/library/include/dfhack-c/modules/Position_C.h
index 665e400bf..2b60fa2e2 100644
--- a/library/include/dfhack-c/modules/Position_C.h
+++ b/library/include/dfhack-c/modules/Position_C.h
@@ -38,8 +38,12 @@ DFHACK_EXPORT int Position_setViewCoords(DFHackObject* pos, const int32_t x, con
DFHACK_EXPORT int Position_getCursorCoords(DFHackObject* pos, int32_t* x, int32_t* y, int32_t* z);
DFHACK_EXPORT int Position_setCursorCoords(DFHackObject* pos, const int32_t x, const int32_t y, const int32_t z);
+DFHACK_EXPORT t_hotkey* Position_ReadHotkeys(DFHackObject* pos);
+
DFHACK_EXPORT int Position_getWindowSize(DFHackObject* pos, int32_t* width, int32_t* height);
+DFHACK_EXPORT t_screen* Position_getScreenTiles(DFHackObject* pos, int32_t width, int32_t height);
+
#ifdef __cplusplus
}
#endif
diff --git a/library/include/dfhack-c/modules/World_C.h b/library/include/dfhack-c/modules/World_C.h
index f6261a738..c4348b5e9 100644
--- a/library/include/dfhack-c/modules/World_C.h
+++ b/library/include/dfhack-c/modules/World_C.h
@@ -40,6 +40,9 @@ DFHACK_EXPORT int World_ReadCurrentYear(DFHackObject* world, uint32_t* year);
DFHACK_EXPORT int World_ReadCurrentMonth(DFHackObject* world, uint32_t* month);
DFHACK_EXPORT int World_ReadCurrentDay(DFHackObject* world, uint32_t* day);
+DFHACK_EXPORT int World_ReadCurrentWeather(DFHackObject* world, uint8_t* weather);
+DFHACK_EXPORT int World_WriteCurrentWeather(DFHackObject* world, uint8_t weather);
+
#ifdef __cplusplus
}
#endif
diff --git a/library/include/dfhack/DFContext.h b/library/include/dfhack/DFContext.h
index 9c092cc38..3d8a0c150 100644
--- a/library/include/dfhack/DFContext.h
+++ b/library/include/dfhack/DFContext.h
@@ -40,7 +40,7 @@ namespace DFHack
class Vegetation;
class Buildings;
class Constructions;
- class memory_info;
+ class VersionInfo;
class DFContextShared;
class WindowIO;
class Process;
@@ -71,7 +71,7 @@ namespace DFHack
/// forces resume on Windows. This can be a bad thing with multiple tools running!
bool ForceResume();
- memory_info *getMemoryInfo();
+ VersionInfo *getMemoryInfo();
Process* getProcess();
void ReadRaw (const uint32_t offset, const uint32_t size, uint8_t *target);
diff --git a/library/include/dfhack/DFError.h b/library/include/dfhack/DFError.h
index 79823a9fa..fcb80f724 100644
--- a/library/include/dfhack/DFError.h
+++ b/library/include/dfhack/DFError.h
@@ -34,7 +34,12 @@ namespace DFHack
{
namespace Error
{
- class DFHACK_EXPORT NoProcess : public std::exception
+ /*
+ * our wrapper for the C++ exception. used to differentiate
+ * the whole array of DFHack exceptions from the rest
+ */
+ class DFHACK_EXPORT All : public std::exception{};
+ class DFHACK_EXPORT NoProcess : public All
{
public:
virtual const char* what() const throw()
@@ -43,7 +48,7 @@ namespace DFHack
}
};
- class DFHACK_EXPORT CantAttach : public std::exception
+ class DFHACK_EXPORT CantAttach : public All
{
public:
virtual const char* what() const throw()
@@ -52,7 +57,7 @@ namespace DFHack
}
};
- class DFHACK_EXPORT NoMapLoaded : public std::exception
+ class DFHACK_EXPORT NoMapLoaded : public All
{
public:
virtual const char* what() const throw()
@@ -61,7 +66,7 @@ namespace DFHack
}
};
- class DFHACK_EXPORT BadMapDimensions : public std::exception
+ class DFHACK_EXPORT BadMapDimensions : public All
{
public:
BadMapDimensions(uint32_t& _x, uint32_t& _y) : x(_x), y(_y) {}
@@ -75,13 +80,13 @@ namespace DFHack
};
// a call to DFHack::mem_info::get* failed
- class DFHACK_EXPORT MissingMemoryDefinition : public std::exception
+ class DFHACK_EXPORT MissingMemoryDefinition : public All
{
public:
- MissingMemoryDefinition(const char* _type, const char* _key) : type(_type), key(_key)
+ MissingMemoryDefinition(const char* _type, const std::string _key) : type(_type), key(_key)
{
std::stringstream s;
- s << "memory definition missing: type " << type << " key " << key;
+ s << "memory object not declared: type=" << type << " key=" << key;
full = s.str();
}
// Used by functios using integer keys, such as getTrait
@@ -92,24 +97,44 @@ namespace DFHack
key = s1.str();
std::stringstream s;
- s << "memory definition missing: type " << type << " key " << key;
+ s << "memory object not declared: type=" << type << " key=" << key;
full = s.str();
}
virtual ~MissingMemoryDefinition() throw(){};
- // (perhaps it should be an enum, but this is intended for easy printing/logging)
- // type can be any of the following:
- //
- // address
- // offset
- // hexvalue
- // string
- // profession
- // job
- // skill
- // trait
- // traitname
- // labor
+ std::string full;
+ const std::string type;
+ std::string key;
+
+ virtual const char* what() const throw()
+ {
+ return full.c_str();
+ }
+ };
+
+ // a call to DFHack::mem_info::get* failed
+ class DFHACK_EXPORT UnsetMemoryDefinition : public All
+ {
+ public:
+ UnsetMemoryDefinition(const char* _type, const std::string _key) : type(_type), key(_key)
+ {
+ std::stringstream s;
+ s << "memory object not set: type " << type << " key " << key;
+ full = s.str();
+ }
+ // Used by functios using integer keys, such as getTrait
+ UnsetMemoryDefinition(const char* _type, uint32_t _key) : type(_type)
+ {
+ std::stringstream s1;
+ s1 << _key;
+ key = s1.str();
+
+ std::stringstream s;
+ s << "memory object not set: type " << type << " key " << key;
+ full = s.str();
+ }
+ virtual ~UnsetMemoryDefinition() throw(){};
+
std::string full;
const std::string type;
std::string key;
@@ -121,7 +146,7 @@ namespace DFHack
};
// Syntax errors and whatnot, the xml cant be read
- class DFHACK_EXPORT MemoryXmlParse : public std::exception
+ class DFHACK_EXPORT MemoryXmlParse : public All
{
public:
MemoryXmlParse(const char* _desc, int _id, int _row, int _col)
@@ -147,7 +172,7 @@ namespace DFHack
}
};
- class DFHACK_EXPORT MemoryXmlBadAttribute : public std::exception
+ class DFHACK_EXPORT MemoryXmlBadAttribute : public All
{
public:
MemoryXmlBadAttribute(const char* _attr) : attr(_attr)
@@ -167,7 +192,7 @@ namespace DFHack
}
};
- class DFHACK_EXPORT MemoryXmlNoRoot : public std::exception
+ class DFHACK_EXPORT MemoryXmlNoRoot : public All
{
public:
MemoryXmlNoRoot() {}
@@ -180,7 +205,7 @@ namespace DFHack
}
};
- class DFHACK_EXPORT MemoryXmlNoDFExtractor : public std::exception
+ class DFHACK_EXPORT MemoryXmlNoDFExtractor : public All
{
public:
MemoryXmlNoDFExtractor(const char* _name) : name(_name)
@@ -200,7 +225,7 @@ namespace DFHack
}
};
- class DFHACK_EXPORT MemoryXmlUnderspecifiedEntry : public std::exception
+ class DFHACK_EXPORT MemoryXmlUnderspecifiedEntry : public All
{
public:
MemoryXmlUnderspecifiedEntry(const char * _where) : where(_where)
@@ -218,7 +243,7 @@ namespace DFHack
}
};
- class DFHACK_EXPORT MemoryXmlUnknownType : public std::exception
+ class DFHACK_EXPORT MemoryXmlUnknownType : public All
{
public:
MemoryXmlUnknownType(const char* _type) : type(_type)
@@ -238,7 +263,7 @@ namespace DFHack
}
};
- class DFHACK_EXPORT SHMServerDisappeared : public std::exception
+ class DFHACK_EXPORT SHMServerDisappeared : public All
{
public:
SHMServerDisappeared(){}
@@ -248,7 +273,7 @@ namespace DFHack
return "The server process has disappeared";
}
};
- class DFHACK_EXPORT SHMLockingError : public std::exception
+ class DFHACK_EXPORT SHMLockingError : public All
{
public:
SHMLockingError(const char* _type) : type(_type)
@@ -267,7 +292,7 @@ namespace DFHack
return full.c_str();
}
};
- class DFHACK_EXPORT MemoryAccessDenied : public std::exception
+ class DFHACK_EXPORT MemoryAccessDenied : public All
{
public:
MemoryAccessDenied() {}
@@ -277,7 +302,7 @@ namespace DFHack
return "SHM ACCESS DENIED";
}
};
- class DFHACK_EXPORT SHMVersionMismatch : public std::exception
+ class DFHACK_EXPORT SHMVersionMismatch : public All
{
public:
SHMVersionMismatch() {}
@@ -287,7 +312,7 @@ namespace DFHack
return "SHM VERSION MISMATCH";
}
};
- class DFHACK_EXPORT SHMAttachFailure : public std::exception
+ class DFHACK_EXPORT SHMAttachFailure : public All
{
public:
SHMAttachFailure() {}
@@ -297,7 +322,7 @@ namespace DFHack
return "SHM ATTACH FAILURE";
}
};
- class DFHACK_EXPORT ModuleNotInitialized : public std::exception
+ class DFHACK_EXPORT ModuleNotInitialized : public All
{
public:
ModuleNotInitialized() {}
diff --git a/library/include/dfhack/DFMiscUtils.h b/library/include/dfhack/DFMiscUtils.h
index 04676a769..7082bbdd4 100644
--- a/library/include/dfhack/DFMiscUtils.h
+++ b/library/include/dfhack/DFMiscUtils.h
@@ -12,7 +12,7 @@
using namespace std;
#include
-#include
+#include
#include
void DumpObjStr0Vector (const char * name, DFHack::Process *p, uint32_t addr)
@@ -81,7 +81,7 @@ void hexdump (DFHack::Context *DF, uint32_t address, uint32_t length)
void interleave_hex (DFHack::Context* DF, vector < uint32_t > & addresses, uint32_t length)
{
vector bufs;
-
+
for(uint32_t counter = 0; counter < addresses.size(); counter ++)
{
char * buf = new char[length * 16];
@@ -97,7 +97,7 @@ void interleave_hex (DFHack::Context* DF, vector < uint32_t > & addresses, uint3
cout << "0x" << hex << setw(9) << addresses[obj] << " ";
}
cout << endl;
-
+
for(uint32_t offs = 0 ; offs < length * 16; offs += 4)
{
if((!(offs % 16)) && offs != 0)
@@ -130,7 +130,7 @@ template
void print_bits ( T val, std::ostream& out )
{
T n_bits = sizeof ( val ) * CHAR_BIT;
-
+
for ( unsigned i = 0; i < n_bits; ++i ) {
out<< !!( val & 1 ) << " ";
val >>= 1;
diff --git a/library/include/dfhack/DFProcess.h b/library/include/dfhack/DFProcess.h
index 25ac51997..282e1b95f 100644
--- a/library/include/dfhack/DFProcess.h
+++ b/library/include/dfhack/DFProcess.h
@@ -31,7 +31,7 @@ distribution.
namespace DFHack
{
- class memory_info;
+ class VersionInfo;
class Process;
class Window;
@@ -160,7 +160,7 @@ namespace DFHack
virtual void getMemRanges(std::vector & ranges ) = 0;
/// get the flattened Memory.xml entry of this process
- virtual memory_info *getDescriptor() = 0;
+ virtual VersionInfo *getDescriptor() = 0;
/// get the DF Process ID
virtual int getPID() = 0;
/// get module index by name and version. bool 1 = error
@@ -182,7 +182,7 @@ namespace DFHack
private:
Private * const d;
public:
- NormalProcess(uint32_t pid, std::vector & known_versions);
+ NormalProcess(uint32_t pid, std::vector & known_versions);
~NormalProcess();
bool attach();
bool detach();
@@ -228,7 +228,7 @@ namespace DFHack
bool getThreadIDs(std::vector & threads );
void getMemRanges(std::vector & ranges );
- memory_info *getDescriptor();
+ VersionInfo *getDescriptor();
int getPID();
// get module index by name and version. bool 1 = error
bool getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT) { OUTPUT=0; return false;};
@@ -246,7 +246,7 @@ namespace DFHack
Private * const d;
public:
- SHMProcess(uint32_t PID, std::vector & known_versions);
+ SHMProcess(uint32_t PID, std::vector & known_versions);
~SHMProcess();
// Set up stuff so we can read memory
bool attach();
@@ -293,7 +293,7 @@ namespace DFHack
bool getThreadIDs(std::vector & threads );
void getMemRanges(std::vector & ranges );
- memory_info *getDescriptor();
+ VersionInfo *getDescriptor();
int getPID();
// get module index by name and version. bool 1 = error
bool getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT);
@@ -311,7 +311,7 @@ namespace DFHack
Private * const d;
public:
- WineProcess(uint32_t pid, std::vector & known_versions);
+ WineProcess(uint32_t pid, std::vector & known_versions);
~WineProcess();
bool attach();
bool detach();
@@ -357,7 +357,7 @@ namespace DFHack
bool getThreadIDs(std::vector & threads );
void getMemRanges(std::vector & ranges );
- memory_info *getDescriptor();
+ VersionInfo *getDescriptor();
int getPID();
// get module index by name and version. bool 1 = error
bool getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT) {OUTPUT=0; return false;};
diff --git a/library/include/dfhack/DFProcessEnumerator.h b/library/include/dfhack/DFProcessEnumerator.h
index 0422367d5..4b1eca7b0 100644
--- a/library/include/dfhack/DFProcessEnumerator.h
+++ b/library/include/dfhack/DFProcessEnumerator.h
@@ -30,7 +30,7 @@ distribution.
namespace DFHack
{
- class memory_info;
+ class VersionInfo;
class Process;
class BadProcesses;
/**
diff --git a/library/include/dfhack/DFVector.h b/library/include/dfhack/DFVector.h
index c46c80492..2eca3f2d8 100644
--- a/library/include/dfhack/DFVector.h
+++ b/library/include/dfhack/DFVector.h
@@ -29,6 +29,7 @@ distribution.
#include "DFExport.h"
namespace DFHack
{
+ class VersionInfo;
class Process;
template
class DFHACK_EXPORT DfVector
@@ -41,9 +42,9 @@ namespace DFHack
DfVector(Process * p, uint32_t address)
{
uint32_t triplet[3];
- memory_info * mem = p->getDescriptor();
- uint32_t offs = mem->getOffset("vector_triplet");
-
+ VersionInfo * mem = p->getDescriptor();
+ uint32_t offs = mem->getGroup("vector")->getOffset("start");
+
p->read(address + offs, sizeof(triplet), (uint8_t *) &triplet);
_start = triplet[0];
uint32_t byte_size = triplet[1] - triplet[0];
@@ -74,12 +75,12 @@ namespace DFHack
return data[index];
};
// get vector size
- inline uint32_t size ()
+ inline uint32_t size ()
{
return _size;
};
// get vector start
- inline uint32_t start ()
+ inline uint32_t start ()
{
return _start;
};
diff --git a/library/include/dfhack/DFMemInfo.h b/library/include/dfhack/VersionInfo.h
similarity index 69%
rename from library/include/dfhack/DFMemInfo.h
rename to library/include/dfhack/VersionInfo.h
index e40ecbf11..84a7087da 100644
--- a/library/include/dfhack/DFMemInfo.h
+++ b/library/include/dfhack/VersionInfo.h
@@ -28,6 +28,7 @@ distribution.
#include "DFPragma.h"
#include "DFExport.h"
#include "dfhack/DFTypes.h"
+#include
namespace DFHack
{
@@ -35,23 +36,67 @@ namespace DFHack
* Stubs
*/
class Process;
+ class XMLPP;
struct t_class;
+ class VersionInfoPrivate;
+ class OffsetGroupPrivate;
- class DFHACK_EXPORT memory_info
+ /*
+ * Offset Group
+ */
+ class DFHACK_EXPORT OffsetGroup
+ {
+ protected:
+ OffsetGroupPrivate * OGd;
+ public:
+ OffsetGroup();
+ OffsetGroup(const std::string & _name, OffsetGroup * parent = 0);
+ ~OffsetGroup();
+
+ void copy(const OffsetGroup * old); // recursive
+ void RebaseAddresses( int32_t offset ); // recursive
+
+ void createOffset (const std::string & key);
+ void createAddress (const std::string & key);
+ void createHexValue (const std::string & key);
+ void createString (const std::string & key);
+ OffsetGroup * createGroup ( const std::string & name );
+
+ int32_t getOffset (const std::string & key);
+ uint32_t getAddress (const std::string & key);
+ uint32_t getHexValue (const std::string & key);
+ std::string getString (const std::string & key);
+ OffsetGroup * getGroup ( const std::string & name );
+
+ void setOffset (const std::string & key, const std::string & value);
+ void setAddress (const std::string & key, const std::string & value);
+ void setHexValue (const std::string & key, const std::string & value);
+ void setString (const std::string & key, const std::string & value);
+ std::string PrintOffsets(int indentation);
+ std::string getName();
+ std::string getFullName();
+ OffsetGroup * getParent();
+ };
+
+ /*
+ * Version Info
+ */
+ class DFHACK_EXPORT VersionInfo : public OffsetGroup
{
private:
- class Private;
- Private * d;
+ VersionInfoPrivate * d;
public:
enum OSType
{
OS_WINDOWS,
OS_LINUX,
+ OS_APPLE,
OS_BAD
};
- memory_info();
- memory_info(const memory_info&);
- ~memory_info();
+ VersionInfo();
+ VersionInfo(const VersionInfo&);
+ void copy(const DFHack::VersionInfo* old);
+ ~VersionInfo();
void RebaseAddresses(const int32_t new_base);
void RebaseAll(const int32_t new_base);
@@ -59,12 +104,11 @@ namespace DFHack
void setBase (const std::string&);
void setBase (const uint32_t);
- int32_t getOffset (const std::string&);
- uint32_t getAddress (const std::string&);
- uint32_t getHexValue (const std::string&);
- int32_t getOffset (const char *);
- uint32_t getAddress (const char *);
- uint32_t getHexValue (const char *);
+ void setMD5 (const std::string & _md5);
+ std::string getMD5();
+
+ void setPE (uint32_t PE_);
+ uint32_t getPE();
std::string getMood(const uint32_t moodID);
std::string getString (const std::string&);
@@ -75,6 +119,7 @@ namespace DFHack
std::string getTraitName(const uint32_t) const;
std::string getLabor (const uint32_t);
std::vector< std::vector > const& getAllTraits();
+ std::map const& getAllLabours();
DFHack::t_level getLevelInfo(const uint32_t level) const;
@@ -87,21 +132,7 @@ namespace DFHack
void setOS(const OSType);
OSType getOS() const;
- void setOffset (const std::string &, const int32_t);
- void setAddress (const std::string &, const uint32_t);
- void setHexValue (const std::string &, const uint32_t);
-
- void setOffset (const std::string &, const char *);
- void setAddress (const std::string &, const char *);
- void setHexValue (const std::string &, const char *);
- void setString (const std::string &, const char *);
-
- void setOffset (const std::string &, const std::string &);
- void setAddress (const std::string &, const std::string &);
- void setHexValue (const std::string &, const std::string &);
- void setString (const std::string &, const std::string &);
-
- void setProfession(const std::string &, const std::string &);
+ void setProfession(const std::string & id, const std::string & name);
void setJob(const std::string &, const std::string &);
void setSkill(const std::string &, const std::string &);
void setTrait(const std::string &, const std::string &, const std::string &,
@@ -145,7 +176,7 @@ namespace DFHack
* Get the internal classID->classname mapping (for speed). DO NOT MANIPULATE THE VECTOR!
*/
const std::vector * getClassIDMapping();
-
+
/**
* Get a string with all addresses and offsets
*/
diff --git a/library/private/DFMemInfoManager.h b/library/include/dfhack/VersionInfoFactory.h
similarity index 60%
rename from library/private/DFMemInfoManager.h
rename to library/include/dfhack/VersionInfoFactory.h
index 60563d228..7f811f588 100644
--- a/library/private/DFMemInfoManager.h
+++ b/library/include/dfhack/VersionInfoFactory.h
@@ -26,25 +26,33 @@ distribution.
#define MEMINFO_MANAGER_H_INCLUDED
#include "dfhack/DFPragma.h"
+#include "dfhack/DFExport.h"
class TiXmlElement;
namespace DFHack
{
- class memory_info;
- class MemInfoManager
+ class VersionInfo;
+ class DFHACK_EXPORT VersionInfoFactory
{
friend class ProcessEnumerator;
public:
- MemInfoManager(string path_to_xml);
- ~MemInfoManager();
+ VersionInfoFactory(std::string path_to_xml);
+ ~VersionInfoFactory();
// memory info entries loaded from a file
- bool loadFile( string path_to_xml);
+ bool loadFile( std::string path_to_xml);
bool isInErrorState() const {return error;};
- std::vector meminfo;
+ std::vector versions;
private:
- void ParseVTable(TiXmlElement* vtable, memory_info* mem);
- void ParseEntry (TiXmlElement* entry, memory_info* mem, map & knownEntries);
+ void ParseVTable(TiXmlElement* vtable, VersionInfo* mem);
+ void ParseBase (TiXmlElement* base, VersionInfo* mem);
+ void ParseVersion (TiXmlElement* version, VersionInfo* mem);
+ // copy version 'base' to 'target' or throw
+ void EvalVersion(std::string base, VersionInfo* target);
+ void ParseOffsets(TiXmlElement* elem, VersionInfo* target, bool initial = false);
+
bool error;
+ typedef std::pair < TiXmlElement *, VersionInfo *> v_descr;
+ std::map knownVersions;
};
}
diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h
index 1686be281..67418d08a 100644
--- a/library/include/dfhack/modules/Creatures.h
+++ b/library/include/dfhack/modules/Creatures.h
@@ -5,6 +5,7 @@
*/
#include "dfhack/DFExport.h"
#include "dfhack/DFModule.h"
+#include "dfhack/modules/Items.h"
namespace DFHack
{
/*
@@ -374,6 +375,8 @@ namespace DFHack
const uint16_t x2, const uint16_t y2,const uint16_t z2);
bool ReadCreature(const int32_t index, t_creature & furball);
bool ReadJob(const t_creature * furball, std::vector & mat);
+ bool ReadInventoryIdx(const uint32_t index, std::vector & item);
+ bool ReadInventoryPtr(const uint32_t index, std::vector & item);
/* Getters */
uint32_t GetDwarfRaceIndex ( void );
diff --git a/library/include/dfhack/modules/Gui.h b/library/include/dfhack/modules/Gui.h
index 0ef170d3f..6ac91f35c 100644
--- a/library/include/dfhack/modules/Gui.h
+++ b/library/include/dfhack/modules/Gui.h
@@ -21,7 +21,9 @@ namespace DFHack
bool Finish();
///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
bool ReadViewScreen(t_viewscreen &);
/// read the DF menu state (designation menu ect)
diff --git a/library/include/dfhack/modules/Items.h b/library/include/dfhack/modules/Items.h
index 9b2dba8fe..3810e6037 100644
--- a/library/include/dfhack/modules/Items.h
+++ b/library/include/dfhack/modules/Items.h
@@ -1,5 +1,10 @@
#ifndef CL_MOD_ITEMS
#define CL_MOD_ITEMS
+
+/*
+ * DEPRECATED, DO NOT USE UNTIL FURTHER NOTICE!
+ **/
+
/*
* Creatures
*/
diff --git a/library/include/dfhack/modules/World.h b/library/include/dfhack/modules/World.h
index fdb08baf7..7834d4719 100644
--- a/library/include/dfhack/modules/World.h
+++ b/library/include/dfhack/modules/World.h
@@ -9,21 +9,29 @@
namespace DFHack
{
+ enum WeatherType
+ {
+ CLEAR,
+ RAINING,
+ SNOWING
+ };
class DFContextShared;
class DFHACK_EXPORT World : public Module
{
public:
-
+
World(DFHack::DFContextShared * d);
~World();
bool Start();
bool Finish();
-
+
uint32_t ReadCurrentTick();
uint32_t ReadCurrentYear();
uint32_t ReadCurrentMonth();
uint32_t ReadCurrentDay();
-
+ uint8_t ReadCurrentWeather();
+ void SetCurrentWeather(uint8_t weather);
+
private:
struct Private;
Private *d;
diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp
index 5d55163b3..92fca41d3 100644
--- a/library/modules/Buildings.cpp
+++ b/library/modules/Buildings.cpp
@@ -25,7 +25,7 @@ distribution.
#include "Internal.h"
#include "ContextShared.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFTypes.h"
@@ -71,12 +71,13 @@ Buildings::Buildings(DFContextShared * d_)
d->d = d_;
d->owner = d_->p;
d->Inited = d->Started = false;
- memory_info * mem = d->d->offset_descriptor;
- d->custom_workshop_vector = mem->getAddress("custom_workshop_vector");
- d->building_custom_workshop_type = mem->getOffset("building_custom_workshop_type");
- d->custom_workshop_type = mem->getOffset("custom_workshop_type");
- d->custom_workshop_name = mem->getOffset("custom_workshop_name");
- d->buildings_vector = mem->getAddress ("buildings_vector");
+ VersionInfo * mem = d->d->offset_descriptor;
+ OffsetGroup * OG_build = mem->getGroup("Buildings");
+ d->custom_workshop_vector = OG_build->getAddress("custom_workshop_vector");
+ d->building_custom_workshop_type = OG_build->getOffset("building_custom_workshop_type");
+ d->custom_workshop_type = OG_build->getOffset("custom_workshop_type");
+ d->custom_workshop_name = OG_build->getOffset("custom_workshop_name");
+ d->buildings_vector = OG_build->getAddress ("buildings_vector");
mem->resolveClassnameToClassID("building_custom_workshop", d->custom_workshop_id);
d->Inited = true;
}
@@ -139,12 +140,12 @@ bool Buildings::ReadCustomWorkshopTypes(map & btypes)
{
if(!d->Started)
return false;
-
+
Process * p = d->owner;
DfVector p_matgloss (p, d->custom_workshop_vector);
uint32_t size = p_matgloss.size();
btypes.clear();
-
+
for (uint32_t i = 0; i < size;i++)
{
string out = p->readSTLString (p_matgloss[i] + d->custom_workshop_name);
diff --git a/library/modules/Constructions.cpp b/library/modules/Constructions.cpp
index 535098fc5..ba6370ffd 100644
--- a/library/modules/Constructions.cpp
+++ b/library/modules/Constructions.cpp
@@ -25,7 +25,7 @@ distribution.
#include "Internal.h"
#include "ContextShared.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFTypes.h"
@@ -38,7 +38,7 @@ struct Constructions::Private
uint32_t construction_vector;
// translation
DfVector * p_cons;
-
+
DFContextShared *d;
Process * owner;
bool Inited;
@@ -52,8 +52,8 @@ Constructions::Constructions(DFContextShared * d_)
d->owner = d_->p;
d->p_cons = 0;
d->Inited = d->Started = false;
- memory_info * mem = d->d->offset_descriptor;
- d->construction_vector = mem->getAddress ("construction_vector");
+ VersionInfo * mem = d->d->offset_descriptor;
+ d->construction_vector = mem->getGroup("Constructions")->getAddress ("vector");
d->Inited = true;
}
diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp
index 2e9e319cd..0d26f336b 100644
--- a/library/modules/Creatures.cpp
+++ b/library/modules/Creatures.cpp
@@ -25,7 +25,7 @@ distribution.
#include "Internal.h"
#include "ContextShared.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFError.h"
@@ -50,10 +50,16 @@ struct Creatures::Private
{
bool Inited;
bool Started;
+ bool Ft_basic;
+ bool Ft_advanced;
+ bool Ft_jobs;
+ bool Ft_soul;
Creatures2010::creature_offsets creatures;
uint32_t creature_module;
uint32_t dwarf_race_index_addr;
uint32_t dwarf_civ_id_addr;
+ OffsetGroup * OG_jobs;
+ OffsetGroup * OG_job_mats;
DfVector *p_cre;
DFContextShared *d;
Process *owner;
@@ -67,67 +73,72 @@ Creatures::Creatures(DFContextShared* _d)
d->Inited = false;
d->Started = false;
d->d->InitReadNames(); // throws on error
+ VersionInfo * minfo = d->d->offset_descriptor;
+ OffsetGroup *OG_Creatures = minfo->getGroup("Creatures");
+ OffsetGroup *OG_creature = OG_Creatures->getGroup("creature");
+ OffsetGroup *OG_creature_ex = OG_creature->getGroup("advanced");
+ OffsetGroup *OG_soul = OG_Creatures->getGroup("soul");
+ OffsetGroup * OG_name = minfo->getGroup("name");
+ d->OG_jobs = OG_Creatures->getGroup("job");
+ d->OG_job_mats = d->OG_jobs->getGroup("material");
+ d->Ft_basic = d->Ft_advanced = d->Ft_jobs = d->Ft_soul = false;
+
+ Creatures2010::creature_offsets &creatures = d->creatures;
try
{
- memory_info * minfo = d->d->offset_descriptor;
- Creatures2010::creature_offsets &creatures = d->creatures;
- creatures.vector = minfo->getAddress ("creature_vector");
- creatures.pos_offset = minfo->getOffset ("creature_position");
- creatures.profession_offset = minfo->getOffset ("creature_profession");
- creatures.custom_profession_offset = minfo->getOffset ("creature_custom_profession");
- creatures.race_offset = minfo->getOffset ("creature_race");
- creatures.civ_offset = minfo->getOffset ("creature_civ");
- creatures.flags1_offset = minfo->getOffset ("creature_flags1");
- creatures.flags2_offset = minfo->getOffset ("creature_flags2");
- creatures.name_offset = minfo->getOffset ("creature_name");
- creatures.sex_offset = minfo->getOffset ("creature_sex");
- creatures.caste_offset = minfo->getOffset ("creature_caste");
- creatures.id_offset = minfo->getOffset ("creature_id");
- creatures.labors_offset = minfo->getOffset ("creature_labors");
- creatures.happiness_offset = minfo->getOffset ("creature_happiness");
- creatures.artifact_name_offset = minfo->getOffset("creature_artifact_name");
- creatures.soul_vector_offset = minfo->getOffset("creature_soul_vector");
- creatures.default_soul_offset = minfo->getOffset("creature_default_soul");
- creatures.physical_offset = minfo->getOffset("creature_physical");
- creatures.mood_offset = minfo->getOffset("creature_mood");
- creatures.mood_skill_offset = minfo->getOffset("creature_mood_skill");
- creatures.pickup_equipment_bit = minfo->getOffset("creature_pickup_equipment_bit");
- creatures.current_job_offset = minfo->getOffset("creature_current_job");
- // soul offsets
- creatures.soul_skills_vector_offset = minfo->getOffset("soul_skills_vector");
- creatures.soul_mental_offset = minfo->getOffset("soul_mental");
- creatures.soul_traits_offset = minfo->getOffset("soul_traits");
-
- // appearance
- creatures.appearance_vector_offset = minfo->getOffset("creature_appearance_vector");
-
- //birth
- creatures.birth_year_offset = minfo->getOffset("creature_birth_year");
- creatures.birth_time_offset = minfo->getOffset("creature_birth_time");
-
- // name offsets for the creature module
- creatures.name_firstname_offset = minfo->getOffset("name_firstname");
- creatures.name_nickname_offset = minfo->getOffset("name_nickname");
- creatures.name_words_offset = minfo->getOffset("name_words");
- d->dwarf_race_index_addr = minfo->getAddress("dwarf_race_index");
- d->dwarf_civ_id_addr = minfo->getAddress("dwarf_civ_id");
- /*
- // upload offsets to the SHM
- if(p->getModuleIndex("Creatures2010",1,d->creature_module))
+ // Creatures
+ creatures.vector = OG_Creatures->getAddress ("vector");
+ d->dwarf_race_index_addr = OG_Creatures->getAddress("current_race");
+ d->dwarf_civ_id_addr = OG_Creatures->getAddress("current_civ");
+ // Creatures/creature
+ creatures.name_offset = OG_creature->getOffset ("name");
+ creatures.custom_profession_offset = OG_creature->getOffset ("custom_profession");
+ creatures.profession_offset = OG_creature->getOffset ("profession");
+ creatures.race_offset = OG_creature->getOffset ("race");
+ creatures.pos_offset = OG_creature->getOffset ("position");
+ creatures.flags1_offset = OG_creature->getOffset ("flags1");
+ creatures.flags2_offset = OG_creature->getOffset ("flags2");
+ creatures.sex_offset = OG_creature->getOffset ("sex");
+ creatures.caste_offset = OG_creature->getOffset ("caste");
+ creatures.id_offset = OG_creature->getOffset ("id");
+ creatures.civ_offset = OG_creature->getOffset ("civ");
+ // name struct
+ creatures.name_firstname_offset = OG_name->getOffset("first");
+ creatures.name_nickname_offset = OG_name->getOffset("nick");
+ creatures.name_words_offset = OG_name->getOffset("second_words");
+ d->Ft_basic = true;
+ try
{
- // supply the module with offsets so it can work with them
- memcpy(SHMDATA(Creatures2010::creature_offsets),&creatures,sizeof(Creatures2010::creature_offsets));
- const uint32_t cmd = Creatures2010::CREATURE_INIT + (d->creature_module << 16);
- p->SetAndWait(cmd);
+ creatures.inventory_offset = OG_creature_ex->getOffset("inventory_vector");
+ creatures.pickup_equipment_bit = OG_creature_ex->getOffset("pickup_equipment_bit");
+ creatures.mood_offset = OG_creature_ex->getOffset("mood");
+ // pregnancy
+ // pregnancy_ptr
+ creatures.birth_year_offset = OG_creature_ex->getOffset("birth_year");
+ creatures.birth_time_offset = OG_creature_ex->getOffset("birth_time");
+ creatures.current_job_offset = OG_creature_ex->getOffset("current_job");
+ creatures.mood_skill_offset = OG_creature_ex->getOffset("current_job_skill");
+ creatures.physical_offset = OG_creature_ex->getOffset("physical");
+ creatures.appearance_vector_offset = OG_creature_ex->getOffset("appearance_vector");
+ creatures.artifact_name_offset = OG_creature_ex->getOffset("artifact_name");
+ creatures.labors_offset = OG_creature_ex->getOffset ("labors");
+ creatures.happiness_offset = OG_creature_ex->getOffset ("happiness");
+ d->Ft_advanced = true;
}
- */
- d->Inited = true;
- }
- catch (Error::MissingMemoryDefinition&)
- {
- d->Inited = false;
- throw;
+ catch(Error::All&){};
+ try
+ {
+ creatures.soul_vector_offset = OG_creature_ex->getOffset("soul_vector");
+ creatures.default_soul_offset = OG_creature_ex->getOffset("current_soul");
+ creatures.soul_mental_offset = OG_soul->getOffset("mental");
+ creatures.soul_skills_vector_offset = OG_soul->getOffset("skills_vector");
+ creatures.soul_traits_offset = OG_soul->getOffset("traits");
+ d->Ft_soul = true;
+ }
+ catch(Error::All&){};
}
+ catch(Error::All&){};
+ d->Inited = true;
}
Creatures::~Creatures()
@@ -158,6 +169,7 @@ bool Creatures::Finish()
bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
{
if(!d->Started) return false;
+ memset(&furball, 0, sizeof(t_creature));
// SHM fast path
Process * p = d->owner;
/*
@@ -171,7 +183,7 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
}
*/
// non-SHM slow path
- memory_info * minfo = d->d->offset_descriptor;
+ VersionInfo * minfo = d->d->offset_descriptor;
// read pointer from vector at position
uint32_t temp = d->p_cre->at (index);
@@ -179,129 +191,120 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
Creatures2010::creature_offsets &offs = d->creatures;
//read creature from memory
-
- // 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)
+ if(d->Ft_basic)
{
- furball.current_job.active = true;
- furball.current_job.jobType = p->readByte (furball.current_job.occupationPtr + minfo->getOffset("job_type") );
- furball.current_job.jobId = p->readDWord (furball.current_job.occupationPtr + minfo->getOffset("job_id") );
+ // name
+ d->d->readName(furball.name,temp + offs.name_offset);
+
+ // 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;;
- }
-
- furball.birth_year = p->readDWord (temp + offs.birth_year_offset );
- furball.birth_time = p->readDWord (temp + offs.birth_time_offset );
+ // happiness
+ p->readDWord (temp + offs.happiness_offset, furball.happiness);
+
+ // 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);
+
+ // 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
- /*
- uint32_t jobIdAddr = p->readDWord (temp + offs.creature_current_job_offset);
+ // appearance
+ DfVector 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];
+ }
- if (jobIdAddr)
- {
- furball.current_job.active = true;
- furball.current_job.jobId = p->readByte (jobIdAddr + offs.creature_current_job_id_offset);
+ //likes
+ /*
+ DfVector likes(d->p, temp + offs.creature_likes_offset);
+ furball.numLikes = likes.getSize();
+ for(uint32_t i = 0;iread(temp2,sizeof(t_like),(uint8_t *) &furball.likes[i]);
+ }*/
}
- else
+ if(d->Ft_soul)
{
- furball.current_job.active = false;
- }
- */
+ /*
+ // enum soul pointer vector
+ DfVector souls(p,temp + offs.creature_soul_vector_offset);
+ */
+ uint32_t soul = p->readDWord(temp + offs.default_soul_offset);
+ furball.has_default_soul = false;
- /*
- p->readDWord(temp + offs.creature_pregnancy_offset, furball.pregnancy_timer);
- */
+ if(soul)
+ {
+ furball.has_default_soul = true;
+ // get first soul's skills
+ DfVector skills(p, soul + offs.soul_skills_vector_offset);
+ furball.defaultSoul.numSkills = skills.size();
- /*
- // enum soul pointer vector
- DfVector souls(p,temp + offs.creature_soul_vector_offset);
- */
- uint32_t soul = p->readDWord(temp + offs.default_soul_offset);
- furball.has_default_soul = false;
+ for (uint32_t i = 0; i < furball.defaultSoul.numSkills;i++)
+ {
+ uint32_t temp2 = skills[i];
+ // a byte: this gives us 256 skills maximum.
+ 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));
+ }
- if(soul)
- {
- furball.has_default_soul = true;
- // get first soul's skills
- DfVector skills(p, soul + offs.soul_skills_vector_offset);
- furball.defaultSoul.numSkills = skills.size();
+ // 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);
- for (uint32_t i = 0; i < furball.defaultSoul.numSkills;i++)
- {
- uint32_t temp2 = skills[i];
- // a byte: this gives us 256 skills maximum.
- 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));
+ // traits as well
+ p->read(soul + offs.soul_traits_offset,
+ sizeof (uint16_t) * NUM_CREATURE_TRAITS,
+ (uint8_t *) &furball.defaultSoul.traits);
}
-
- // 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);
}
-
- DfVector app(p, temp + offs.appearance_vector_offset);
- furball.nbcolors = app.size();
- if(furball.nbcolors>MAX_COLORS)
- furball.nbcolors = MAX_COLORS;
- for(uint32_t i = 0; i < furball.nbcolors; i++)
+ if(d->Ft_jobs)
{
- furball.color[i] = app[i];
+ furball.current_job.occupationPtr = p->readDWord (temp + offs.current_job_offset);
+ if(furball.current_job.occupationPtr)
+ {
+ furball.current_job.active = true;
+ furball.current_job.jobType = p->readByte (furball.current_job.occupationPtr + d->OG_jobs->getOffset("type") );
+ furball.current_job.jobId = p->readDWord (furball.current_job.occupationPtr + d->OG_jobs->getOffset("id") );
+ }
+ else
+ {
+ furball.current_job.active = false;;
+ }
}
- //likes
- /*
- DfVector likes(d->p, temp + offs.creature_likes_offset);
- furball.numLikes = likes.getSize();
- for(uint32_t i = 0;iread(temp2,sizeof(t_like),(uint8_t *) &furball.likes[i]);
- }*/
-
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 const& mat)
{
- unsigned int i;
+ unsigned int i;
if(!d->Inited) return false;
if(!furball->current_job.active) return false;
Process * p = d->owner;
- memory_info * minfo = d->d->offset_descriptor;
-
- DfVector cmats(p, furball->current_job.occupationPtr + minfo->getOffset("job_materials_vector"));
+ DfVector cmats(p, furball->current_job.occupationPtr + d->OG_jobs->getOffset("materials_vector"));
for(i=0;iwriteWord(cmats[i] + minfo->getOffset("job_material_maintype"), mat[i].itemType);
- p->writeWord(cmats[i] + minfo->getOffset("job_material_sectype1"), mat[i].subType);
- p->writeWord(cmats[i] + minfo->getOffset("job_material_sectype2"), mat[i].subIndex);
- p->writeDWord(cmats[i] + minfo->getOffset("job_material_sectype3"), mat[i].index);
- p->writeDWord(cmats[i] + minfo->getOffset("job_material_flags"), mat[i].flags);
+ p->writeWord(cmats[i] + d->OG_job_mats->getOffset("maintype"), mat[i].itemType);
+ p->writeWord(cmats[i] + d->OG_job_mats->getOffset("sectype1"), mat[i].subType);
+ p->writeWord(cmats[i] + d->OG_job_mats->getOffset("sectype2"), mat[i].subIndex);
+ p->writeDWord(cmats[i] + d->OG_job_mats->getOffset("sectype3"), mat[i].index);
+ p->writeDWord(cmats[i] + d->OG_job_mats->getOffset("flags"), mat[i].flags);
}
return true;
}
@@ -595,17 +596,40 @@ bool Creatures::ReadJob(const t_creature * furball, vector & mat)
if(!d->Inited) return false;
if(!furball->current_job.active) return false;
Process * p = d->owner;
- memory_info * minfo = d->d->offset_descriptor;
+ VersionInfo * minfo = d->d->offset_descriptor;
- DfVector cmats(p, furball->current_job.occupationPtr + minfo->getOffset("job_materials_vector"));
+ DfVector cmats(p, furball->current_job.occupationPtr + d->OG_jobs->getOffset("materials_vector"));
mat.resize(cmats.size());
for(i=0;ireadWord(cmats[i] + minfo->getOffset("job_material_maintype"));
- mat[i].subType = p->readWord(cmats[i] + minfo->getOffset("job_material_sectype1"));
- mat[i].subIndex = p->readWord(cmats[i] + minfo->getOffset("job_material_sectype2"));
- mat[i].index = p->readDWord(cmats[i] + minfo->getOffset("job_material_sectype3"));
- mat[i].flags = p->readDWord(cmats[i] + minfo->getOffset("job_material_flags"));
+ mat[i].itemType = p->readWord(cmats[i] + d->OG_job_mats->getOffset("maintype"));
+ mat[i].subType = p->readWord(cmats[i] + d->OG_job_mats->getOffset("sectype1"));
+ mat[i].subIndex = p->readWord(cmats[i] + d->OG_job_mats->getOffset("sectype2"));
+ mat[i].index = p->readDWord(cmats[i] + d->OG_job_mats->getOffset("sectype3"));
+ mat[i].flags = p->readDWord(cmats[i] + d->OG_job_mats->getOffset("flags"));
}
return true;
}
+
+bool Creatures::ReadInventoryIdx(const uint32_t index, std::vector & 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 & item)
+{
+ unsigned int i;
+ if(!d->Started) return false;
+ Process * p = d->owner;
+
+ DfVector citem(p, temp + d->creatures.inventory_offset);
+ if(citem.size() == 0)
+ return false;
+ item.resize(citem.size());
+ for(i=0;ireadDWord(citem[i]);
+ return true;
+}
diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp
index f017a04f3..177a00467 100644
--- a/library/modules/Gui.cpp
+++ b/library/modules/Gui.cpp
@@ -26,36 +26,54 @@ distribution.
#include "ContextShared.h"
#include "dfhack/modules/Gui.h"
#include "dfhack/DFProcess.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFTypes.h"
using namespace DFHack;
struct Gui::Private
{
- bool Inited;
+ Private()
+ {
+ Started = PauseInited = ViewScreeInited = MenuStateInited = false;
+ }
bool Started;
uint32_t pause_state_offset;
+ bool PauseInited;
uint32_t view_screen_offset;
- uint32_t current_cursor_creature_offset;
+ bool ViewScreeInited;
uint32_t current_menu_state_offset;
+ bool MenuStateInited;
DFContextShared *d;
Process * owner;
};
Gui::Gui(DFContextShared * _d)
{
-
+
d = new Private;
d->d = _d;
d->owner = _d->p;
- d->Inited = d->Started = true;
-
- memory_info * mem = d->d->offset_descriptor;
- d->current_menu_state_offset = mem->getAddress("current_menu_state");
- d->pause_state_offset = mem->getAddress ("pause_state");
- d->view_screen_offset = mem->getAddress ("view_screen");
- d->Inited = d->Started = true;
+ OffsetGroup * OG_Gui = d->d->offset_descriptor->getGroup("GUI");
+ try
+ {
+ d->current_menu_state_offset = OG_Gui->getAddress("current_menu_state");
+ d->MenuStateInited = true;
+ }
+ catch(exception &){};
+ try
+ {
+ d->pause_state_offset = OG_Gui->getAddress ("pause_state");
+ d->PauseInited = true;
+ }
+ catch(exception &){};
+ try
+ {
+ d->view_screen_offset = OG_Gui->getAddress ("view_screen");
+ d->ViewScreeInited = true;
+ }
+ catch(exception &){};
+ d->Started = true;
}
Gui::~Gui()
@@ -75,25 +93,31 @@ bool Gui::Finish()
bool Gui::ReadPauseState()
{
- // replace with an exception
- if(!d->Inited) return false;
+ if(!d->PauseInited) return false;
uint32_t pauseState = d->owner->readDWord (d->pause_state_offset);
return pauseState & 1;
}
+void Gui::SetPauseState(bool paused)
+{
+ if(!d->PauseInited) return;
+ cout << "pause set" << endl;
+ d->owner->writeDWord (d->pause_state_offset, paused);
+}
+
uint32_t Gui::ReadMenuState()
{
- if(d->Inited)
+ if(d->MenuStateInited)
return(d->owner->readDWord(d->current_menu_state_offset));
return false;
}
bool Gui::ReadViewScreen (t_viewscreen &screen)
{
- if (!d->Inited) return false;
+ if (!d->ViewScreeInited) return false;
Process * p = d->owner;
-
+
uint32_t last = p->readDWord (d->view_screen_offset);
uint32_t screenAddr = p->readDWord (last);
uint32_t nextScreenPtr = p->readDWord (last + 4);
diff --git a/library/modules/Gui_C.cpp b/library/modules/Gui_C.cpp
index da17d2a18..8870b4e87 100644
--- a/library/modules/Gui_C.cpp
+++ b/library/modules/Gui_C.cpp
@@ -60,8 +60,6 @@ int Gui_ReadPauseState(DFHackObject* gui)
int Gui_ReadViewScreen(DFHackObject* gui, t_viewscreen* viewscreen)
{
- //int result;
-
if(gui != NULL)
{
return ((DFHack::Gui*)gui)->ReadViewScreen(*viewscreen);
@@ -70,6 +68,18 @@ int Gui_ReadViewScreen(DFHackObject* gui, t_viewscreen* viewscreen)
return -1;
}
+int Gui_ReadMenuState(DFHackObject* gui, uint32_t* menuState)
+{
+ if(gui != NULL)
+ {
+ *menuState = ((DFHack::Gui*)gui)->ReadMenuState();
+
+ return 1;
+ }
+
+ return -1;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp
index 2419bbf40..6ae558dcd 100644
--- a/library/modules/Items.cpp
+++ b/library/modules/Items.cpp
@@ -25,7 +25,7 @@ distribution.
#include "Internal.h"
#include "ContextShared.h"
#include "dfhack/DFTypes.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/modules/Materials.h"
@@ -189,11 +189,12 @@ int32_t Accessor::getValue(uint32_t objectPtr)
ItemDesc::ItemDesc(uint32_t VTable, Process *p)
{
- uint32_t funcOffsetA = p->getDescriptor()->getOffset("item_type_accessor");
- uint32_t funcOffsetB = p->getDescriptor()->getOffset("item_subtype_accessor");
- uint32_t funcOffsetC = p->getDescriptor()->getOffset("item_subindex_accessor");
- uint32_t funcOffsetD = p->getDescriptor()->getOffset("item_index_accessor");
- uint32_t funcOffsetQuality = p->getDescriptor()->getOffset("item_quality_accessor");
+ OffsetGroup * Items = p->getDescriptor()->getGroup("Items");
+ uint32_t funcOffsetA = Items->getOffset("item_type_accessor");
+ uint32_t funcOffsetB = Items->getOffset("item_subtype_accessor");
+ uint32_t funcOffsetC = Items->getOffset("item_subindex_accessor");
+ uint32_t funcOffsetD = Items->getOffset("item_index_accessor");
+ uint32_t funcOffsetQuality = Items->getOffset("item_quality_accessor");
this->vtable = VTable;
this->p = p;
this->className = p->readClassName(VTable).substr(5);
diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp
index 0cf3588a1..124e9bea9 100644
--- a/library/modules/Maps.cpp
+++ b/library/modules/Maps.cpp
@@ -29,7 +29,7 @@ distribution.
#include "ContextShared.h"
#include "dfhack/modules/Maps.h"
#include "dfhack/DFError.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
@@ -52,6 +52,9 @@ struct Maps::Private
DFContextShared *d;
Process * owner;
+ OffsetGroup *OG_local_features;
+ OffsetGroup *OG_global_features;
+ OffsetGroup *OG_vector;
bool Inited;
bool Started;
@@ -67,40 +70,52 @@ Maps::Maps(DFContextShared* _d)
d->d = _d;
Process *p = d->owner = _d->p;
d->Inited = d->Started = false;
+ d->block = NULL;
- DFHack::memory_info * mem = p->getDescriptor();
+ DFHack::VersionInfo * mem = p->getDescriptor();
Server::Maps::maps_offsets &off = d->offsets;
// get the offsets once here
- off.map_offset = mem->getAddress ("map_data");
- off.x_count_offset = mem->getAddress ("x_count_block");
- off.y_count_offset = mem->getAddress ("y_count_block");
- off.z_count_offset = mem->getAddress ("z_count_block");
- off.tile_type_offset = mem->getOffset ("map_data_type");
- off.designation_offset = mem->getOffset ("map_data_designation");
- off.occupancy_offset = mem->getOffset("map_data_occupancy");
- off.biome_stuffs = mem->getOffset ("map_data_biome_stuffs");
- off.veinvector = mem->getOffset ("map_data_vein_vector");
- off.local_feature_offset = mem->getOffset ("map_data_feature_local");
- off.global_feature_offset = mem->getOffset ("map_data_feature_global");
-
- off.temperature1_offset = mem->getOffset ("map_data_temperature1_offset");
- off.temperature2_offset = mem->getOffset ("map_data_temperature2_offset");
- off.region_x_offset = mem->getAddress ("region_x");
- off.region_y_offset = mem->getAddress ("region_y");
- off.region_z_offset = mem->getAddress ("region_z");
-
- off.world_regions = mem->getAddress ("ptr2_region_array");
- off.region_size = mem->getHexValue ("region_size");
- off.region_geo_index_offset = mem->getOffset ("region_geo_index_off");
- off.geolayer_geoblock_offset = mem->getOffset ("geolayer_geoblock_offset");
- off.world_geoblocks_vector = mem->getAddress ("geoblock_vector");
- off.type_inside_geolayer = mem->getOffset ("type_inside_geolayer");
-
- off.world_size_x = mem->getAddress ("world_size_x");
- off.world_size_y = mem->getAddress ("world_size_y");
-
- // these can fail and will be found when looking at the actual veins later
+ OffsetGroup *OG_Maps = mem->getGroup("Maps");
+ {
+ off.map_offset = OG_Maps->getAddress ("map_data");
+ off.x_count_offset = OG_Maps->getAddress ("x_count_block");
+ off.y_count_offset = OG_Maps->getAddress ("y_count_block");
+ off.z_count_offset = OG_Maps->getAddress ("z_count_block");
+ off.region_x_offset = OG_Maps->getAddress ("region_x");
+ off.region_y_offset = OG_Maps->getAddress ("region_y");
+ off.region_z_offset = OG_Maps->getAddress ("region_z");
+ off.world_size_x = OG_Maps->getAddress ("world_size_x");
+ off.world_size_y = OG_Maps->getAddress ("world_size_y");
+
+ OffsetGroup *OG_MapBlock = OG_Maps->getGroup("block");
+ {
+ off.tile_type_offset = OG_MapBlock->getOffset ("type");
+ off.designation_offset = OG_MapBlock->getOffset ("designation");
+ off.occupancy_offset = OG_MapBlock->getOffset("occupancy");
+ off.biome_stuffs = OG_MapBlock->getOffset ("biome_stuffs");
+ off.veinvector = OG_MapBlock->getOffset ("vein_vector");
+ off.local_feature_offset = OG_MapBlock->getOffset ("feature_local");
+ off.global_feature_offset = OG_MapBlock->getOffset ("feature_global");
+ off.temperature1_offset = OG_MapBlock->getOffset ("temperature1");
+ off.temperature2_offset = OG_MapBlock->getOffset ("temperature2");
+ }
+
+ OffsetGroup *OG_Geology = OG_Maps->getGroup("geology");
+ {
+ off.world_regions = OG_Geology->getAddress ("ptr2_region_array");
+ off.region_size = OG_Geology->getHexValue ("region_size");
+ off.region_geo_index_offset = OG_Geology->getOffset ("region_geo_index_off");
+ off.geolayer_geoblock_offset = OG_Geology->getOffset ("geolayer_geoblock_offset");
+ off.world_geoblocks_vector = OG_Geology->getAddress ("geoblock_vector");
+ off.type_inside_geolayer = OG_Geology->getOffset ("type_inside_geolayer");
+ }
+ d->OG_global_features = OG_Maps->getGroup("features")->getGroup("global");
+ d->OG_local_features = OG_Maps->getGroup("features")->getGroup("local");
+ }
+ d->OG_vector = mem->getGroup("vector");
+
+ // these can (will) fail and will be found when looking at the actual veins later
// basically a cache
off.vein_ice_vptr = 0;
mem->resolveClassnameToVPtr("block_square_event_frozen_liquid", off.vein_ice_vptr);
@@ -446,7 +461,7 @@ bool Maps::WriteTemperatures (uint32_t x, uint32_t y, uint32_t z, t_temperatures
/*
* Region Offsets - used for layer geology
- */
+ */
bool Maps::ReadRegionOffsets (uint32_t x, uint32_t y, uint32_t z, biome_indices40d *buffer)
{
MAPS_GUARD
@@ -501,7 +516,7 @@ bool Maps::WriteGlobalFeature(uint32_t x, uint32_t y, uint32_t z, int16_t global
/*
* Block events
- */
+ */
bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector * veins, vector * ices, vector *splatter)
{
MAPS_GUARD
@@ -509,12 +524,12 @@ bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector * veins,
t_frozenliquidvein fv;
t_spattervein sv;
Process* p = d->owner;
-
+
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if(veins) veins->clear();
if(ices) ices->clear();
if(splatter) splatter->clear();
-
+
Server::Maps::maps_offsets &off = d->offsets;
if (addr)
{
@@ -646,7 +661,7 @@ __int16 __userpurge GetGeologicalRegion(__int16 block_X, int X, __i
bool Maps::ReadGeology (vector < vector >& assign)
{
MAPS_GUARD
- memory_info * minfo = d->d->offset_descriptor;
+ VersionInfo * minfo = d->d->offset_descriptor;
Process *p = d->owner;
// get needed addresses and offsets. Now this is what I call crazy.
uint16_t worldSizeX, worldSizeY;
@@ -721,16 +736,16 @@ bool Maps::ReadLocalFeatures( std::map > &
return false;
Process * p = d->owner;
- memory_info * mem = p->getDescriptor();
+ VersionInfo * mem = p->getDescriptor();
// deref pointer to the humongo-structure
- uint32_t base = p->readDWord(mem->getAddress("local_feature_start_ptr"));
+ uint32_t base = p->readDWord(d->OG_local_features->getAddress("start_ptr"));
if(!base)
return false;
- uint32_t sizeof_vec = mem->getHexValue("sizeof_vector");
+ const uint32_t sizeof_vec = d->OG_vector->getHexValue("sizeof");
const uint32_t sizeof_elem = 16;
const uint32_t offset_elem = 4;
- const uint32_t main_mat_offset = mem->getOffset("local_feature_mat"); // 0x30
- const uint32_t sub_mat_offset = mem->getOffset("local_feature_submat"); // 0x34
+ const uint32_t main_mat_offset = d->OG_local_features->getOffset("material"); // 0x30
+ const uint32_t sub_mat_offset = d->OG_local_features->getOffset("submaterial"); // 0x34
local_features.clear();
@@ -746,7 +761,7 @@ bool Maps::ReadLocalFeatures( std::map > &
uint32_t array_elem = p->readDWord(base + (region_x_local / 16) * 4);
// 16B structs, second DWORD of the struct is a pointer
- uint32_t wtf = p->readDWord(array_elem + ( sizeof_elem * ( (uint32_t)region_y_local/16)) + offset_elem);
+ uint32_t wtf = p->readDWord(array_elem + ( sizeof_elem * ( (uint32_t)region_y_local/16)) + offset_elem);
if(wtf)
{
// wtf + sizeof(vector) * crap;
@@ -814,12 +829,11 @@ bool Maps::ReadGlobalFeatures( std::vector & features)
return false;
Process * p = d->owner;
- memory_info * mem = p->getDescriptor();
- uint32_t global_feature_vector = mem->getAddress("global_feature_vector");
- uint32_t global_feature_funcptr = mem->getOffset("global_feature_funcptr_");
- const uint32_t main_mat_offset = mem->getOffset("global_feature_mat"); // 0x34
- const uint32_t sub_mat_offset = mem->getOffset("global_feature_submat"); // 0x38
+ const uint32_t global_feature_vector = d->OG_global_features->getAddress("vector");
+ const uint32_t global_feature_funcptr = d->OG_global_features->getOffset("funcptr");
+ const uint32_t main_mat_offset = d->OG_global_features->getOffset("material"); // 0x34
+ const uint32_t sub_mat_offset = d->OG_global_features->getOffset("submaterial"); // 0x38
DfVector p_features (p,global_feature_vector);
features.clear();
diff --git a/library/modules/Maps_C.cpp b/library/modules/Maps_C.cpp
index 09a7dc065..911f4e0f9 100644
--- a/library/modules/Maps_C.cpp
+++ b/library/modules/Maps_C.cpp
@@ -54,6 +54,37 @@ int Maps_Finish(DFHackObject* maps)
return -1;
}
+t_feature* Maps_ReadGlobalFeatures(DFHackObject* maps)
+{
+ if(maps != NULL)
+ {
+ std::vector featureVec;
+
+ if(((DFHack::Maps*)maps)->ReadGlobalFeatures(featureVec))
+ {
+ if(featureVec.size() <= 0)
+ return NULL;
+
+ t_feature* buf;
+
+ (*alloc_t_feature_buffer_callback)(buf, featureVec.size());
+
+ if(buf != NULL)
+ {
+ copy(featureVec.begin(), featureVec.end(), buf);
+
+ return buf;
+ }
+ else
+ return NULL;
+ }
+ else
+ return NULL;
+ }
+
+ return NULL;
+}
+
void Maps_getSize(DFHackObject* maps, uint32_t* x, uint32_t* y, uint32_t* z)
{
if(maps != NULL)
diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp
index fe8e3f339..2ad78361e 100644
--- a/library/modules/Materials.cpp
+++ b/library/modules/Materials.cpp
@@ -26,9 +26,10 @@ distribution.
#include "ContextShared.h"
#include "dfhack/DFTypes.h"
#include "dfhack/modules/Materials.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
+#include
using namespace DFHack;
@@ -37,6 +38,13 @@ class Materials::Private
public:
DFContextShared *d;
Process * owner;
+ OffsetGroup * OG_Materials;
+ uint32_t vector_inorganic;
+ uint32_t vector_organic_all;
+ uint32_t vector_organic_plants;
+ uint32_t vector_organic_trees;
+ uint32_t vector_races;
+ uint32_t vector_other;
/*
bool Inited;
bool Started;
@@ -48,6 +56,14 @@ Materials::Materials(DFContextShared * d_)
d = new Private;
d->d = d_;
d->owner = d_->p;
+ OffsetGroup *OG_Materials = d->OG_Materials = d->owner->getDescriptor()->getGroup("Materials");
+ {
+ d->vector_inorganic = OG_Materials->getAddress("inorganics");
+ d->vector_organic_all = OG_Materials->getAddress ("organics_all");
+ d->vector_organic_plants = OG_Materials->getAddress ("organics_plants");
+ d->vector_organic_trees = OG_Materials->getAddress ("organics_trees");
+ d->vector_races = OG_Materials->getAddress("creature_type_vector");
+ }
}
Materials::~Materials()
{
@@ -56,6 +72,7 @@ Materials::~Materials()
bool Materials::Finish()
{
+ /*
inorganic.clear();
organic.clear();
tree.clear();
@@ -65,6 +82,7 @@ bool Materials::Finish()
color.clear();
other.clear();
alldesc.clear();
+ */
return true;
}
@@ -183,12 +201,12 @@ bool API::ReadInorganicMaterials (vector & inorganic)
//cout << temp << endl;
//fill_char_buf(mat.id, d->p->readSTLString(temp)); // reads a C string given an address
p->readSTLString (temp, mat.id, 128);
-
+
p->readSTLString (temp+matgloss_stone_name_offset, mat.name, 128);
mat.fore = (uint8_t) p->readWord (temp + matgloss_colors);
mat.back = (uint8_t) p->readWord (temp + matgloss_colors + 2);
mat.bright = (uint8_t) p->readWord (temp + matgloss_colors + 4);
-
+
inorganic.push_back (mat);
}
return true;
@@ -216,14 +234,14 @@ inline bool ReadNamesOnly(Process* p, uint32_t address, vector & nam
bool Materials::ReadInorganicMaterials (void)
{
Process * p = d->owner;
- DfVector p_matgloss (p, d->owner->getDescriptor()->getAddress ("mat_inorganics"));
+ DfVector p_matgloss (p, d->vector_inorganic);
uint32_t size = p_matgloss.size();
inorganic.clear();
inorganic.reserve (size);
for (uint32_t i = 0; i < size;i++)
{
t_matgloss mat;
-
+
p->readSTLString (p_matgloss[i], mat.id, 128);
//p->readSTLString (p_matgloss[i] + mat_name, mat.name, 128);
mat.name[0] = 0;
@@ -237,29 +255,29 @@ bool Materials::ReadInorganicMaterials (void)
bool Materials::ReadOrganicMaterials (void)
{
- return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("mat_organics_all"), organic );
+ return ReadNamesOnly(d->owner, d->vector_organic_all, organic );
}
bool Materials::ReadWoodMaterials (void)
{
- return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("mat_organics_trees"), tree );
+ return ReadNamesOnly(d->owner, d->vector_organic_trees, tree );
}
bool Materials::ReadPlantMaterials (void)
{
- return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("mat_organics_plants"), plant );
+ return ReadNamesOnly(d->owner, d->vector_organic_plants, plant );
}
bool Materials::ReadCreatureTypes (void)
{
- return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("creature_type_vector"), race );
+ return ReadNamesOnly(d->owner, d->vector_races, race );
return true;
}
bool Materials::ReadOthers(void)
{
Process * p = d->owner;
- uint32_t matBase = p->getDescriptor()->getAddress ("mat_other");
+ uint32_t matBase = d->OG_Materials->getAddress ("other");
uint32_t i = 0;
uint32_t ptr;
@@ -281,7 +299,8 @@ bool Materials::ReadOthers(void)
bool Materials::ReadDescriptorColors (void)
{
Process * p = d->owner;
- DfVector p_colors (p, p->getDescriptor()->getAddress ("descriptor_colors_vector"));
+ OffsetGroup * OG_Descriptors = p->getDescriptor()->getGroup("Materials")->getGroup("descriptors");
+ DfVector p_colors (p, OG_Descriptors->getAddress ("colors_vector"));
uint32_t size = p_colors.size();
color.clear();
@@ -291,43 +310,70 @@ bool Materials::ReadDescriptorColors (void)
for (uint32_t i = 0; i < size;i++)
{
t_descriptor_color col;
- p->readSTLString (p_colors[i] + p->getDescriptor()->getOffset ("descriptor_rawname"), col.id, 128);
- p->readSTLString (p_colors[i] + p->getDescriptor()->getOffset ("descriptor_name"), col.name, 128);
- col.r = p->readFloat( p_colors[i] + p->getDescriptor()->getOffset ("descriptor_color_r") );
- col.v = p->readFloat( p_colors[i] + p->getDescriptor()->getOffset ("descriptor_color_v") );
- col.b = p->readFloat( p_colors[i] + p->getDescriptor()->getOffset ("descriptor_color_b") );
+ p->readSTLString (p_colors[i] + OG_Descriptors->getOffset ("rawname"), col.id, 128);
+ p->readSTLString (p_colors[i] + OG_Descriptors->getOffset ("name"), col.name, 128);
+ col.r = p->readFloat( p_colors[i] + OG_Descriptors->getOffset ("color_r") );
+ col.v = p->readFloat( p_colors[i] + OG_Descriptors->getOffset ("color_v") );
+ col.b = p->readFloat( p_colors[i] + OG_Descriptors->getOffset ("color_b") );
color.push_back(col);
}
- return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("descriptor_all_colors"), alldesc );
+ return ReadNamesOnly(d->owner, OG_Descriptors->getAddress ("all_colors_vector"), alldesc );
return true;
}
bool Materials::ReadCreatureTypesEx (void)
{
Process *p = d->owner;
- memory_info *mem = d->owner->getDescriptor();
- DfVector p_races (p, mem->getAddress ("creature_type_vector"));
- uint32_t castes_vector_offset = mem->getOffset ("creature_type_caste_vector");
- uint32_t extract_vector_offset = mem->getOffset ("creature_type_extract_vector");
- uint32_t sizeof_string = mem->getHexValue ("sizeof_string");
- uint32_t caste_colormod_offset = mem->getOffset ("caste_color_modifiers");
- uint32_t caste_bodypart_offset = mem->getOffset ("caste_bodypart_vector");
- uint32_t caste_attributes_offset = mem->getOffset ("caste_attributes");
- uint32_t bodypart_id_offset = mem->getOffset ("bodypart_id");
- uint32_t bodypart_category_offset = mem->getOffset ("bodypart_category");
- uint32_t bodypart_layers_offset = mem->getOffset ("bodypart_layers_vector");
- uint32_t bodypart_singular_offset = mem->getOffset ("bodypart_singular_vector"); // unused
- uint32_t bodypart_plural_offset = mem->getOffset ("bodypart_plural_vector"); // unused
- uint32_t color_modifier_part_offset = mem->getOffset ("color_modifier_part");
- uint32_t color_modifier_startdate_offset = mem->getOffset ("color_modifier_startdate");
- uint32_t color_modifier_enddate_offset = mem->getOffset ("color_modifier_enddate");
+ VersionInfo *mem = p->getDescriptor();
+ OffsetGroup * OG_string = mem->getGroup("string");
+ uint32_t sizeof_string = OG_string->getHexValue ("sizeof");
+
+ OffsetGroup * OG_Mats = mem->getGroup("Materials");
+ DfVector p_races (p, OG_Mats->getAddress ("creature_type_vector"));
+
+ OffsetGroup * OG_Creature = OG_Mats->getGroup("creature");
+ uint32_t castes_vector_offset = OG_Creature->getOffset ("caste_vector");
+ uint32_t extract_vector_offset = OG_Creature->getOffset ("extract_vector");
+ uint32_t tile_offset = OG_Creature->getOffset ("tile");
+ uint32_t tile_color_offset = OG_Creature->getOffset ("tile_color");
+
+ bool have_advanced = false;
+ uint32_t caste_colormod_offset;
+ uint32_t caste_attributes_offset;
+ uint32_t caste_bodypart_offset;
+ uint32_t bodypart_id_offset;
+ uint32_t bodypart_category_offset;
+ uint32_t bodypart_layers_offset;
+ uint32_t bodypart_singular_offset;
+ uint32_t bodypart_plural_offset;
+ uint32_t color_modifier_part_offset;
+ uint32_t color_modifier_startdate_offset;
+ uint32_t color_modifier_enddate_offset;
+ try
+ {
+ OffsetGroup * OG_Caste = OG_Creature->getGroup("caste");
+ caste_colormod_offset = OG_Caste->getOffset ("color_modifiers");
+ caste_attributes_offset = OG_Caste->getOffset ("attributes");
+ caste_bodypart_offset = OG_Caste->getOffset ("bodypart_vector");
+ OffsetGroup * OG_CasteBodyparts = OG_Creature->getGroup("caste_bodyparts");
+ bodypart_id_offset = OG_CasteBodyparts->getOffset ("id");
+ bodypart_category_offset = OG_CasteBodyparts->getOffset ("category");
+ bodypart_layers_offset = OG_CasteBodyparts->getOffset ("layers_vector"); // unused
+ bodypart_singular_offset = OG_CasteBodyparts->getOffset ("singular_vector"); // unused
+ bodypart_plural_offset = OG_CasteBodyparts->getOffset ("plural_vector"); // unused
+ OffsetGroup * OG_CasteColorMods = OG_Creature->getGroup("caste_color_mods");
+ color_modifier_part_offset = OG_CasteColorMods->getOffset ("part");
+ color_modifier_startdate_offset = OG_CasteColorMods->getOffset ("startdate");
+ color_modifier_enddate_offset = OG_CasteColorMods->getOffset ("enddate");
+ have_advanced = true;
+ }
+ catch (Error::All &){};
+
uint32_t size = p_races.size();
uint32_t sizecas = 0;
uint32_t sizecolormod;
uint32_t sizecolorlist;
uint32_t sizebp;
- uint32_t tile_offset = mem->getOffset ("creature_tile");
- uint32_t tile_color_offset = mem->getOffset ("creature_tile_color");
raceEx.clear();
raceEx.reserve (size);
for (uint32_t i = 0; i < size;i++)
@@ -338,13 +384,13 @@ bool Materials::ReadCreatureTypesEx (void)
// char tile_character AT tile_offset,
// word tilecolor.fore : tile_color_offset,
// word tilecolor.back : tile_color_offset + 2,
- // word tilecolor.bright : tile_color_offset + 4
+ // word tilecolor.bright : tile_color_offset + 4
p->readSTLString (p_races[i], mat.rawname, sizeof(mat.rawname));
mat.tile_character = p->readByte( p_races[i] + tile_offset );
mat.tilecolor.fore = p->readWord( p_races[i] + tile_color_offset );
mat.tilecolor.back = p->readWord( p_races[i] + tile_color_offset + 2 );
mat.tilecolor.bright = p->readWord( p_races[i] + tile_color_offset + 4 );
-
+
DfVector p_castes(p, p_races[i] + castes_vector_offset);
sizecas = p_castes.size();
for (uint32_t j = 0; j < sizecas;j++)
@@ -356,38 +402,36 @@ bool Materials::ReadCreatureTypesEx (void)
p->readSTLString (caste_start + sizeof_string, caste.singular, sizeof(caste.singular));
p->readSTLString (caste_start + 2 * sizeof_string, caste.plural, sizeof(caste.plural));
p->readSTLString (caste_start + 3 * sizeof_string, caste.adjective, sizeof(caste.adjective));
-
- /* color mod reading */
- DfVector 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 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 p_bodypart(p, caste_start + caste_bodypart_offset);
- caste.bodypart.empty();
- sizebp = p_bodypart.size();
- for(uint32_t k = 0; k < sizebp; k++)
+ if(have_advanced)
{
- 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);
+ /* color mod reading */
+ DfVector 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 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 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);
}
DfVector p_extract(p, p_races[i] + extract_vector_offset);
@@ -411,7 +455,7 @@ void Materials::ReadAllMaterials(void)
this->ReadCreatureTypes();
this->ReadCreatureTypesEx();
this->ReadDescriptorColors();
- this->ReadOthers();
+ //this->ReadOthers();
}
std::string Materials::getDescription(t_material & mat)
@@ -504,7 +548,7 @@ std::string Materials::getType(t_material & mat)
}
}
}
- else
+ else
return "inorganic";
}
else
diff --git a/library/modules/Materials_C.cpp b/library/modules/Materials_C.cpp
index f95c4e76c..4fa8b7705 100644
--- a/library/modules/Materials_C.cpp
+++ b/library/modules/Materials_C.cpp
@@ -116,6 +116,18 @@ void Materials_ReadAllMaterials(DFHackObject* mat)
}
}
+const char* Materials_getType(DFHackObject* mat, t_material* material)
+{
+ if(mat != NULL)
+ {
+ std::string type = ((DFHack::Materials*)mat)->getType(*material);
+
+ return type.c_str();
+ }
+
+ return "\0";
+}
+
const char* Materials_getDescription(DFHackObject* mat, t_material* material)
{
if(mat != NULL)
diff --git a/library/modules/Position.cpp b/library/modules/Position.cpp
index ab3fccba3..7442d9ddb 100644
--- a/library/modules/Position.cpp
+++ b/library/modules/Position.cpp
@@ -25,8 +25,9 @@ distribution.
#include "Internal.h"
#include "ContextShared.h"
#include "dfhack/modules/Position.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
+#include "dfhack/DFError.h"
using namespace DFHack;
struct Position::Private
@@ -41,7 +42,7 @@ struct Position::Private
uint32_t hotkey_mode_offset;
uint32_t hotkey_xyz_offset;
uint32_t hotkey_size;
-
+
uint32_t screen_tiles_ptr_offset;
DFContextShared *d;
@@ -59,33 +60,36 @@ Position::Position(DFContextShared * d_)
d->owner = d_->p;
d->Inited = true;
d->StartedHotkeys = d->Started = d->StartedScreen = false;
- memory_info * mem;
+ OffsetGroup * OG_Position;
+ VersionInfo * mem = d->d->offset_descriptor;
+ // this is how to do feature detection properly
try
{
- mem = d->d->offset_descriptor;
- d->window_x_offset = mem->getAddress ("window_x");
- d->window_y_offset = mem->getAddress ("window_y");
- d->window_z_offset = mem->getAddress ("window_z");
- d->cursor_xyz_offset = mem->getAddress ("cursor_xyz");
- d->window_dims_offset = mem->getAddress ("window_dims");
+ OG_Position = mem->getGroup("Position");
+ d->window_x_offset = OG_Position->getAddress ("window_x");
+ d->window_y_offset = OG_Position->getAddress ("window_y");
+ d->window_z_offset = OG_Position->getAddress ("window_z");
+ d->cursor_xyz_offset = OG_Position->getAddress ("cursor_xyz");
+ d->window_dims_offset = OG_Position->getAddress ("window_dims");
d->Started = true;
}
- catch(exception &){};
+ catch(Error::All &){};
try
{
- d->hotkey_start = mem->getAddress("hotkey_start");
- d->hotkey_mode_offset = mem->getOffset ("hotkey_mode");
- d->hotkey_xyz_offset = mem->getOffset("hotkey_xyz");
- d->hotkey_size = mem->getHexValue("hotkey_size");
+ OffsetGroup * OG_Hotkeys = mem->getGroup("Hotkeys");
+ d->hotkey_start = OG_Hotkeys->getAddress("start");
+ d->hotkey_mode_offset = OG_Hotkeys->getOffset ("mode");
+ d->hotkey_xyz_offset = OG_Hotkeys->getOffset("coords");
+ d->hotkey_size = OG_Hotkeys->getHexValue("size");
d->StartedHotkeys = true;
}
- catch(exception &){};
+ catch(Error::All &){};
try
{
- d->screen_tiles_ptr_offset = mem->getAddress ("screen_tiles_pointer");
+ d->screen_tiles_ptr_offset = OG_Position->getAddress ("screen_tiles_pointer");
d->StartedScreen = true;
}
- catch(exception &){};
+ catch(Error::All &){};
}
Position::~Position()
@@ -176,9 +180,7 @@ bool Position::getScreenTiles (int32_t width, int32_t height, t_screen screen[])
if(!d->Inited) return false;
if(!d->StartedScreen) return false;
- uint32_t screen_addr;
- d->owner->read (d->screen_tiles_ptr_offset, sizeof(uint32_t), (uint8_t *) screen_addr);
-
+ uint32_t screen_addr = d->owner->readDWord(d->screen_tiles_ptr_offset);
uint8_t* tiles = new uint8_t[width*height*4/* + 80 + width*height*4*/];
d->owner->read (screen_addr, (width*height*4/* + 80 + width*height*4*/), (uint8_t *) tiles);
@@ -187,10 +189,10 @@ bool Position::getScreenTiles (int32_t width, int32_t height, t_screen screen[])
{
for(int32_t ix=0; ixReadHotkeys(buf))
+ return buf;
+ else
+ return NULL;
+ }
+ else
+ return NULL;
+ }
+
+ return NULL;
+}
+
int Position_getWindowSize(DFHackObject* pos, int32_t* width, int32_t* height)
{
if(pos != NULL)
@@ -117,6 +140,26 @@ int Position_getWindowSize(DFHackObject* pos, int32_t* width, int32_t* height)
return -1;
}
+t_screen* Position_getScreenTiles(DFHackObject* pos, int32_t width, int32_t height)
+{
+ if(pos != NULL)
+ {
+ t_screen* buf;
+
+ (*alloc_t_screen_buffer_callback)(buf, width * height);
+
+ if(buf == NULL)
+ return NULL;
+
+ if(((DFHack::Position*)pos)->getScreenTiles(width, height, buf))
+ return buf;
+ else
+ return NULL;
+ }
+
+ return NULL;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/library/modules/Translation.cpp b/library/modules/Translation.cpp
index ae0c8b7ed..ba6018d55 100644
--- a/library/modules/Translation.cpp
+++ b/library/modules/Translation.cpp
@@ -25,7 +25,7 @@ distribution.
#include "Internal.h"
#include "ContextShared.h"
#include "dfhack/modules/Translation.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFTypes.h"
@@ -38,10 +38,10 @@ struct Translation::Private
uint32_t transAddress;
uint32_t word_table_offset;
uint32_t sizeof_string;
-
+
// translation
Dicts dicts;
-
+
DFContextShared *d;
bool Inited;
bool Started;
@@ -52,11 +52,12 @@ Translation::Translation(DFContextShared * d_)
d = new Private;
d->d = d_;
d->Inited = d->Started = false;
- memory_info * mem = d->d->offset_descriptor;
- d->genericAddress = mem->getAddress ("language_vector");
- d->transAddress = mem->getAddress ("translation_vector");
- d->word_table_offset = mem->getOffset ("word_table");
- d->sizeof_string = mem->getHexValue ("sizeof_string");
+ OffsetGroup * OG_Translation = d->d->offset_descriptor->getGroup("Translations");
+ OffsetGroup * OG_String = d->d->offset_descriptor->getGroup("string");
+ d->genericAddress = OG_Translation->getAddress ("language_vector");
+ d->transAddress = OG_Translation->getAddress ("translation_vector");
+ d->word_table_offset = OG_Translation->getOffset ("word_table");
+ d->sizeof_string = OG_String->getHexValue ("sizeof");
d->Inited = true;
}
@@ -116,7 +117,7 @@ bool Translation::Finish()
Dicts * Translation::getDicts()
{
assert(d->Started);
-
+
if(d->Started)
return &d->dicts;
return 0;
@@ -126,10 +127,10 @@ string Translation::TranslateName(const t_name &name, bool inEnglish)
{
string out;
assert (d->Started);
-
+
map >::const_iterator it;
- if(!inEnglish)
+ if(!inEnglish)
{
if(name.words[0] >=0 || name.words[1] >=0)
{
@@ -137,7 +138,7 @@ string Translation::TranslateName(const t_name &name, bool inEnglish)
if(name.words[1]>=0) out.append(d->dicts.foreign_languages[name.language][name.words[1]]);
out[0] = toupper(out[0]);
}
- if(name.words[5] >=0)
+ if(name.words[5] >=0)
{
string word;
for(int i=2;i<=5;i++)
@@ -146,7 +147,7 @@ string Translation::TranslateName(const t_name &name, bool inEnglish)
if(out.length() > 0) out.append(" ");
out.append(word);
}
- if(name.words[6] >=0)
+ if(name.words[6] >=0)
{
string word;
word.append(d->dicts.foreign_languages[name.language][name.words[6]]);
@@ -154,7 +155,7 @@ string Translation::TranslateName(const t_name &name, bool inEnglish)
if(out.length() > 0) out.append(" ");
out.append(word);
}
- }
+ }
else
{
if(name.words[0] >=0 || name.words[1] >=0)
@@ -163,7 +164,7 @@ string Translation::TranslateName(const t_name &name, bool inEnglish)
if(name.words[1]>=0) out.append(d->dicts.translations[name.parts_of_speech[1]+1][name.words[1]]);
out[0] = toupper(out[0]);
}
- if(name.words[5] >=0)
+ if(name.words[5] >=0)
{
if(out.length() > 0)
out.append(" the");
@@ -180,7 +181,7 @@ string Translation::TranslateName(const t_name &name, bool inEnglish)
}
}
}
- if(name.words[6] >=0)
+ if(name.words[6] >=0)
{
if(out.length() > 0)
out.append(" of");
diff --git a/library/modules/Vegetation.cpp b/library/modules/Vegetation.cpp
index 6038e4d53..cceff66ef 100644
--- a/library/modules/Vegetation.cpp
+++ b/library/modules/Vegetation.cpp
@@ -25,7 +25,7 @@ distribution.
#include "Internal.h"
#include "ContextShared.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFTypes.h"
@@ -40,7 +40,7 @@ struct Vegetation::Private
uint32_t tree_desc_offset;
// translation
DfVector * p_veg;
-
+
DFContextShared *d;
Process * owner;
bool Inited;
@@ -53,9 +53,9 @@ Vegetation::Vegetation(DFContextShared * d_)
d->owner = d_->p;
d->d = d_;
d->Inited = d->Started = false;
- memory_info * mem = d->d->offset_descriptor;
- d->vegetation_vector = mem->getAddress ("vegetation_vector");
- d->tree_desc_offset = mem->getOffset ("tree_desc_offset");
+ OffsetGroup * OG_Veg = d->d->offset_descriptor->getGroup("Vegetation");
+ d->vegetation_vector = OG_Veg->getAddress ("vector");
+ d->tree_desc_offset = OG_Veg->getOffset ("tree_desc_offset");
d->Inited = true;
}
@@ -68,6 +68,8 @@ Vegetation::~Vegetation()
bool Vegetation::Start(uint32_t & numplants)
{
+ if(!d->Inited)
+ return false;
d->p_veg = new DfVector (d->owner, d->vegetation_vector);
numplants = d->p_veg->size();
d->Started = true;
diff --git a/library/modules/World.cpp b/library/modules/World.cpp
index 92c8606d4..3e1a670de 100644
--- a/library/modules/World.cpp
+++ b/library/modules/World.cpp
@@ -38,32 +38,47 @@ FIXME: Japa said that he had to do this with the time stuff he got from here
#include "ContextShared.h"
#include "dfhack/modules/World.h"
#include "dfhack/DFProcess.h"
-#include "dfhack/DFMemInfo.h"
+#include "dfhack/VersionInfo.h"
#include "dfhack/DFTypes.h"
+#include "dfhack/DFError.h"
using namespace DFHack;
struct World::Private
{
bool Inited;
- bool Started;
+ bool StartedTime;
+ bool StartedWeather;
uint32_t year_offset;
uint32_t tick_offset;
+ uint32_t weather_offset;
DFContextShared *d;
Process * owner;
};
World::World(DFContextShared * _d)
{
-
+
d = new Private;
d->d = _d;
d->owner = _d->p;
-
- memory_info * mem = d->d->offset_descriptor;
- d->year_offset = mem->getAddress( "current_year" );
- d->tick_offset = mem->getAddress( "current_tick" );
- d->Inited = d->Started = true;
+ d->Inited = d->StartedTime = d->StartedWeather = false;
+
+ OffsetGroup * OG_World = d->d->offset_descriptor->getGroup("World");
+ try
+ {
+ d->year_offset = OG_World->getAddress( "current_year" );
+ d->tick_offset = OG_World->getAddress( "current_tick" );
+ d->StartedTime = true;
+ }
+ catch(Error::All &){};
+ try
+ {
+ d->weather_offset = OG_World->getAddress( "current_weather" );
+ d->StartedWeather = true;
+ }
+ catch(Error::All &){};
+ d->Inited = true;
}
World::~World()
@@ -83,19 +98,19 @@ bool World::Finish()
uint32_t World::ReadCurrentYear()
{
- if(d->Inited)
+ if(d->Inited && d->StartedTime)
return(d->owner->readDWord(d->year_offset));
return 0;
}
uint32_t World::ReadCurrentTick()
{
- if(d->Inited)
+ if(d->Inited && d->StartedTime)
return(d->owner->readDWord(d->tick_offset));
return 0;
}
-// FIX'D according to this:
+// FIX'D according to this:
/*
World::ReadCurrentMonth and World::ReadCurrentDay
« Sent to: peterix on: June 04, 2010, 04:44:30 »
@@ -114,3 +129,26 @@ uint32_t World::ReadCurrentDay()
{
return ((this->ReadCurrentTick() / 1200) % 28) + 1;
}
+
+uint8_t World::ReadCurrentWeather()
+{
+ if (d->Inited && d->StartedWeather)
+ return(d->owner->readByte(d->weather_offset + 12));
+ return 0;
+}
+/*
+void World::SetCurrentWeather(uint8_t weather)
+{
+ if (d->Inited && d->StartedWeather)
+ d->owner->writeByte(d->weather_offset,weather);
+}
+*/
+void World::SetCurrentWeather(uint8_t weather)
+{
+ if (d->Inited && d->StartedWeather)
+ {
+ uint8_t buf[25];
+ memset(&buf,weather, sizeof(buf));
+ d->owner->write(d->weather_offset,sizeof(buf),buf);
+ }
+}
diff --git a/library/modules/World_C.cpp b/library/modules/World_C.cpp
index a5be3bcd0..6aa0b320f 100644
--- a/library/modules/World_C.cpp
+++ b/library/modules/World_C.cpp
@@ -39,7 +39,7 @@ int World_Start(DFHackObject* world)
else
return 0;
}
-
+
return -1;
}
@@ -52,7 +52,7 @@ int World_Finish(DFHackObject* world)
else
return 0;
}
-
+
return -1;
}
@@ -63,7 +63,7 @@ int World_ReadCurrentTick(DFHackObject* world, uint32_t* tick)
*tick = ((DFHack::World*)world)->ReadCurrentTick();
return 1;
}
-
+
return -1;
}
@@ -74,7 +74,7 @@ int World_ReadCurrentYear(DFHackObject* world, uint32_t* year)
*year = ((DFHack::World*)world)->ReadCurrentYear();
return 1;
}
-
+
return -1;
}
@@ -85,7 +85,7 @@ int World_ReadCurrentMonth(DFHackObject* world, uint32_t* month)
*month = ((DFHack::World*)world)->ReadCurrentMonth();
return 1;
}
-
+
return -1;
}
@@ -96,10 +96,32 @@ int World_ReadCurrentDay(DFHackObject* world, uint32_t* day)
*day = ((DFHack::World*)world)->ReadCurrentDay();
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
}
#endif
diff --git a/library/private/ContextShared.h b/library/private/ContextShared.h
index 361ccc45d..89403836c 100644
--- a/library/private/ContextShared.h
+++ b/library/private/ContextShared.h
@@ -48,7 +48,7 @@ namespace DFHack
class ProcessEnumerator;
class Process;
- class memory_info;
+ class VersionInfo;
struct t_name;
class DFContextShared
{
@@ -68,7 +68,7 @@ namespace DFHack
ProcessEnumerator* pm;
Process* p;
char * shm_start;
- memory_info* offset_descriptor;
+ VersionInfo* offset_descriptor;
string xml;
// Modules
diff --git a/library/shm/mod-creature2010.h b/library/shm/mod-creature2010.h
index f52122127..64a9936a6 100644
--- a/library/shm/mod-creature2010.h
+++ b/library/shm/mod-creature2010.h
@@ -67,6 +67,7 @@ typedef struct
uint32_t appearance_vector_offset;
uint32_t birth_year_offset;
uint32_t birth_time_offset;
+ uint32_t inventory_offset;
} creature_offsets;
typedef struct
diff --git a/tools/examples/CMakeLists.txt b/tools/examples/CMakeLists.txt
index 05d03e3d8..251efe49c 100644
--- a/tools/examples/CMakeLists.txt
+++ b/tools/examples/CMakeLists.txt
@@ -1,8 +1,5 @@
# don't use this file directly. use the one in the root folder of the project
-# only build this stuff when BUILD_DFHACK_EXAMPLES is set to ON
-IF (BUILD_DFHACK_EXAMPLES)
-
# this is required to ensure we use the right configuration for the system.
IF(UNIX)
add_definitions(-DLINUX_BUILD)
@@ -61,5 +58,4 @@ dftreedump
dfspatterdump
dfprocessenum
RUNTIME DESTINATION bin
-)
-ENDIF (BUILD_DFHACK_EXAMPLES)
\ No newline at end of file
+)
\ No newline at end of file
diff --git a/tools/examples/buildingsdump.cpp b/tools/examples/buildingsdump.cpp
index bfb747685..1d7e20709 100644
--- a/tools/examples/buildingsdump.cpp
+++ b/tools/examples/buildingsdump.cpp
@@ -54,7 +54,7 @@ int main (int argc,const char* argv[])
return 1;
}
- DFHack::memory_info * mem = DF->getMemoryInfo();
+ DFHack::VersionInfo * mem = DF->getMemoryInfo();
DFHack::Buildings * Bld = DF->getBuildings();
DFHack::Position * Pos = DF->getPosition();
diff --git a/tools/examples/creaturedump.cpp b/tools/examples/creaturedump.cpp
index 81fc3da8d..dddd6e018 100644
--- a/tools/examples/creaturedump.cpp
+++ b/tools/examples/creaturedump.cpp
@@ -19,7 +19,7 @@ enum likeType
};
DFHack::Materials * Materials;
-DFHack::memory_info *mem;
+DFHack::VersionInfo *mem;
vector< vector > englishWords;
vector< vector > foreignWords;
DFHack::Creatures * Creatures = NULL;
@@ -134,7 +134,7 @@ likeType printLike40d(DFHack::t_like like, const matGlosses & mat,const vector<
void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature)
{
uint32_t dayoflife;
- cout << "address: " << hex << creature.origin << dec << " creature type: " << Materials->raceEx[creature.race].rawname
+ cout << "address: " << hex << creature.origin << dec << ", creature race: " << creature.race << "/" << Materials->raceEx[creature.race].rawname
<< "[" << Materials->raceEx[creature.race].tile_character
<< "," << Materials->raceEx[creature.race].tilecolor.fore
<< "," << Materials->raceEx[creature.race].tilecolor.back
@@ -154,7 +154,7 @@ void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature)
}
DFHack::Translation *Tran = DF->getTranslation();
- DFHack::memory_info *mem = DF->getMemoryInfo();
+ DFHack::VersionInfo *mem = DF->getMemoryInfo();
string transName = Tran->TranslateName(creature.name,false);
if(!transName.empty())
@@ -172,7 +172,7 @@ void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature)
if(creature.civ)
{
- cout << "civilization: " << creature.civ;
+ cout << ", civilization: " << creature.civ;
addendl = true;
}
@@ -191,7 +191,7 @@ void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature)
cout << endl;
addendl = false;
}
- cout << "profession: " << mem->getProfession(creature.profession) << "(" << (int) creature.profession << ")";
+ cout << ", profession: " << mem->getProfession(creature.profession) << "(" << (int) creature.profession << ")";
if(creature.custom_profession[0])
{
@@ -271,6 +271,20 @@ void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature)
}
}
+ //std::vector inventory;
+ // FIXME: TOO BAD...
+ /*
+ if( Creatures->ReadInventoryPtr(creature.origin, inventory) )
+ {
+ DFHack::Items * Items = DF->getItems();
+ printf("\tInventory:\n");
+ for(unsigned int i = 0; i < inventory.size(); i++)
+ {
+ printf("\t\t%s\n", Items->getItemDescription(inventory[i], Materials).c_str());
+ }
+ }
+ */
+
/*
if(creature.pregnancy_timer > 0)
cout << "gives birth in " << creature.pregnancy_timer/1200 << " days. ";
@@ -439,8 +453,14 @@ int main (int numargs, char ** args)
}
mem = DF->getMemoryInfo();
- Materials->ReadAllMaterials();
-
+ Materials->ReadInorganicMaterials();
+ Materials->ReadOrganicMaterials();
+ Materials->ReadWoodMaterials();
+ Materials->ReadPlantMaterials();
+ Materials->ReadCreatureTypes();
+ Materials->ReadCreatureTypesEx();
+ Materials->ReadDescriptorColors();
+
if(!Tran->Start())
{
cerr << "Can't get name tables" << endl;
@@ -450,6 +470,7 @@ int main (int numargs, char ** args)
//DF.InitViewAndCursor();
for(uint32_t i = 0; i < numCreatures; i++)
{
+ printf("%d/%d\n", i, numCreatures);
DFHack::t_creature temp;
Creatures->ReadCreature(i,temp);
if(check.empty() || string(Materials->raceEx[temp.race].rawname) == check)
@@ -459,6 +480,7 @@ int main (int numargs, char ** args)
printCreature(DF,temp);
addrs.push_back(temp.origin);
}
+ printf("!\n");
}
if(addrs.size() <= 10)
{
@@ -473,6 +495,7 @@ int main (int numargs, char ** args)
DF.ReadCreature(currentIdx, currentCreature);
printCreature(DF,currentCreature);
*/
+
Creatures->Finish();
DF->Detach();
#ifndef LINUX_BUILD
diff --git a/tools/examples/dfitemdump.cpp b/tools/examples/dfitemdump.cpp
index cf1778326..f3a3dd39e 100644
--- a/tools/examples/dfitemdump.cpp
+++ b/tools/examples/dfitemdump.cpp
@@ -37,7 +37,7 @@ int main ()
return 1;
}
- DFHack::memory_info * mem = DF->getMemoryInfo();
+ DFHack::VersionInfo * mem = DF->getMemoryInfo();
Materials = DF->getMaterials();
Materials->ReadAllMaterials();
p = DF->getProcess();
diff --git a/tools/examples/hotkeynotedump.cpp b/tools/examples/hotkeynotedump.cpp
index 2e35f2796..405498a4d 100644
--- a/tools/examples/hotkeynotedump.cpp
+++ b/tools/examples/hotkeynotedump.cpp
@@ -25,7 +25,7 @@ int main (void)
return 1;
}
- DFHack::memory_info * mem = DF->getMemoryInfo();
+ DFHack::VersionInfo * mem = DF->getMemoryInfo();
DFHack::Position * Pos = DF->getPosition();
// get stone matgloss mapping
/*
diff --git a/tools/examples/materialtest.cpp b/tools/examples/materialtest.cpp
index 65426e4ba..c1b02063b 100644
--- a/tools/examples/materialtest.cpp
+++ b/tools/examples/materialtest.cpp
@@ -35,7 +35,7 @@ int main (int numargs, const char ** args)
}
DFHack::Process* p = DF->getProcess();
- DFHack::memory_info* mem = DF->getMemoryInfo();
+ DFHack::VersionInfo* mem = DF->getMemoryInfo();
DFHack::Materials *Materials = DF->getMaterials();
cout << "----==== Inorganic ====----" << endl;
diff --git a/tools/examples/processenum.cpp b/tools/examples/processenum.cpp
index 745e94371..425b247e4 100644
--- a/tools/examples/processenum.cpp
+++ b/tools/examples/processenum.cpp
@@ -56,7 +56,7 @@ int main (void)
{
cout << "Testing ProcessEnumerator" << endl;
ProcessEnumerator Penum("Memory.xml");
- memory_info * mem;
+ VersionInfo * mem;
do
{
// make the ProcessEnumerator update its list of Processes
@@ -90,7 +90,7 @@ int main (void)
{
cout << "Testing ContextManager" << endl;
ContextManager Cman("Memory.xml");
- memory_info * mem;
+ VersionInfo * mem;
do
{
// make the ContextManager update its list of Contexts
diff --git a/tools/examples/treedump.cpp b/tools/examples/treedump.cpp
index 71b386220..410587173 100644
--- a/tools/examples/treedump.cpp
+++ b/tools/examples/treedump.cpp
@@ -37,7 +37,7 @@ int main (int numargs, const char ** args)
}
DFHack::Process* p = DF->getProcess();
- DFHack::memory_info* mem = DF->getMemoryInfo();
+ DFHack::VersionInfo* mem = DF->getMemoryInfo();
DFHack::Position * pos = DF->getPosition();
DFHack::Vegetation * v = DF->getVegetation();
DFHack::Materials * mat = DF->getMaterials();
diff --git a/tools/playground/CMakeLists.txt b/tools/playground/CMakeLists.txt
index a28597475..ab21e3c2d 100644
--- a/tools/playground/CMakeLists.txt
+++ b/tools/playground/CMakeLists.txt
@@ -1,8 +1,5 @@
# don't use this file directly. use the one in the root folder of the project
-# only build this stuff when BUILD_DFHACK_PLAYGROUND is set to ON
-IF (BUILD_DFHACK_PLAYGROUND)
-
# this is required to ensure we use the right configuration for the system.
IF(UNIX)
add_definitions(-DLINUX_BUILD)
@@ -56,8 +53,15 @@ TARGET_LINK_LIBRARIES(dfcatsplosion dfhack)
#ADD_EXECUTABLE(dfrenamer renamer.cpp)
#TARGET_LINK_LIBRARIES(dfrenamer dfhack)
+# copypaste
+# Author: belal
+# copies the current buildings in a df map, and then designates the area to be dug
+# mainly a proof of concept for my gui application dfCopyPaste
+ADD_EXECUTABLE(dfcopypaste copypaste.cpp)
+TARGET_LINK_LIBRARIES(dfcopypaste dfhack)
+
# this needs the C bindings
-IF(BUILD_DFHACK_C_BINDIGS)
+IF(BUILD_DFHACK_C_BINDINGS)
# for trying out some 'stuff'
ADD_EXECUTABLE(dftest test.cpp)
TARGET_LINK_LIBRARIES(dftest dfhack)
@@ -65,7 +69,7 @@ IF(BUILD_DFHACK_C_BINDIGS)
dftest
RUNTIME DESTINATION bin
)
-ENDIF(BUILD_DFHACK_C_BINDIGS)
+ENDIF(BUILD_DFHACK_C_BINDINGS)
install(TARGETS
dfmoodump
@@ -80,4 +84,3 @@ IF(UNIX)
RUNTIME DESTINATION bin
)
ENDIF(UNIX)
-ENDIF (BUILD_DFHACK_PLAYGROUND)
\ No newline at end of file
diff --git a/tools/playground/SegmentedFinder.h b/tools/playground/SegmentedFinder.h
index c50cc4c6f..98de87711 100644
--- a/tools/playground/SegmentedFinder.h
+++ b/tools/playground/SegmentedFinder.h
@@ -311,4 +311,11 @@ bool findString (SegmentedFinder* s, uint32_t *addr, const char * compare )
return false;
}
+bool findStrBuffer (SegmentedFinder* s, uint32_t *addr, const char * compare )
+{
+ if(strcmp((const char *)addr, compare) == 0)
+ return true;
+ return false;
+}
+
#endif // SEGMENTED_FINDER_H
\ No newline at end of file
diff --git a/tools/playground/catsplosion.cpp b/tools/playground/catsplosion.cpp
index 08d5c8961..c3c0126d2 100644
--- a/tools/playground/catsplosion.cpp
+++ b/tools/playground/catsplosion.cpp
@@ -21,7 +21,7 @@ using namespace DFHack;
int main ( int argc, char** argv )
{
- DFHack::memory_info *mem;
+ DFHack::VersionInfo *mem;
DFHack::Process *proc;
uint32_t creature_pregnancy_offset;
diff --git a/tools/playground/copypaste.cpp b/tools/playground/copypaste.cpp
new file mode 100644
index 000000000..dd304d5e9
--- /dev/null
+++ b/tools/playground/copypaste.cpp
@@ -0,0 +1,449 @@
+// Console version of DF copy paste, proof of concept
+// By belal
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DFHACK_WANT_MISCUTILS
+#define DFHACK_WANT_TILETYPES
+#include
+#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 > >vec,char sep){
+ for(int k=0;k 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 > >dig(cz2-cz1+1,vector >(cy2-cy1+1,vector(cx2-cx1+1)));
+ vector > >build(cz2-cz1+1,vector >(cy2-cy1+1,vector