code moved from khazad
							parent
							
								
									52f768f6c5
								
							
						
					
					
						commit
						fac88478bd
					
				@ -0,0 +1,30 @@
 | 
			
		||||
# main project file. use it from a build sub-folder, see COMPILE for details
 | 
			
		||||
PROJECT (dfhack) 
 | 
			
		||||
cmake_minimum_required(VERSION 2.6)
 | 
			
		||||
 | 
			
		||||
# disable warning, autosearch
 | 
			
		||||
if(COMMAND cmake_policy)
 | 
			
		||||
  cmake_policy(SET CMP0003 NEW)
 | 
			
		||||
endif(COMMAND cmake_policy)
 | 
			
		||||
 | 
			
		||||
if("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}")
 | 
			
		||||
   message(SEND_ERROR "In-source builds are not allowed.")
 | 
			
		||||
endif("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}")
 | 
			
		||||
 | 
			
		||||
IF(NOT DEFINED CMAKE_BUILD_TYPE)
 | 
			
		||||
  SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
 | 
			
		||||
ENDIF(NOT DEFINED CMAKE_BUILD_TYPE)
 | 
			
		||||
 | 
			
		||||
SET(SO_MAJOR_VERSION "0")
 | 
			
		||||
SET(SO_MINOR_VERSION "0")
 | 
			
		||||
SET(SO_BUILD_VERSION "1")
 | 
			
		||||
SET(SO_VERSION "${SO_MAJOR_VERSION}.${SO_MINOR_VERSION}.${SO_BUILD_VERSION}")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SET( LIBRARY_OUTPUT_PATH ${dfhack_SOURCE_DIR}/output CACHE PATH "Output directory for the dfhack library" )
 | 
			
		||||
SET( EXECUTABLE_OUTPUT_PATH ${dfhack_SOURCE_DIR}/output CACHE PATH "Output directory for the dfhack tools" )
 | 
			
		||||
 | 
			
		||||
include_directories (${CMAKE_SOURCE_DIR}/library/)
 | 
			
		||||
 | 
			
		||||
add_subdirectory (library)
 | 
			
		||||
add_subdirectory (tools)
 | 
			
		||||
@ -0,0 +1,55 @@
 | 
			
		||||
Here's how you build dfhack!
 | 
			
		||||
----------------------------
 | 
			
		||||
 | 
			
		||||
First, there is one dependency:
 | 
			
		||||
  cmake - it's the build system
 | 
			
		||||
 | 
			
		||||
building the library is simple. Enter the build folder, run th tools. Like this:
 | 
			
		||||
  cd build
 | 
			
		||||
  cmake .. -DCMAKE_BUILD_TYPE:string=Release
 | 
			
		||||
  make
 | 
			
		||||
 | 
			
		||||
Changing folder to build and using 'cmake ..' is important!
 | 
			
		||||
 | 
			
		||||
This will build the library and its tools and place them in /output.
 | 
			
		||||
You can also use a cmake-friendly IDE like KDevelop 4 or the cmake GUI program.
 | 
			
		||||
 | 
			
		||||
Building on Windows:
 | 
			
		||||
--------------------
 | 
			
		||||
 | 
			
		||||
You need cmake. Get the win32 installer version from the official site: http://www.cmake.org/cmake/resources/software.html
 | 
			
		||||
It has the usual installer wizard thing.
 | 
			
		||||
 | 
			
		||||
* Using mingw:
 | 
			
		||||
 | 
			
		||||
You also need a compiler. I build dfhack using mingw. You can get it from the mingw site:
 | 
			
		||||
Get the automated installer, it will download newest version of mingw and set things up nicely.
 | 
			
		||||
You'll have to add C:\MinGW\ to your PATH variable.
 | 
			
		||||
 | 
			
		||||
 - Building:
 | 
			
		||||
 open up cmd and navigate to the dfhack\build folder, run cmake and the mingw version of make:
 | 
			
		||||
 cd build
 | 
			
		||||
 cmake .. -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE:string=Release
 | 
			
		||||
 mingw32-make
 | 
			
		||||
 | 
			
		||||
* Using some other compiler:
 | 
			
		||||
 | 
			
		||||
I'm afraid you are on your own. dfhack wasn't tested with any other compiler.
 | 
			
		||||
Try using a different cmake generator that's intended for your tools.
 | 
			
		||||
 | 
			
		||||
Build targets
 | 
			
		||||
-------------
 | 
			
		||||
dfhack has a few build targets. If you're only after the library run 'make dfhack'.
 | 
			
		||||
'make' will build everything.
 | 
			
		||||
'make expbench' will build the expbench throughput testing program and the library.
 | 
			
		||||
 | 
			
		||||
Build types
 | 
			
		||||
-----------
 | 
			
		||||
cmake allows you to pick a build type by changing this variable: CMAKE_BUILD_TYPE
 | 
			
		||||
 | 
			
		||||
cmake .. -DCMAKE_BUILD_TYPE:string=BUILD_TYPE
 | 
			
		||||
 | 
			
		||||
Without specifying a build type or 'None', cmake uses the CMAKE_CXX_FLAGS variable for building.
 | 
			
		||||
Valid build types include 'Release' and 'Debug'. There are others, but they aren't really that useful.
 | 
			
		||||
 | 
			
		||||
Have fun.
 | 
			
		||||
@ -0,0 +1,21 @@
 | 
			
		||||
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.
 | 
			
		||||
@ -0,0 +1,47 @@
 | 
			
		||||
Introduction
 | 
			
		||||
------------
 | 
			
		||||
DFHack is a Dwarf Fortress memory access library and a set of basic tools using this library.
 | 
			
		||||
The library is a work in progress, so things might change as more tools are written for it.
 | 
			
		||||
 | 
			
		||||
Getting DFHack
 | 
			
		||||
----------------
 | 
			
		||||
You can get the code or a release at DFHack's sourceforge site:
 | 
			
		||||
  https://sourceforge.net/projects/dfhack/
 | 
			
		||||
 | 
			
		||||
* subversion access: 
 | 
			
		||||
  svn co https://dfhack.svn.sourceforge.net/svnroot/dfhack/trunk dfhack 
 | 
			
		||||
 | 
			
		||||
Using the library
 | 
			
		||||
-----------------
 | 
			
		||||
The library should be compilable under Linux with GCC and under Windows with MinGW32
 | 
			
		||||
compiler. It is using the cmake build system. See COMPILE for details.
 | 
			
		||||
 | 
			
		||||
Main part of the API is in SimpleAPI.h
 | 
			
		||||
You might also have to include a few other files:
 | 
			
		||||
Types.h      - defines many of the used data structures
 | 
			
		||||
TileTypes.h  - functions for translating map tile type values to useful properties
 | 
			
		||||
               (wall, flooer, etc.)
 | 
			
		||||
 | 
			
		||||
Memory offset definitions
 | 
			
		||||
-------------------------
 | 
			
		||||
 | 
			
		||||
The file with memory offset definitions used by dfhack can be found in the output folder. 
 | 
			
		||||
TODO: write format explanation
 | 
			
		||||
 | 
			
		||||
Tools
 | 
			
		||||
-----
 | 
			
		||||
All the DFHack tools are terminal programs. This might seem strange to Windows users,
 | 
			
		||||
but they are meant mostly as examples for developers. Still, they can be useful and
 | 
			
		||||
are cross-platform just like the library itself.
 | 
			
		||||
 | 
			
		||||
* expbench   - just exports the map 1000 times over. Meant to test how fast the
 | 
			
		||||
               DFHack<->DF interface is. This should take 3-12 seconds.
 | 
			
		||||
               
 | 
			
		||||
* reveal     - plain old reveal tool. Demonstrates writing map data back to DF.
 | 
			
		||||
 | 
			
		||||
* prospector - scans the map for minerals. by default it only scans only visible veins.
 | 
			
		||||
               You can make it show hidden things with '-a' and base rock and soil layers
 | 
			
		||||
               with '-b'. These can be combined ('-ab')
 | 
			
		||||
               
 | 
			
		||||
* cleanmap   - cleans mud, vomit, snow and all kinds of bloody mess from the map. It will
 | 
			
		||||
               clean your irrigated farms too, so consider yourself warned.
 | 
			
		||||
@ -0,0 +1,3 @@
 | 
			
		||||
[Project]
 | 
			
		||||
Manager=KDevCMakeManager
 | 
			
		||||
Name=dfhack
 | 
			
		||||
@ -0,0 +1,25 @@
 | 
			
		||||
# don't use this file directly. use the one in the root folder of the project
 | 
			
		||||
 | 
			
		||||
SET(PROJECT_SRCS
 | 
			
		||||
DFDataModel.cpp
 | 
			
		||||
DFMemInfo.cpp
 | 
			
		||||
DFProcess.cpp
 | 
			
		||||
DFProcessManager.cpp
 | 
			
		||||
DFHackAPI.cpp
 | 
			
		||||
DFTileTypes.cpp
 | 
			
		||||
md5/md5.cpp
 | 
			
		||||
md5/md5wrapper.cpp
 | 
			
		||||
tinyxml/tinystr.cpp
 | 
			
		||||
tinyxml/tinyxml.cpp
 | 
			
		||||
tinyxml/tinyxmlerror.cpp
 | 
			
		||||
tinyxml/tinyxmlparser.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
IF(UNIX)
 | 
			
		||||
  add_definitions(-DLINUX_BUILD)
 | 
			
		||||
ELSE(UNIX)
 | 
			
		||||
  SET(PROJECT_LIBS psapi)
 | 
			
		||||
ENDIF(UNIX)
 | 
			
		||||
 | 
			
		||||
ADD_LIBRARY(dfhack SHARED ${PROJECT_SRCS})
 | 
			
		||||
TARGET_LINK_LIBRARIES(dfhack ${PROJECT_LIBS})
 | 
			
		||||
@ -0,0 +1,63 @@
 | 
			
		||||
/*
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef DFCOMMON_H_INCLUDED
 | 
			
		||||
#define DFCOMMON_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
///TODO: separate into extrenal and internal
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <map>
 | 
			
		||||
//#include <boost/bimap/bimap.hpp>
 | 
			
		||||
//using namespace boost::bimaps;
 | 
			
		||||
 | 
			
		||||
#include <fstream>
 | 
			
		||||
using namespace std;
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#ifdef LINUX_BUILD
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/ptrace.h>
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
#else
 | 
			
		||||
#define WINVER 0x0501					// OpenThread(), PSAPI, Toolhelp32
 | 
			
		||||
#define WIN32_LEAN_AND_MEAN
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
#include <winbase.h>
 | 
			
		||||
#include <winnt.h>
 | 
			
		||||
#include <psapi.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "DFTypes.h"
 | 
			
		||||
#include "DFDataModel.h"
 | 
			
		||||
#include "DFProcessManager.h"
 | 
			
		||||
#include "DFMemAccess.h"
 | 
			
		||||
#include "DFVector.h"
 | 
			
		||||
//#include "DfMap.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // DFCOMMON_H_INCLUDED
 | 
			
		||||
@ -0,0 +1,105 @@
 | 
			
		||||
/*
 | 
			
		||||
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 "DFCommon.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DfVector DMWindows40d::readVector (uint32_t offset, uint32_t item_size)
 | 
			
		||||
{
 | 
			
		||||
    /*
 | 
			
		||||
        MSVC++ vector is four pointers long
 | 
			
		||||
        ptr allocator
 | 
			
		||||
        ptr start
 | 
			
		||||
        ptr end
 | 
			
		||||
        ptr alloc_end
 | 
			
		||||
     
 | 
			
		||||
        we don't care about alloc_end because we don't try to add stuff
 | 
			
		||||
        we also don't care about the allocator thing in front
 | 
			
		||||
    */
 | 
			
		||||
    uint32_t start = MreadDWord(offset+4);
 | 
			
		||||
    uint32_t end = MreadDWord(offset+8);
 | 
			
		||||
    uint32_t size = (end - start) /4;
 | 
			
		||||
    return DfVector(start,size,item_size);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const string DMWindows40d::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 = MreadDWord(offset + 20);
 | 
			
		||||
    uint32_t capacity = MreadDWord(offset + 24);
 | 
			
		||||
    char * temp = new char[capacity+1];
 | 
			
		||||
    
 | 
			
		||||
    // read data from inside the string structure
 | 
			
		||||
    if(capacity < 16)
 | 
			
		||||
    {
 | 
			
		||||
        Mread(start_offset, capacity, (uint8_t *)temp);
 | 
			
		||||
    }
 | 
			
		||||
    else // read data from what the offset + 4 dword points to
 | 
			
		||||
    {
 | 
			
		||||
        start_offset = MreadDWord(start_offset);// dereference the start offset
 | 
			
		||||
        Mread(start_offset, capacity, (uint8_t *)temp);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    temp[length] = 0;
 | 
			
		||||
    string ret = temp;
 | 
			
		||||
    delete temp;
 | 
			
		||||
    return ret;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DfVector DMLinux40d::readVector (uint32_t offset, uint32_t item_size)
 | 
			
		||||
{
 | 
			
		||||
    /*
 | 
			
		||||
        GNU libstdc++ vector is three pointers long
 | 
			
		||||
        ptr start
 | 
			
		||||
        ptr end
 | 
			
		||||
        ptr alloc_end
 | 
			
		||||
 | 
			
		||||
        we don't care about alloc_end because we don't try to add stuff
 | 
			
		||||
    */
 | 
			
		||||
    uint32_t start = MreadDWord(offset);
 | 
			
		||||
    uint32_t end = MreadDWord(offset+4);
 | 
			
		||||
    uint32_t size = (end - start) /4;
 | 
			
		||||
    return DfVector(start,size,item_size);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const string DMLinux40d::readSTLString (uint32_t offset)
 | 
			
		||||
{
 | 
			
		||||
    // GNU std::string is a single pointer (as far as we are concerned)
 | 
			
		||||
    offset = MreadDWord(offset);
 | 
			
		||||
    return MreadCString(offset);
 | 
			
		||||
};
 | 
			
		||||
@ -0,0 +1,54 @@
 | 
			
		||||
/*
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef DATAMODEL_H_INCLUDED
 | 
			
		||||
#define DATAMODEL_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
class DfVector;
 | 
			
		||||
 | 
			
		||||
// let's go pure virtual.
 | 
			
		||||
class DataModel
 | 
			
		||||
{
 | 
			
		||||
    public:
 | 
			
		||||
    // read a string
 | 
			
		||||
    virtual const string readSTLString (uint32_t offset) = 0;
 | 
			
		||||
    // read a vector from memory
 | 
			
		||||
    virtual DfVector readVector (uint32_t offset, uint32_t item_size) = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DMWindows40d : public DataModel
 | 
			
		||||
{
 | 
			
		||||
    virtual const string readSTLString (uint32_t offset);
 | 
			
		||||
    // read a vector from memory
 | 
			
		||||
    virtual DfVector readVector (uint32_t offset, uint32_t item_size);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DMLinux40d : public DataModel
 | 
			
		||||
{
 | 
			
		||||
    virtual const string readSTLString (uint32_t offset);
 | 
			
		||||
    // read a vector from memory
 | 
			
		||||
    virtual DfVector readVector (uint32_t offset, uint32_t item_size);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // DATAMODEL_H_INCLUDED
 | 
			
		||||
@ -0,0 +1,596 @@
 | 
			
		||||
/*
 | 
			
		||||
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 "DFCommon.h"
 | 
			
		||||
#include "DFVector.h"
 | 
			
		||||
#include "DFHackAPI.h"
 | 
			
		||||
#include "DFMemInfo.h"
 | 
			
		||||
 | 
			
		||||
/* TODO: Test these
 | 
			
		||||
    ReadVegetation
 | 
			
		||||
    ReadConstruction
 | 
			
		||||
    ReadBuilding
 | 
			
		||||
    matgloss other than stone/soil
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// TODO: templating for vectors, simple copy constructor for stl vectors
 | 
			
		||||
// TODO: encapsulate access to multidimensional arrays.
 | 
			
		||||
 | 
			
		||||
DFHackAPI::DFHackAPI(const string path_to_xml)
 | 
			
		||||
{
 | 
			
		||||
    xml = path_to_xml;
 | 
			
		||||
    constructionsInited = false;
 | 
			
		||||
    buildingsInited = false;
 | 
			
		||||
    vegetationInited = false;
 | 
			
		||||
    pm = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------*
 | 
			
		||||
 *  Init the mapblock pointer array   *
 | 
			
		||||
 *-----------------------------------*/
 | 
			
		||||
bool DFHackAPI::InitMap()
 | 
			
		||||
{
 | 
			
		||||
    uint32_t    map_loc,   // location of the X array
 | 
			
		||||
                temp_loc,  // block location
 | 
			
		||||
                temp_locx, // iterator for the X array
 | 
			
		||||
                temp_locy, // iterator for the Y array
 | 
			
		||||
                temp_locz; // iterator for the Z array
 | 
			
		||||
    uint32_t map_offset = offset_descriptor->getAddress("map_data");
 | 
			
		||||
    uint32_t x_count_offset = offset_descriptor->getAddress("x_count");
 | 
			
		||||
    uint32_t y_count_offset = offset_descriptor->getAddress("y_count");
 | 
			
		||||
    uint32_t z_count_offset = offset_descriptor->getAddress("z_count");
 | 
			
		||||
 | 
			
		||||
    // get the offsets once here
 | 
			
		||||
    tile_type_offset = offset_descriptor->getOffset("type");
 | 
			
		||||
    designation_offset = offset_descriptor->getOffset("designation");
 | 
			
		||||
    occupancy_offset = offset_descriptor->getOffset("occupancy");
 | 
			
		||||
 | 
			
		||||
    // get the map pointer
 | 
			
		||||
    map_loc = MreadDWord(map_offset);
 | 
			
		||||
    if (!map_loc)
 | 
			
		||||
    {
 | 
			
		||||
        // bad stuffz happend
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // get the size
 | 
			
		||||
    x_block_count = MreadDWord(x_count_offset);
 | 
			
		||||
    y_block_count = MreadDWord(y_count_offset);
 | 
			
		||||
    z_block_count = MreadDWord(z_count_offset);
 | 
			
		||||
 | 
			
		||||
    // alloc array for pinters to all blocks
 | 
			
		||||
    block = new uint32_t[x_block_count*y_block_count*z_block_count];
 | 
			
		||||
 | 
			
		||||
    //read the memory from the map blocks - x -> map slice
 | 
			
		||||
    for(uint32_t x = 0; x < x_block_count; x++)
 | 
			
		||||
    {
 | 
			
		||||
        temp_locx = map_loc + ( 4 * x );
 | 
			
		||||
        temp_locy = MreadDWord(temp_locx);
 | 
			
		||||
 | 
			
		||||
        // y -> map column
 | 
			
		||||
        for(uint32_t y = 0; y < y_block_count; y++)
 | 
			
		||||
        {
 | 
			
		||||
            temp_locz = MreadDWord(temp_locy);
 | 
			
		||||
            temp_locy += 4;
 | 
			
		||||
 | 
			
		||||
            // z -> map block (16x16)
 | 
			
		||||
            for(uint32_t z = 0; z < z_block_count; z++)
 | 
			
		||||
            {
 | 
			
		||||
                temp_loc = MreadDWord(temp_locz);
 | 
			
		||||
                temp_locz += 4;
 | 
			
		||||
                block[x*y_block_count*z_block_count + y*z_block_count + z] = temp_loc;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool DFHackAPI::isValidBlock(uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    return block[x*y_block_count*z_block_count + y*z_block_count + z] != NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 256 * sizeof(uint16_t)
 | 
			
		||||
bool DFHackAPI::ReadTileTypes(uint32_t x, uint32_t y, uint32_t z, uint16_t *buffer)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t addr = block[x*y_block_count*z_block_count + y*z_block_count + z];
 | 
			
		||||
    if (addr!=NULL)
 | 
			
		||||
    {
 | 
			
		||||
        Mread(addr+tile_type_offset, 256 * sizeof(uint16_t), (uint8_t *)buffer);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// 256 * sizeof(uint32_t)
 | 
			
		||||
bool DFHackAPI::ReadDesignations(uint32_t x, uint32_t y, uint32_t z, uint32_t *buffer)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t addr = block[x*y_block_count*z_block_count + y*z_block_count + z];
 | 
			
		||||
    if (addr!=NULL)
 | 
			
		||||
    {
 | 
			
		||||
        Mread(addr+designation_offset, 256 * sizeof(uint32_t), (uint8_t *)buffer);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// 256 * sizeof(uint32_t)
 | 
			
		||||
bool DFHackAPI::ReadOccupancy(uint32_t x, uint32_t y, uint32_t z, uint32_t *buffer)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t addr = block[x*y_block_count*z_block_count + y*z_block_count + z];
 | 
			
		||||
    if (addr!=NULL)
 | 
			
		||||
    {
 | 
			
		||||
        Mread(addr+occupancy_offset, 256 * sizeof(uint32_t), (uint8_t *)buffer);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// 256 * sizeof(uint16_t)
 | 
			
		||||
bool DFHackAPI::WriteTileTypes(uint32_t x, uint32_t y, uint32_t z, uint16_t *buffer)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t addr = block[x*y_block_count*z_block_count + y*z_block_count + z];
 | 
			
		||||
    if (addr!=NULL)
 | 
			
		||||
    {
 | 
			
		||||
        Mwrite(addr+tile_type_offset, 256 * sizeof(uint16_t), (uint8_t *)buffer);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// 256 * sizeof(uint32_t)
 | 
			
		||||
bool DFHackAPI::WriteDesignations(uint32_t x, uint32_t y, uint32_t z, uint32_t *buffer)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t addr = block[x*y_block_count*z_block_count + y*z_block_count + z];
 | 
			
		||||
    if (addr!=NULL)
 | 
			
		||||
    {
 | 
			
		||||
        Mwrite(addr+designation_offset, 256 * sizeof(uint32_t), (uint8_t *)buffer);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// 256 * sizeof(uint32_t)
 | 
			
		||||
bool DFHackAPI::WriteOccupancy(uint32_t x, uint32_t y, uint32_t z, uint32_t *buffer)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t addr = block[x*y_block_count*z_block_count + y*z_block_count + z];
 | 
			
		||||
    if (addr!=NULL)
 | 
			
		||||
    {
 | 
			
		||||
        Mwrite(addr+occupancy_offset, 256 * sizeof(uint32_t), (uint8_t *)buffer);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//16 of them? IDK... there's probably just 7. Reading more doesn't cause errors as it's an array nested inside a block
 | 
			
		||||
// 16 * sizeof(uint8_t)
 | 
			
		||||
bool DFHackAPI::ReadRegionOffsets(uint32_t x, uint32_t y, uint32_t z, uint8_t *buffer)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t biome_stuffs = offset_descriptor->getOffset("biome_stuffs");
 | 
			
		||||
    uint32_t addr = block[x*y_block_count*z_block_count + y*z_block_count + z];
 | 
			
		||||
    if (addr!=NULL)
 | 
			
		||||
    {
 | 
			
		||||
        Mread(addr+biome_stuffs, 16 * sizeof(uint8_t), buffer);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// veins of a block, expects empty vein vector
 | 
			
		||||
bool DFHackAPI::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector <t_vein> & veins)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t addr = block[x*y_block_count*z_block_count + y*z_block_count + z];
 | 
			
		||||
    int veinvector = offset_descriptor->getOffset("v_vein");
 | 
			
		||||
    int veinsize = offset_descriptor->getHexValue("v_vein_size");
 | 
			
		||||
    veins.clear();
 | 
			
		||||
    if(addr!=NULL && veinvector && veinsize)
 | 
			
		||||
    {
 | 
			
		||||
        assert(sizeof(t_vein) == veinsize);
 | 
			
		||||
        // veins are stored as a vector of pointers to veins
 | 
			
		||||
        /*pointer is 4 bytes! we work with a 32bit program here, no matter what architecture we compile khazad for*/
 | 
			
		||||
        DfVector p_veins = dm->readVector(addr + veinvector, 4);
 | 
			
		||||
 | 
			
		||||
        // read all veins
 | 
			
		||||
        for (uint32_t i = 0; i< p_veins.getSize();i++)
 | 
			
		||||
        {
 | 
			
		||||
            t_vein v;
 | 
			
		||||
            uint32_t temp;
 | 
			
		||||
            // read the vein pointer from the vector
 | 
			
		||||
            p_veins.read((uint32_t)i,(uint8_t *)&temp);
 | 
			
		||||
            // read the vein data (dereference pointer)
 | 
			
		||||
            Mread(temp, veinsize, (uint8_t *)&v);
 | 
			
		||||
            // store it in the vector
 | 
			
		||||
            veins.push_back(v);
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// getter for map size
 | 
			
		||||
void DFHackAPI::getSize(uint32_t& x, uint32_t& y, uint32_t& z)
 | 
			
		||||
{
 | 
			
		||||
    x = x_block_count;
 | 
			
		||||
    y = y_block_count;
 | 
			
		||||
    z = z_block_count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool DFHackAPI::ReadStoneMatgloss(vector<t_matgloss> & stones)
 | 
			
		||||
{
 | 
			
		||||
    int matgloss_address = offset_descriptor->getAddress("matgloss");
 | 
			
		||||
    int matgloss_offset = offset_descriptor->getHexValue("matgloss_skip");
 | 
			
		||||
    int matgloss_colors = offset_descriptor->getOffset("matgloss_stone_color");
 | 
			
		||||
    DfVector p_matgloss = dm->readVector(matgloss_address + matgloss_offset, 4);
 | 
			
		||||
 | 
			
		||||
    stones.clear();
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i< p_matgloss.getSize();i++)
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t temp;
 | 
			
		||||
        // read the matgloss pointer from the vector into temp
 | 
			
		||||
        p_matgloss.read((uint32_t)i,(uint8_t *)&temp);
 | 
			
		||||
        // read the string pointed at by
 | 
			
		||||
        t_matgloss mat;
 | 
			
		||||
        mat.id = dm->readSTLString(temp); // reads a C string given an address
 | 
			
		||||
        mat.fore = MreadWord(temp + matgloss_colors);
 | 
			
		||||
        mat.back = MreadWord(temp + matgloss_colors + 2);
 | 
			
		||||
        mat.bright = MreadWord(temp + matgloss_colors + 4);
 | 
			
		||||
        stones.push_back(mat);
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool DFHackAPI::ReadMetalMatgloss(vector<t_matgloss> & metals)
 | 
			
		||||
{
 | 
			
		||||
    int matgloss_address = offset_descriptor->getAddress("matgloss");
 | 
			
		||||
    int matgloss_offset = offset_descriptor->getHexValue("matgloss_skip");
 | 
			
		||||
    int matgloss_colors = offset_descriptor->getOffset("matgloss_metal_color");
 | 
			
		||||
    DfVector p_matgloss = dm->readVector(matgloss_address + matgloss_offset*2, 4);
 | 
			
		||||
 | 
			
		||||
    metals.clear();
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i< p_matgloss.getSize();i++)
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t temp;
 | 
			
		||||
 | 
			
		||||
        // read the matgloss pointer from the vector into temp
 | 
			
		||||
        p_matgloss.read((uint32_t)i,(uint8_t *)&temp);
 | 
			
		||||
 | 
			
		||||
        // read the string pointed at by
 | 
			
		||||
        t_matgloss mat;
 | 
			
		||||
        mat.id = dm->readSTLString(temp); // reads a C string given an address
 | 
			
		||||
        mat.fore = MreadWord(temp + matgloss_colors);
 | 
			
		||||
        mat.back = MreadWord(temp + matgloss_colors + 2);
 | 
			
		||||
        mat.bright = MreadWord(temp + matgloss_colors + 4);
 | 
			
		||||
        metals.push_back(mat);
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool DFHackAPI::ReadWoodMatgloss(vector<t_matgloss> & woods)
 | 
			
		||||
{
 | 
			
		||||
    int matgloss_address = offset_descriptor->getAddress("matgloss");
 | 
			
		||||
    // TODO: find flag for autumnal coloring?
 | 
			
		||||
    DfVector p_matgloss = dm->readVector(matgloss_address, 4);
 | 
			
		||||
 | 
			
		||||
    woods.clear();
 | 
			
		||||
 | 
			
		||||
    t_matgloss mat;
 | 
			
		||||
    // TODO: use brown?
 | 
			
		||||
    mat.fore = 7;
 | 
			
		||||
    mat.back = 0;
 | 
			
		||||
    mat.bright = 0;
 | 
			
		||||
    for (uint32_t i = 0; i< p_matgloss.getSize();i++)
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t temp;
 | 
			
		||||
 | 
			
		||||
        // read the matgloss pointer from the vector into temp
 | 
			
		||||
        p_matgloss.read((uint32_t)i,(uint8_t *)&temp);
 | 
			
		||||
 | 
			
		||||
        // read the string pointed at by
 | 
			
		||||
        mat.id = dm->readSTLString(temp); // reads a C string given an address
 | 
			
		||||
        woods.push_back(mat);
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool DFHackAPI::ReadPlantMatgloss(vector<t_matgloss> & plants)
 | 
			
		||||
{
 | 
			
		||||
    int matgloss_address = offset_descriptor->getAddress("matgloss");
 | 
			
		||||
    int matgloss_offset = offset_descriptor->getHexValue("matgloss_skip");
 | 
			
		||||
    DfVector p_matgloss = dm->readVector(matgloss_address + matgloss_offset*3, 4);
 | 
			
		||||
 | 
			
		||||
    plants.clear();
 | 
			
		||||
 | 
			
		||||
    // TODO: use green?
 | 
			
		||||
    t_matgloss mat;
 | 
			
		||||
    mat.fore = 7;
 | 
			
		||||
    mat.back = 0;
 | 
			
		||||
    mat.bright = 0;
 | 
			
		||||
    for (uint32_t i = 0; i< p_matgloss.getSize();i++)
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t temp;
 | 
			
		||||
 | 
			
		||||
        // read the matgloss pointer from the vector into temp
 | 
			
		||||
        p_matgloss.read((uint32_t)i,(uint8_t *)&temp);
 | 
			
		||||
 | 
			
		||||
        // read the string pointed at by
 | 
			
		||||
        mat.id = dm->readSTLString(temp); // reads a C string given an address
 | 
			
		||||
        plants.push_back(mat);
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//vector<uint16_t> v_geology[eBiomeCount];
 | 
			
		||||
bool DFHackAPI::ReadGeology( vector < vector <uint16_t> >& assign )
 | 
			
		||||
{
 | 
			
		||||
    // get needed addresses and offsets
 | 
			
		||||
    int region_x_offset = offset_descriptor->getAddress("region_x");
 | 
			
		||||
    int region_y_offset = offset_descriptor->getAddress("region_y");
 | 
			
		||||
    int region_z_offset =  offset_descriptor->getAddress("region_z");
 | 
			
		||||
    int world_offset =  offset_descriptor->getAddress("world");
 | 
			
		||||
    int world_regions_offset =  offset_descriptor->getOffset("w_regions_arr");
 | 
			
		||||
    int region_size =  offset_descriptor->getHexValue("region_size");
 | 
			
		||||
    int region_geo_index_offset =  offset_descriptor->getOffset("region_geo_index_off");
 | 
			
		||||
    int world_geoblocks_offset =  offset_descriptor->getOffset("w_geoblocks");
 | 
			
		||||
    int world_size_x = offset_descriptor->getOffset("world_size_x");
 | 
			
		||||
    int world_size_y = offset_descriptor->getOffset("world_size_y");
 | 
			
		||||
    int geolayer_geoblock_offset = offset_descriptor->getOffset("geolayer_geoblock_offset");
 | 
			
		||||
 | 
			
		||||
    uint32_t regionX, regionY, regionZ;
 | 
			
		||||
    uint16_t worldSizeX, worldSizeY;
 | 
			
		||||
 | 
			
		||||
    // check if we have 'em all
 | 
			
		||||
    if(
 | 
			
		||||
        !(
 | 
			
		||||
        region_x_offset && region_y_offset && region_z_offset && world_size_x && world_size_y
 | 
			
		||||
        && world_offset && world_regions_offset && world_geoblocks_offset && region_size
 | 
			
		||||
        && region_geo_index_offset && geolayer_geoblock_offset
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
        // fail if we don't have them
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // read position of the region inside DF world
 | 
			
		||||
    MreadDWord(region_x_offset, regionX);
 | 
			
		||||
    MreadDWord(region_y_offset, regionY);
 | 
			
		||||
    MreadDWord(region_z_offset, regionZ);
 | 
			
		||||
 | 
			
		||||
    // get world size
 | 
			
		||||
    MreadWord(world_offset + world_size_x, worldSizeX);
 | 
			
		||||
    MreadWord(world_offset + world_size_y, worldSizeY);
 | 
			
		||||
 | 
			
		||||
    // get pointer to first part of 2d array of regions
 | 
			
		||||
    uint32_t regions = MreadDWord(world_offset + world_regions_offset);
 | 
			
		||||
 | 
			
		||||
    // read the geoblock vector
 | 
			
		||||
    DfVector geoblocks = dm->readVector(world_offset + world_geoblocks_offset,4);
 | 
			
		||||
 | 
			
		||||
    // iterate over 8 surrounding regions + local region
 | 
			
		||||
    for(int i = eNorthWest; i< eBiomeCount; i++)
 | 
			
		||||
    {
 | 
			
		||||
        // check bounds, fix them if needed
 | 
			
		||||
        int bioRX = regionX / 16 + (i%3) - 1;
 | 
			
		||||
        if( bioRX < 0) bioRX = 0;
 | 
			
		||||
        if( bioRX >= worldSizeX) bioRX = worldSizeX - 1;
 | 
			
		||||
        int bioRY = regionY / 16 + (i/3) - 1;
 | 
			
		||||
        if( bioRY < 0) bioRY = 0;
 | 
			
		||||
        if( bioRY >= worldSizeY) bioRY = worldSizeY - 1;
 | 
			
		||||
 | 
			
		||||
        // get pointer to column of regions
 | 
			
		||||
        uint32_t geoX;
 | 
			
		||||
        MreadDWord(regions + bioRX*4, geoX);
 | 
			
		||||
 | 
			
		||||
        // get index into geoblock vector
 | 
			
		||||
        uint16_t geoindex;
 | 
			
		||||
        MreadWord(geoX + bioRY*region_size + region_geo_index_offset, geoindex);
 | 
			
		||||
 | 
			
		||||
        // get the geoblock from the geoblock vector using the geoindex
 | 
			
		||||
        uint32_t geoblock_off;
 | 
			
		||||
        geoblocks.read(geoindex,(uint8_t *) &geoblock_off);
 | 
			
		||||
 | 
			
		||||
        // get the vector with pointer to layers
 | 
			
		||||
        DfVector geolayers = dm->readVector(geoblock_off + geolayer_geoblock_offset , 4); // let's hope
 | 
			
		||||
        // make sure we don't load crap
 | 
			
		||||
        assert(geolayers.getSize() > 0 && geolayers.getSize() <= 16);
 | 
			
		||||
 | 
			
		||||
        // finally, read the layer matgloss
 | 
			
		||||
        for(uint32_t j = 0;j< geolayers.getSize();j++)
 | 
			
		||||
        {
 | 
			
		||||
            int geol_offset;
 | 
			
		||||
            // read pointer to a layer
 | 
			
		||||
            geolayers.read(j, (uint8_t *) & geol_offset);
 | 
			
		||||
            // read word at pointer + 2, store in our geology vectors
 | 
			
		||||
            v_geology[i].push_back(MreadWord(geol_offset + 2));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    assign.clear();
 | 
			
		||||
    // TODO: clean this up
 | 
			
		||||
    for(int i = 0; i< eBiomeCount;i++)
 | 
			
		||||
    {
 | 
			
		||||
        assign.push_back(v_geology[i]);
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// returns number of buildings, expects v_buildingtypes that will later map t_building.type to its name
 | 
			
		||||
uint32_t DFHackAPI::InitReadBuildings(vector <string> &v_buildingtypes)
 | 
			
		||||
{
 | 
			
		||||
    buildingsInited = true;
 | 
			
		||||
    int buildings = offset_descriptor->getAddress("buildings");
 | 
			
		||||
    assert(buildings);
 | 
			
		||||
    p_bld = new DfVector( dm->readVector(buildings,4));
 | 
			
		||||
    offset_descriptor->copyBuildings(v_buildingtypes);
 | 
			
		||||
    return p_bld->getSize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// read one building
 | 
			
		||||
bool DFHackAPI::ReadBuilding(const uint32_t &index, t_building & building)
 | 
			
		||||
{
 | 
			
		||||
    assert(buildingsInited);
 | 
			
		||||
    uint32_t temp;
 | 
			
		||||
    t_building_df40d bld_40d;
 | 
			
		||||
 | 
			
		||||
    // read pointer from vector at position
 | 
			
		||||
    p_bld->read(index,(uint8_t *)&temp);
 | 
			
		||||
 | 
			
		||||
    //read building from memory
 | 
			
		||||
    Mread(temp, sizeof(t_building_df40d), (uint8_t *)&bld_40d);
 | 
			
		||||
 | 
			
		||||
    // transform
 | 
			
		||||
    int32_t type = -1;
 | 
			
		||||
    offset_descriptor->resolveClassId(temp, type);
 | 
			
		||||
    building.vtable = bld_40d.vtable;
 | 
			
		||||
    building.x1 = bld_40d.x1;
 | 
			
		||||
    building.x2 = bld_40d.x2;
 | 
			
		||||
    building.y1 = bld_40d.y1;
 | 
			
		||||
    building.y2 = bld_40d.y2;
 | 
			
		||||
    building.z = bld_40d.z;
 | 
			
		||||
    building.material = bld_40d.material;
 | 
			
		||||
    building.type = type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void DFHackAPI::FinishReadBuildings()
 | 
			
		||||
{
 | 
			
		||||
    buildingsInited = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//TODO: maybe do construction reading differently - this could go slow with many of them.
 | 
			
		||||
// returns number of constructions, prepares a vector, returns total number of constructions
 | 
			
		||||
uint32_t DFHackAPI::InitReadConstructions()
 | 
			
		||||
{
 | 
			
		||||
    constructionsInited = true;
 | 
			
		||||
    int constructions = offset_descriptor->getAddress("constructions");
 | 
			
		||||
    assert(constructions);
 | 
			
		||||
 | 
			
		||||
    p_cons = new DfVector(dm->readVector(constructions,4));
 | 
			
		||||
    return p_cons->getSize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool DFHackAPI::ReadConstruction(const uint32_t &index, t_construction & construction)
 | 
			
		||||
{
 | 
			
		||||
    assert(constructionsInited);
 | 
			
		||||
    t_construction_df40d c_40d;
 | 
			
		||||
    uint32_t temp;
 | 
			
		||||
 | 
			
		||||
    // read pointer from vector at position
 | 
			
		||||
    p_cons->read((uint32_t)index,(uint8_t *)&temp);
 | 
			
		||||
 | 
			
		||||
    //read construction from memory
 | 
			
		||||
    Mread(temp, sizeof(t_construction_df40d), (uint8_t *)&c_40d);
 | 
			
		||||
 | 
			
		||||
    // transform
 | 
			
		||||
    construction.x = c_40d.x;
 | 
			
		||||
    construction.y = c_40d.y;
 | 
			
		||||
    construction.z = c_40d.z;
 | 
			
		||||
    construction.material = c_40d.material;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void DFHackAPI::FinishReadConstructions()
 | 
			
		||||
{
 | 
			
		||||
    constructionsInited = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint32_t DFHackAPI::InitReadVegetation()
 | 
			
		||||
{
 | 
			
		||||
    vegetationInited = true;
 | 
			
		||||
    int vegetation = offset_descriptor->getAddress("vegetation");
 | 
			
		||||
    treeoffset = offset_descriptor->getOffset("tree_desc_offset");
 | 
			
		||||
    assert(vegetation && treeoffset);
 | 
			
		||||
    p_veg = new DfVector(dm->readVector(vegetation,4));
 | 
			
		||||
    return p_veg->getSize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool DFHackAPI::ReadVegetation(const uint32_t &index, t_tree_desc & shrubbery)
 | 
			
		||||
{
 | 
			
		||||
    assert(vegetationInited);
 | 
			
		||||
    uint32_t temp;
 | 
			
		||||
    // read pointer from vector at position
 | 
			
		||||
    p_veg->read(index,(uint8_t *)&temp);
 | 
			
		||||
    //read construction from memory
 | 
			
		||||
    Mread(temp + treeoffset, sizeof(t_tree_desc), (uint8_t *) &shrubbery);
 | 
			
		||||
    // FIXME: this is completely wrong. type isn't just tree/shrub but also different kinds of trees. stuff that grows around ponds has its own type ID
 | 
			
		||||
    if(shrubbery.material.type == 3) shrubbery.material.type = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void DFHackAPI::FinishReadVegetation()
 | 
			
		||||
{
 | 
			
		||||
    vegetationInited = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool DFHackAPI::Attach()
 | 
			
		||||
{
 | 
			
		||||
    // detach all processes, destroy manager
 | 
			
		||||
    if(pm != NULL)
 | 
			
		||||
        delete pm;
 | 
			
		||||
    // find a process (ProcessManager can find multiple when used properly)
 | 
			
		||||
    pm = new ProcessManager(xml); // FIXME: handle bad XML better
 | 
			
		||||
    if(!pm->findProcessess())
 | 
			
		||||
        return false; // FIXME: throw exceptions to distinguish errors? provide error code?
 | 
			
		||||
    p = (*pm)[0]; // we just use the first found process
 | 
			
		||||
    if(!p->attach())
 | 
			
		||||
        return false; // couldn't attach to process, no go
 | 
			
		||||
    offset_descriptor = p->getDescriptor();
 | 
			
		||||
    dm = p->getDataModel();
 | 
			
		||||
    // process is attached, everything went just fine... hopefully
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// TODO: clean inited stuff here
 | 
			
		||||
bool DFHackAPI::Detach()
 | 
			
		||||
{
 | 
			
		||||
    p->detach();
 | 
			
		||||
    if(pm != NULL)
 | 
			
		||||
        delete pm;
 | 
			
		||||
    pm = NULL;
 | 
			
		||||
    p = NULL;
 | 
			
		||||
    offset_descriptor = NULL;
 | 
			
		||||
    dm = NULL;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,160 @@
 | 
			
		||||
/*
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef SIMPLEAPI_H_INCLUDED
 | 
			
		||||
#define SIMPLEAPI_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
class memory_info;
 | 
			
		||||
class DfVector;
 | 
			
		||||
class ProcessManager;
 | 
			
		||||
class Process;
 | 
			
		||||
class DataModel;
 | 
			
		||||
 | 
			
		||||
//FIXME: better control over state, creation and destruction
 | 
			
		||||
//TODO: give this the pimpl treatment?
 | 
			
		||||
class DFHackAPI
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
    // internals
 | 
			
		||||
    uint32_t * block;
 | 
			
		||||
    uint32_t x_block_count, y_block_count, z_block_count;
 | 
			
		||||
    uint32_t regionX, regionY, regionZ;
 | 
			
		||||
    uint32_t worldSizeX, worldSizeY;
 | 
			
		||||
    
 | 
			
		||||
    uint32_t tile_type_offset;
 | 
			
		||||
    uint32_t designation_offset;
 | 
			
		||||
    uint32_t occupancy_offset;
 | 
			
		||||
    
 | 
			
		||||
    ProcessManager* pm;
 | 
			
		||||
    Process* p;
 | 
			
		||||
    DataModel* dm;
 | 
			
		||||
    memory_info* offset_descriptor;
 | 
			
		||||
    vector<uint16_t> v_geology[eBiomeCount];
 | 
			
		||||
    string xml;
 | 
			
		||||
 | 
			
		||||
    bool constructionsInited;
 | 
			
		||||
    bool buildingsInited;
 | 
			
		||||
    bool vegetationInited;
 | 
			
		||||
    uint32_t treeoffset;
 | 
			
		||||
    DfVector *p_cons;
 | 
			
		||||
    DfVector *p_bld;
 | 
			
		||||
    DfVector *p_veg;
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
public:
 | 
			
		||||
    DFHackAPI(const string path_to_xml);
 | 
			
		||||
 | 
			
		||||
    bool Attach();
 | 
			
		||||
    bool Detach();
 | 
			
		||||
    bool isAttached();
 | 
			
		||||
    /**
 | 
			
		||||
     * Matgloss. next four methods look very similar. I could use two and move the processing one level up...
 | 
			
		||||
     * I'll keep it like this, even with the code duplication as it will hopefully get more features and separate data types later.
 | 
			
		||||
     * Yay for nebulous plans for a rock survey tool that tracks how much of which metal could be smelted from available resorces
 | 
			
		||||
     */
 | 
			
		||||
    bool ReadStoneMatgloss(vector<t_matgloss> & output);
 | 
			
		||||
    bool ReadWoodMatgloss (vector<t_matgloss> & output);
 | 
			
		||||
    bool ReadMetalMatgloss(vector<t_matgloss> & output);
 | 
			
		||||
    bool ReadPlantMatgloss(vector<t_matgloss> & output);
 | 
			
		||||
    // FIXME: add creatures for all the creature products
 | 
			
		||||
 | 
			
		||||
    // read region surroundings, get their vectors of geolayers so we can do translation (or just hand the translation table to the client)
 | 
			
		||||
    // returns an array of 9 vectors of indices into stone matgloss
 | 
			
		||||
    /**
 | 
			
		||||
        Method for reading the geological surrounding of the currently loaded region.
 | 
			
		||||
        assign is a reference to an array of nine vectors of unsigned words that are to be filled with the data
 | 
			
		||||
        array is indexed by the BiomeOffset enum
 | 
			
		||||
 | 
			
		||||
        I omitted resolving the layer matgloss in this API, because it would
 | 
			
		||||
        introduce overhead by calling some method for each tile. You have to do it
 | 
			
		||||
        yourself. First get the stuff from ReadGeology and then for each block get
 | 
			
		||||
        the RegionOffsets. For each tile get the real region from RegionOffsets and
 | 
			
		||||
        cross-reference it with the geology stuff (region -- array of vectors, depth --
 | 
			
		||||
        vector). I'm thinking about turning that Geology stuff into a
 | 
			
		||||
        two-dimensional array with static size.
 | 
			
		||||
 | 
			
		||||
        this is the algorithm for applying matgloss:
 | 
			
		||||
        void DfMap::applyGeoMatgloss(Block * b)
 | 
			
		||||
        {
 | 
			
		||||
            // load layer matgloss
 | 
			
		||||
            for(int x_b = 0; x_b < BLOCK_SIZE; x_b++)
 | 
			
		||||
            {
 | 
			
		||||
                for(int y_b = 0; y_b < BLOCK_SIZE; y_b++)
 | 
			
		||||
                {
 | 
			
		||||
                    int geolayer = b->designation[x_b][y_b].bits.geolayer_index;
 | 
			
		||||
                    int biome = b->designation[x_b][y_b].bits.biome;
 | 
			
		||||
                    b->material[x_b][y_b].type = Mat_Stone;
 | 
			
		||||
                    b->material[x_b][y_b].index = v_geology[b->RegionOffsets[biome]][geolayer];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
     */
 | 
			
		||||
    bool ReadGeology( vector < vector <uint16_t> >& assign );
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * BLOCK DATA
 | 
			
		||||
     */
 | 
			
		||||
    /// allocate and read pointers to map blocks
 | 
			
		||||
    bool InitMap();
 | 
			
		||||
    /// destroy the mapblock cache
 | 
			
		||||
    bool DestroyMap();
 | 
			
		||||
    /// get size of the map in tiles
 | 
			
		||||
    void getSize(uint32_t& x, uint32_t& y, uint32_t& z);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Return false/0 on failure, buffer allocated by client app, 256 items long
 | 
			
		||||
     */
 | 
			
		||||
    bool isValidBlock(uint32_t blockx, uint32_t blocky, uint32_t blockz);
 | 
			
		||||
    
 | 
			
		||||
    bool ReadTileTypes(uint32_t blockx, uint32_t blocky, uint32_t blockz, uint16_t *buffer); // 256 * sizeof(uint16_t)
 | 
			
		||||
    bool WriteTileTypes(uint32_t blockx, uint32_t blocky, uint32_t blockz, uint16_t *buffer); // 256 * sizeof(uint16_t)
 | 
			
		||||
    
 | 
			
		||||
    bool ReadDesignations(uint32_t blockx, uint32_t blocky, uint32_t blockz, uint32_t *buffer); // 256 * sizeof(uint32_t)
 | 
			
		||||
    bool WriteDesignations (uint32_t blockx, uint32_t blocky, uint32_t blockz, uint32_t *buffer);
 | 
			
		||||
    
 | 
			
		||||
    bool ReadOccupancy(uint32_t blockx, uint32_t blocky, uint32_t blockz, uint32_t *buffer); // 256 * sizeof(uint32_t)
 | 
			
		||||
    bool WriteOccupancy(uint32_t blockx, uint32_t blocky, uint32_t blockz, uint32_t *buffer); // 256 * sizeof(uint32_t)
 | 
			
		||||
    
 | 
			
		||||
    /// read region offsets of a block
 | 
			
		||||
    bool ReadRegionOffsets(uint32_t blockx, uint32_t blocky, uint32_t blockz, uint8_t *buffer); // 16 * sizeof(uint8_t)
 | 
			
		||||
    
 | 
			
		||||
    /// read aggregated veins of a block
 | 
			
		||||
    bool ReadVeins(uint32_t blockx, uint32_t blocky, uint32_t blockz, vector <t_vein> & veins);
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Buildings, constructions, plants, all pretty straighforward. InitReadBuildings returns all the building types as a mapping between a numeric values and strings
 | 
			
		||||
     */
 | 
			
		||||
    uint32_t InitReadConstructions();
 | 
			
		||||
    bool ReadConstruction(const uint32_t &index, t_construction & construction);
 | 
			
		||||
    void FinishReadConstructions();
 | 
			
		||||
 | 
			
		||||
    uint32_t InitReadBuildings(vector <string> &v_buildingtypes);
 | 
			
		||||
    bool ReadBuilding(const uint32_t &index, t_building & building);
 | 
			
		||||
    void FinishReadBuildings();
 | 
			
		||||
 | 
			
		||||
    uint32_t InitReadVegetation();
 | 
			
		||||
    bool ReadVegetation(const uint32_t &index, t_tree_desc & shrubbery);
 | 
			
		||||
    void FinishReadVegetation();
 | 
			
		||||
};
 | 
			
		||||
#endif // SIMPLEAPI_H_INCLUDED
 | 
			
		||||
@ -0,0 +1,34 @@
 | 
			
		||||
/*
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef PROCESSUTIL_H_INCLUDED
 | 
			
		||||
#define PROCESSUTIL_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#ifdef LINUX_BUILD
 | 
			
		||||
    #include "LinuxMemAccess.h"
 | 
			
		||||
#else
 | 
			
		||||
    #include "WindowsMemAccess.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // PROCESSUTIL_H_INCLUDED
 | 
			
		||||
@ -0,0 +1,382 @@
 | 
			
		||||
/*
 | 
			
		||||
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 "DFCommon.h"
 | 
			
		||||
#include "DFMemInfo.h"
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
memory_info::memory_info()
 | 
			
		||||
{
 | 
			
		||||
    base = 0;
 | 
			
		||||
    classindex = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void memory_info::setVersion(const char * v)
 | 
			
		||||
{
 | 
			
		||||
    version = v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void memory_info::setVersion(string v)
 | 
			
		||||
{
 | 
			
		||||
    version = v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
string memory_info::getVersion()
 | 
			
		||||
{
 | 
			
		||||
    return version;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void memory_info::setOS(const char *os)
 | 
			
		||||
{
 | 
			
		||||
    string oss = os;
 | 
			
		||||
    if(oss == "windows")
 | 
			
		||||
        OS = OS_WINDOWS;
 | 
			
		||||
    else if(oss == "linux")
 | 
			
		||||
        OS = OS_LINUX;
 | 
			
		||||
    else
 | 
			
		||||
        OS = OS_BAD;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void memory_info::setOS(string os)
 | 
			
		||||
{
 | 
			
		||||
    if(os == "windows")
 | 
			
		||||
        OS = OS_WINDOWS;
 | 
			
		||||
    else if(os == "linux")
 | 
			
		||||
        OS = OS_LINUX;
 | 
			
		||||
    else
 | 
			
		||||
        OS = OS_BAD;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void memory_info::setOS(OSType os)
 | 
			
		||||
{
 | 
			
		||||
    if(os >= OS_WINDOWS && os < OS_BAD)
 | 
			
		||||
    {
 | 
			
		||||
        OS = os;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    OS = OS_BAD;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
memory_info::OSType memory_info::getOS()
 | 
			
		||||
{
 | 
			
		||||
    return OS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// copy constructor
 | 
			
		||||
memory_info::memory_info(const memory_info &old)
 | 
			
		||||
{
 | 
			
		||||
    version = old.version;
 | 
			
		||||
    OS = old.OS;
 | 
			
		||||
    addresses = old.addresses;
 | 
			
		||||
    offsets = old.offsets;
 | 
			
		||||
    hexvals = old.hexvals;
 | 
			
		||||
    strings = old.strings;
 | 
			
		||||
    base = old.base;
 | 
			
		||||
    classes = old.classes;
 | 
			
		||||
    classsubtypes = old.classsubtypes;
 | 
			
		||||
    classindex = old.classindex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint32_t memory_info::getBase ()
 | 
			
		||||
{
 | 
			
		||||
    return base;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void memory_info::setBase (string s)
 | 
			
		||||
{
 | 
			
		||||
    base = strtol(s.c_str(), NULL, 16);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void memory_info::setBase (uint32_t b)
 | 
			
		||||
{
 | 
			
		||||
    base = b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void memory_info::setOffset (string key, string value)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t offset = strtol(value.c_str(), NULL, 16);
 | 
			
		||||
    offsets[key] = offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void memory_info::setAddress (string key, string value)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t address = strtol(value.c_str(), NULL, 16);
 | 
			
		||||
    addresses[key] = address;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void memory_info::setHexValue (string key, string value)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t hexval = strtol(value.c_str(), NULL, 16);
 | 
			
		||||
    hexvals[key] = hexval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void memory_info::setString (string key, string value)
 | 
			
		||||
{
 | 
			
		||||
    strings[key] = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// FIXME: next three methods should use some kind of custom container so it doesn't have to search so much.
 | 
			
		||||
void memory_info::setClass (const char * name, const char * vtable)
 | 
			
		||||
{
 | 
			
		||||
    for (uint32_t i=0; i<classes.size(); i++)
 | 
			
		||||
    {
 | 
			
		||||
        if(classes[i].classname == name)
 | 
			
		||||
        {
 | 
			
		||||
            classes[i].vtable = strtol(vtable, NULL, 16);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    t_class cls;
 | 
			
		||||
        cls.assign = classindex;
 | 
			
		||||
        cls.classname = name;
 | 
			
		||||
        cls.is_multiclass = false;
 | 
			
		||||
        cls.type_offset = 0;
 | 
			
		||||
        classindex++;
 | 
			
		||||
        cls.vtable = strtol(vtable, NULL, 16);
 | 
			
		||||
    classes.push_back(cls);
 | 
			
		||||
    //cout << "class " << name << ", assign " << cls.assign << ", vtable  " << cls.vtable << endl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// find old entry by name, rewrite, return its multi index. otherwise make a new one, append an empty vector of t_type to classtypes,  return its index.
 | 
			
		||||
uint32_t memory_info::setMultiClass (const char * name, const char * vtable, const char * typeoffset)
 | 
			
		||||
{
 | 
			
		||||
    for (uint32_t i=0; i<classes.size(); i++)
 | 
			
		||||
    {
 | 
			
		||||
        if(classes[i].classname == name)
 | 
			
		||||
        {
 | 
			
		||||
            // vtable and typeoffset can be left out from the xml definition when there's already a named multiclass
 | 
			
		||||
            if(vtable != NULL)
 | 
			
		||||
                classes[i].vtable = strtol(vtable, NULL, 16);
 | 
			
		||||
            if(typeoffset != NULL)
 | 
			
		||||
                classes[i].type_offset = strtol(typeoffset, NULL, 16);
 | 
			
		||||
            return classes[i].multi_index;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    //FIXME: add checking for vtable and typeoffset here. they HAVE to be valid. maybe change the return value into a bool and pass in multi index by reference?
 | 
			
		||||
    t_class cls;
 | 
			
		||||
        cls.assign = classindex;
 | 
			
		||||
        cls.classname = name;
 | 
			
		||||
        cls.is_multiclass = true;
 | 
			
		||||
        cls.type_offset = strtol(typeoffset, NULL, 16);
 | 
			
		||||
        cls.vtable = strtol(vtable, NULL, 16);
 | 
			
		||||
        cls.multi_index = classsubtypes.size();
 | 
			
		||||
    classes.push_back(cls);
 | 
			
		||||
    classindex++;
 | 
			
		||||
 | 
			
		||||
    vector<t_type> thistypes;
 | 
			
		||||
    classsubtypes.push_back(thistypes);
 | 
			
		||||
    //cout << "multiclass " << name << ", assign " << cls.assign << ", vtable  " << cls.vtable << endl;
 | 
			
		||||
    return classsubtypes.size() - 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void memory_info::setMultiClassChild (uint32_t multi_index, const char * name, const char * type)
 | 
			
		||||
{
 | 
			
		||||
    vector <t_type>& vec = classsubtypes[multi_index];
 | 
			
		||||
    for (uint32_t i=0; i<vec.size(); i++)
 | 
			
		||||
    {
 | 
			
		||||
        if(vec[i].classname == name)
 | 
			
		||||
        {
 | 
			
		||||
            vec[i].type = strtol(type, NULL, 16);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // new multiclass child
 | 
			
		||||
    t_type mcc;
 | 
			
		||||
        mcc.assign = classindex;
 | 
			
		||||
        mcc.classname = name;
 | 
			
		||||
        mcc.type = strtol(type, NULL, 16);
 | 
			
		||||
    vec.push_back(mcc);
 | 
			
		||||
    classindex++;
 | 
			
		||||
    //cout << "    classtype " << name << ", assign " << mcc.assign << ", vtable  " << mcc.type << endl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool memory_info::resolveClassId(uint32_t address, int32_t & classid)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t vtable = MreadDWord(address);
 | 
			
		||||
    // FIXME: stupid search. we need a better container
 | 
			
		||||
    for(uint32_t i = 0;i< classes.size();i++)
 | 
			
		||||
    {
 | 
			
		||||
        if(classes[i].vtable == vtable) // got class
 | 
			
		||||
        {
 | 
			
		||||
            // if it is a multiclass, try resolving it
 | 
			
		||||
            if(classes[i].is_multiclass)
 | 
			
		||||
            {
 | 
			
		||||
                vector <t_type>& vec = classsubtypes[classes[i].multi_index];
 | 
			
		||||
                uint32_t type = MreadWord(address + classes[i].type_offset);
 | 
			
		||||
                //printf ("class %d:%s offset 0x%x\n", i , classes[i].classname.c_str(), classes[i].type_offset);
 | 
			
		||||
                // return typed building if successful
 | 
			
		||||
                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;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            // otherwise return the class we found
 | 
			
		||||
            classid = classes[i].assign;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // we failed to find anything that would match
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Flatten vtables into a index<->name mapping
 | 
			
		||||
void memory_info::copyBuildings(vector<string> & v_buildingtypes)
 | 
			
		||||
{
 | 
			
		||||
    for(uint32_t i = 0;i< classes.size();i++)
 | 
			
		||||
    {
 | 
			
		||||
        v_buildingtypes.push_back(classes[i].classname);
 | 
			
		||||
        if(!classes[i].is_multiclass)
 | 
			
		||||
        {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        vector <t_type>& vec = classsubtypes[classes[i].multi_index];
 | 
			
		||||
        for (uint32_t k = 0; k < vec.size();k++)
 | 
			
		||||
        {
 | 
			
		||||
            v_buildingtypes.push_back(vec[k].classname);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// change base of all addresses/vtable entries
 | 
			
		||||
void memory_info::RebaseAddresses(int32_t new_base)
 | 
			
		||||
{
 | 
			
		||||
    map<string, uint32_t>::iterator iter;
 | 
			
		||||
    int32_t rebase = - (int32_t)base + new_base;
 | 
			
		||||
    for(iter = addresses.begin(); iter != addresses.end(); iter++)
 | 
			
		||||
    {
 | 
			
		||||
        addresses[iter->first] = iter->second + rebase;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// change base of all addresses/vtable entries
 | 
			
		||||
void memory_info::RebaseAll(int32_t new_base)
 | 
			
		||||
{
 | 
			
		||||
    map<string, uint32_t>::iterator iter;
 | 
			
		||||
    int32_t rebase = - (int32_t)base + new_base;
 | 
			
		||||
    for(iter = addresses.begin(); iter != addresses.end(); iter++)
 | 
			
		||||
    {
 | 
			
		||||
        addresses[iter->first] = iter->second + rebase;
 | 
			
		||||
    }
 | 
			
		||||
    RebaseVTable(rebase);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// change all vtable entries by offset
 | 
			
		||||
void memory_info::RebaseVTable(int32_t offset)
 | 
			
		||||
{
 | 
			
		||||
    vector<t_class>::iterator iter;
 | 
			
		||||
    for(iter = classes.begin(); iter != classes.end(); iter++)
 | 
			
		||||
    {
 | 
			
		||||
        iter->vtable += offset;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Get named address
 | 
			
		||||
uint32_t memory_info::getAddress (string key)
 | 
			
		||||
{
 | 
			
		||||
    if(addresses.count(key))
 | 
			
		||||
    {
 | 
			
		||||
        return addresses[key];
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Get named offset
 | 
			
		||||
uint32_t memory_info::getOffset (string key)
 | 
			
		||||
{
 | 
			
		||||
    if(offsets.count(key))
 | 
			
		||||
    {
 | 
			
		||||
        return offsets[key];
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Get named string
 | 
			
		||||
std::string memory_info::getString (string key)
 | 
			
		||||
{
 | 
			
		||||
    if(strings.count(key))
 | 
			
		||||
    {
 | 
			
		||||
        return strings[key];
 | 
			
		||||
    }
 | 
			
		||||
    else return string("");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Get named numerical value
 | 
			
		||||
uint32_t memory_info::getHexValue (string key)
 | 
			
		||||
{
 | 
			
		||||
    if(hexvals.count(key))
 | 
			
		||||
    {
 | 
			
		||||
        return hexvals[key];
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Reset everything
 | 
			
		||||
void memory_info::flush()
 | 
			
		||||
{
 | 
			
		||||
    base = 0;
 | 
			
		||||
    addresses.clear();
 | 
			
		||||
    offsets.clear();
 | 
			
		||||
    strings.clear();
 | 
			
		||||
    hexvals.clear();
 | 
			
		||||
    classes.clear();
 | 
			
		||||
    classsubtypes.clear();
 | 
			
		||||
    classindex = 0;
 | 
			
		||||
    version = "";
 | 
			
		||||
    OS = OS_BAD;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,113 @@
 | 
			
		||||
/*
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef MEMINFO_H_INCLUDED
 | 
			
		||||
#define MEMINFO_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
class memory_info
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    enum OSType
 | 
			
		||||
    {
 | 
			
		||||
        OS_WINDOWS,
 | 
			
		||||
        OS_LINUX,
 | 
			
		||||
        OS_BAD
 | 
			
		||||
    };
 | 
			
		||||
    struct t_class
 | 
			
		||||
    {
 | 
			
		||||
        string classname;
 | 
			
		||||
        uint32_t vtable;
 | 
			
		||||
        bool is_multiclass;
 | 
			
		||||
        uint32_t multi_index;
 | 
			
		||||
        uint32_t assign;// index to typeclass array if multiclass. return value if not.
 | 
			
		||||
        uint32_t type_offset; // offset of type data for multiclass
 | 
			
		||||
    };
 | 
			
		||||
    struct t_type
 | 
			
		||||
    {
 | 
			
		||||
        string classname;
 | 
			
		||||
        uint32_t assign;
 | 
			
		||||
        uint32_t type;
 | 
			
		||||
    };
 | 
			
		||||
    memory_info();
 | 
			
		||||
    memory_info(const memory_info&);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    void RebaseAddresses(int32_t new_base);
 | 
			
		||||
    void RebaseAll(int32_t new_base);
 | 
			
		||||
    uint32_t getBase ();
 | 
			
		||||
    void setBase (string);
 | 
			
		||||
    void setBase (uint32_t);
 | 
			
		||||
 | 
			
		||||
    uint32_t getOffset (string);
 | 
			
		||||
    uint32_t getAddress (string);
 | 
			
		||||
    uint32_t getHexValue (string);
 | 
			
		||||
    string getString (string);
 | 
			
		||||
 | 
			
		||||
    void setVersion(const char *);
 | 
			
		||||
    void setVersion(string);
 | 
			
		||||
    string getVersion();
 | 
			
		||||
 | 
			
		||||
    void setOS(const char *);
 | 
			
		||||
    void setOS(string);
 | 
			
		||||
    void setOS(OSType);
 | 
			
		||||
    OSType getOS();
 | 
			
		||||
 | 
			
		||||
    void setOffset (string, int32_t);
 | 
			
		||||
    void setAddress (string, uint32_t);
 | 
			
		||||
    void setHexValue (string, uint32_t);
 | 
			
		||||
 | 
			
		||||
    void setOffset (string, const char *);
 | 
			
		||||
    void setAddress (string, const char *);
 | 
			
		||||
    void setHexValue (string, const char *);
 | 
			
		||||
    void setString (string, const char *);
 | 
			
		||||
 | 
			
		||||
    void setOffset (string, string);
 | 
			
		||||
    void setAddress (string, string);
 | 
			
		||||
    void setHexValue (string, string);
 | 
			
		||||
    void setString (string, string);
 | 
			
		||||
 | 
			
		||||
    void RebaseVTable(int32_t offset);
 | 
			
		||||
    void setClass (const char * name, const char * vtable);
 | 
			
		||||
    uint32_t setMultiClass (const char * name, const char * vtable, const char * typeoffset);
 | 
			
		||||
    void setMultiClassChild (uint32_t multi_index, const char * name, const char * type);
 | 
			
		||||
 | 
			
		||||
    // ALERT: uses memory reading directly
 | 
			
		||||
    bool resolveClassId(uint32_t address, int32_t & classid);
 | 
			
		||||
    void copyBuildings(vector<string> & v_buildingtypes);
 | 
			
		||||
 | 
			
		||||
    void flush();
 | 
			
		||||
    
 | 
			
		||||
private:
 | 
			
		||||
    map <string, uint32_t> addresses;
 | 
			
		||||
    map <string, uint32_t> offsets;
 | 
			
		||||
    map <string, uint32_t> hexvals;
 | 
			
		||||
    map <string, string> strings;
 | 
			
		||||
    vector<t_class> classes;
 | 
			
		||||
    vector<vector<t_type> > classsubtypes;
 | 
			
		||||
    int32_t base;
 | 
			
		||||
    uint32_t classindex;
 | 
			
		||||
    string version;
 | 
			
		||||
    OSType OS;
 | 
			
		||||
};
 | 
			
		||||
#endif // MEMINFO_H_INCLUDED
 | 
			
		||||
@ -0,0 +1,160 @@
 | 
			
		||||
/*
 | 
			
		||||
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 "DFCommon.h"
 | 
			
		||||
#ifdef LINUX_BUILD
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Process::Process(DataModel * dm, memory_info* mi, ProcessHandle ph, uint32_t pid)
 | 
			
		||||
{
 | 
			
		||||
    my_datamodel = dm;
 | 
			
		||||
    my_descriptor = mi;
 | 
			
		||||
    my_handle = ph;
 | 
			
		||||
    my_pid = pid;
 | 
			
		||||
    attached = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Process::~Process()
 | 
			
		||||
{
 | 
			
		||||
    if(attached)
 | 
			
		||||
    {
 | 
			
		||||
        detach();
 | 
			
		||||
    }
 | 
			
		||||
    // destroy data model. this is assigned by processmanager
 | 
			
		||||
    delete my_datamodel;
 | 
			
		||||
    freeResources();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DataModel *Process::getDataModel()
 | 
			
		||||
{
 | 
			
		||||
    return my_datamodel;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
memory_info * Process::getDescriptor()
 | 
			
		||||
{
 | 
			
		||||
    return my_descriptor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void Process::setMemFile(const string & memf)
 | 
			
		||||
{
 | 
			
		||||
    assert(!attached);
 | 
			
		||||
    memFile = memf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef LINUX_BUILD
 | 
			
		||||
/*
 | 
			
		||||
 *     LINUX PART
 | 
			
		||||
 */
 | 
			
		||||
bool Process::attach()
 | 
			
		||||
{
 | 
			
		||||
    // TODO: check for errors!
 | 
			
		||||
    if(g_pProcess != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ptrace(PTRACE_ATTACH , my_handle, NULL, NULL);
 | 
			
		||||
    wait(NULL); // wait for DF to be stopped.
 | 
			
		||||
    attached = true;
 | 
			
		||||
 | 
			
		||||
    // HACK: Set the global process variables
 | 
			
		||||
    g_pProcess = this;
 | 
			
		||||
    g_ProcessHandle = my_handle;
 | 
			
		||||
    g_ProcessMemFile = fopen(memFile.c_str(),"rb");
 | 
			
		||||
    return true; // we are attached
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool Process::detach()
 | 
			
		||||
{
 | 
			
		||||
    // TODO: check for errors.
 | 
			
		||||
    ptrace(PTRACE_DETACH, my_handle, NULL, NULL);
 | 
			
		||||
    attached = false;
 | 
			
		||||
 | 
			
		||||
    g_pProcess = NULL;
 | 
			
		||||
    g_ProcessHandle = 0;
 | 
			
		||||
    fclose(g_ProcessMemFile);// close /proc/PID/mem
 | 
			
		||||
    g_ProcessMemFile = NULL;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void Process::freeResources()
 | 
			
		||||
{
 | 
			
		||||
    // nil
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
/*
 | 
			
		||||
 *     WINDOWS PART
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//FIXME: should support stopping and resuming the process
 | 
			
		||||
 | 
			
		||||
bool Process::attach()
 | 
			
		||||
{
 | 
			
		||||
    if(DebugActiveProcess(my_pid))
 | 
			
		||||
    {
 | 
			
		||||
        attached = true;
 | 
			
		||||
        g_pProcess = this;
 | 
			
		||||
        g_ProcessHandle = my_handle;
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool Process::detach()
 | 
			
		||||
{
 | 
			
		||||
    if(!attached)
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if(DebugActiveProcessStop(my_pid))
 | 
			
		||||
    {
 | 
			
		||||
        attached = false;
 | 
			
		||||
        g_pProcess = NULL;
 | 
			
		||||
        g_ProcessHandle = 0;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void Process::freeResources()
 | 
			
		||||
{
 | 
			
		||||
    // opened by process manager
 | 
			
		||||
    CloseHandle(my_handle);
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,526 @@
 | 
			
		||||
/*
 | 
			
		||||
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 "DFCommon.h"
 | 
			
		||||
 | 
			
		||||
#include "DFDataModel.h"
 | 
			
		||||
#include "DFMemInfo.h"
 | 
			
		||||
 | 
			
		||||
#include "tinyxml/tinyxml.h"
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
/// HACK: global variables (only one process can be attached at the same time.)
 | 
			
		||||
Process * g_pProcess; ///< current process. non-NULL when picked
 | 
			
		||||
ProcessHandle g_ProcessHandle; ///< cache of handle to current process. used for speed reasons
 | 
			
		||||
FILE * g_ProcessMemFile; ///< opened /proc/PID/mem, valid when attached
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef LINUX_BUILD
 | 
			
		||||
/*
 | 
			
		||||
 *  LINUX version of the process finder.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "md5/md5wrapper.h"
 | 
			
		||||
 | 
			
		||||
Process* ProcessManager::addProcess(const string & exe,ProcessHandle PH, const string & memFile)
 | 
			
		||||
{
 | 
			
		||||
    md5wrapper md5;
 | 
			
		||||
    // get hash of the running DF process
 | 
			
		||||
    string hash = md5.getHashFromFile(exe);
 | 
			
		||||
    vector<memory_info>::iterator it;
 | 
			
		||||
 | 
			
		||||
    // iterate over the list of memory locations
 | 
			
		||||
    for ( it=meminfo.begin() ; it < meminfo.end(); it++ )
 | 
			
		||||
    {
 | 
			
		||||
        if(hash == (*it).getString("md5")) // are the md5 hashes the same?
 | 
			
		||||
        {
 | 
			
		||||
            memory_info * m = &*it;
 | 
			
		||||
            Process * ret;
 | 
			
		||||
            //cout <<"Found process " << PH <<  ". It's DF version " << m->getVersion() << "." << endl;
 | 
			
		||||
 | 
			
		||||
            // df can run under wine on Linux
 | 
			
		||||
            if(memory_info::OS_WINDOWS == (*it).getOS())
 | 
			
		||||
            {
 | 
			
		||||
                ret= new Process(new DMWindows40d(),m,PH, PH);
 | 
			
		||||
            }
 | 
			
		||||
            else if (memory_info::OS_LINUX == (*it).getOS())
 | 
			
		||||
            {
 | 
			
		||||
                ret= new Process(new DMLinux40d(),m,PH, PH);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                // some error happened, continue with next process
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            // tell Process about the /proc/PID/mem file
 | 
			
		||||
            ret->setMemFile(memFile);
 | 
			
		||||
            processes.push_back(ret);
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ProcessManager::findProcessess()
 | 
			
		||||
{
 | 
			
		||||
    DIR *dir_p;
 | 
			
		||||
    struct dirent *dir_entry_p;
 | 
			
		||||
    string dir_name;
 | 
			
		||||
    string exe_link;
 | 
			
		||||
    string cwd_link;
 | 
			
		||||
    string cmdline_path;
 | 
			
		||||
    string cmdline;
 | 
			
		||||
 | 
			
		||||
    // ALERT: buffer overrun potential
 | 
			
		||||
    char target_name[1024];
 | 
			
		||||
    int target_result;
 | 
			
		||||
    int errorcount;
 | 
			
		||||
    int result;
 | 
			
		||||
 | 
			
		||||
    errorcount=0;
 | 
			
		||||
    result=0;
 | 
			
		||||
    // Open /proc/ directory
 | 
			
		||||
    dir_p = opendir("/proc/");
 | 
			
		||||
    // Reading /proc/ entries
 | 
			
		||||
    while(NULL != (dir_entry_p = readdir(dir_p)))
 | 
			
		||||
    {
 | 
			
		||||
        // Only PID folders (numbers)
 | 
			
		||||
        if (strspn(dir_entry_p->d_name, "0123456789") != strlen(dir_entry_p->d_name))
 | 
			
		||||
        {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // string manipulation - get /proc/PID/exe link and /proc/PID/mem names
 | 
			
		||||
        dir_name = "/proc/";
 | 
			
		||||
        dir_name += dir_entry_p->d_name;
 | 
			
		||||
        dir_name += "/";
 | 
			
		||||
        exe_link = dir_name + "exe";
 | 
			
		||||
        string mem_name = dir_name + "mem";
 | 
			
		||||
 | 
			
		||||
        // resolve /proc/PID/exe link
 | 
			
		||||
        target_result = readlink(exe_link.c_str(), target_name, sizeof(target_name)-1);
 | 
			
		||||
        if (target_result == -1)
 | 
			
		||||
        {
 | 
			
		||||
            // bad result from link resolution, continue with another processed
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        // 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") != NULL)
 | 
			
		||||
        {
 | 
			
		||||
            exe_link = target_name;
 | 
			
		||||
            // get PID
 | 
			
		||||
            result = atoi(dir_entry_p->d_name);
 | 
			
		||||
            // create linux process, add it to the vector
 | 
			
		||||
            addProcess(exe_link,result,mem_name);
 | 
			
		||||
            // continue with next process
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // FIXME: this fails when the wine process isn't started from the 'current working directory'. strip path data from cmdline
 | 
			
		||||
        // DF in wine?
 | 
			
		||||
        if(strstr(target_name, "wine-preloader")!= NULL)
 | 
			
		||||
        {
 | 
			
		||||
            // get working directory
 | 
			
		||||
            cwd_link = dir_name + "cwd";
 | 
			
		||||
            target_result = readlink(cwd_link.c_str(), target_name, sizeof(target_name)-1);
 | 
			
		||||
            target_name[target_result] = 0;
 | 
			
		||||
 | 
			
		||||
            // got path to executable, do the same for its name
 | 
			
		||||
            cmdline_path = dir_name + "cmdline";
 | 
			
		||||
            ifstream ifs ( cmdline_path.c_str() , ifstream::in );
 | 
			
		||||
            getline(ifs,cmdline);
 | 
			
		||||
            if (cmdline.find("dwarfort.exe") != string::npos || cmdline.find("Dwarf Fortress.exe") != string::npos)
 | 
			
		||||
            {
 | 
			
		||||
                // put executable name and path together
 | 
			
		||||
                exe_link = target_name;
 | 
			
		||||
                exe_link += "/";
 | 
			
		||||
                exe_link += cmdline;
 | 
			
		||||
 | 
			
		||||
                // get PID
 | 
			
		||||
                result = atoi(dir_entry_p->d_name);
 | 
			
		||||
 | 
			
		||||
                // create wine process, add it to the vector
 | 
			
		||||
                addProcess(exe_link,result,mem_name);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    closedir(dir_p);
 | 
			
		||||
    // return value depends on if we found some DF processes
 | 
			
		||||
    if(processes.size())
 | 
			
		||||
    {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
// some magic - will come in handy when we start doing debugger stuff on Windows
 | 
			
		||||
bool EnableDebugPriv()
 | 
			
		||||
{
 | 
			
		||||
    bool               bRET = FALSE;
 | 
			
		||||
    TOKEN_PRIVILEGES   tp;
 | 
			
		||||
    HANDLE             hToken;
 | 
			
		||||
 | 
			
		||||
    if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid))
 | 
			
		||||
    {
 | 
			
		||||
        if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
 | 
			
		||||
        {
 | 
			
		||||
            if (hToken != INVALID_HANDLE_VALUE)
 | 
			
		||||
            {
 | 
			
		||||
                tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 | 
			
		||||
                tp.PrivilegeCount = 1;
 | 
			
		||||
                if (AdjustTokenPrivileges(hToken, FALSE, &tp, 0, 0, 0))
 | 
			
		||||
                {
 | 
			
		||||
                    bRET = TRUE;
 | 
			
		||||
                }
 | 
			
		||||
                CloseHandle(hToken);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return bRET;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WINDOWS version of the process finder
 | 
			
		||||
bool ProcessManager::findProcessess()
 | 
			
		||||
{
 | 
			
		||||
    // Get the list of process identifiers.
 | 
			
		||||
    //TODO: make this dynamic. (call first to get the array size and second to really get process handles)
 | 
			
		||||
    DWORD ProcArray[512], memoryNeeded, numProccesses;
 | 
			
		||||
    HMODULE hmod = NULL;
 | 
			
		||||
    DWORD junk;
 | 
			
		||||
    HANDLE hProcess;
 | 
			
		||||
    bool found = false;
 | 
			
		||||
 | 
			
		||||
    IMAGE_NT_HEADERS32 pe_header;
 | 
			
		||||
    IMAGE_SECTION_HEADER sections[16];
 | 
			
		||||
 | 
			
		||||
    EnableDebugPriv();
 | 
			
		||||
    if ( !EnumProcesses( ProcArray, sizeof(ProcArray), &memoryNeeded ) )
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Calculate how many process identifiers were returned.
 | 
			
		||||
    numProccesses = memoryNeeded / sizeof(DWORD);
 | 
			
		||||
 | 
			
		||||
    // iterate through processes
 | 
			
		||||
    for ( int i = 0; i < numProccesses; i++ )
 | 
			
		||||
    {
 | 
			
		||||
        found = false;
 | 
			
		||||
        // open process
 | 
			
		||||
        hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, ProcArray[i] );
 | 
			
		||||
        if (NULL == hProcess)
 | 
			
		||||
            continue;
 | 
			
		||||
        // we've got some process, look at its first module
 | 
			
		||||
        if(EnumProcessModules(hProcess, &hmod, 1 * sizeof(HMODULE), &junk))
 | 
			
		||||
        {
 | 
			
		||||
            // TODO: check module filename to verify that it's DF!
 | 
			
		||||
            // got base ;)
 | 
			
		||||
            uint32_t base = (uint32_t)hmod;
 | 
			
		||||
            // read from this process
 | 
			
		||||
            g_ProcessHandle = hProcess;
 | 
			
		||||
            uint32_t pe_offset = MreadDWord(base+0x3C);
 | 
			
		||||
            Mread(base + pe_offset                   , sizeof(pe_header), (uint8_t *)&pe_header);
 | 
			
		||||
            Mread(base + pe_offset+ sizeof(pe_header), sizeof(sections) , (uint8_t *)§ions );
 | 
			
		||||
            // see if there's a version entry that matches this process
 | 
			
		||||
            vector<memory_info>::iterator it;
 | 
			
		||||
            for ( it=meminfo.begin() ; it < meminfo.end(); it++ )
 | 
			
		||||
            {
 | 
			
		||||
                // filter by OS
 | 
			
		||||
                if(memory_info::OS_WINDOWS == (*it).getOS())
 | 
			
		||||
                {
 | 
			
		||||
                    uint32_t pe_timestamp = (*it).getHexValue("pe_timestamp");
 | 
			
		||||
                    if (pe_timestamp == pe_header.FileHeader.TimeDateStamp)
 | 
			
		||||
                    {
 | 
			
		||||
                        printf("Match found! Using version %s.\n", (*it).getVersion().c_str());
 | 
			
		||||
                        // give the process a data model and memory layout fixed for the base of first module
 | 
			
		||||
                        memory_info *m = new memory_info(*it);
 | 
			
		||||
                        m->RebaseAll(base);
 | 
			
		||||
                        // keep track of created memory_info objects so we can destroy them later
 | 
			
		||||
                        destroy_meminfo.push_back(m);
 | 
			
		||||
                        // process is responsible for destroying its data model
 | 
			
		||||
                        Process *ret= new Process(new DMWindows40d(),m,hProcess, ProcArray[i]);
 | 
			
		||||
                        processes.push_back(ret);
 | 
			
		||||
                        found = true;
 | 
			
		||||
                        break; // break the iterator loop
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            // close handle of processes that aren't DF
 | 
			
		||||
            if(!found)
 | 
			
		||||
            {
 | 
			
		||||
                CloseHandle(hProcess);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
	if(processes.size())
 | 
			
		||||
        return true;
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void ProcessManager::ParseVTable(TiXmlElement* vtable, memory_info& mem)
 | 
			
		||||
{
 | 
			
		||||
    TiXmlElement* pClassEntry;
 | 
			
		||||
    TiXmlElement* pClassSubEntry;
 | 
			
		||||
    const char * rebase = vtable->Attribute("rebase");
 | 
			
		||||
    if(rebase)
 | 
			
		||||
    {
 | 
			
		||||
        int32_t rebase_offset = strtol(rebase, NULL, 16);
 | 
			
		||||
        mem.RebaseVTable(rebase_offset);
 | 
			
		||||
    }
 | 
			
		||||
    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");
 | 
			
		||||
        if(type== "class")
 | 
			
		||||
        {
 | 
			
		||||
            mem.setClass(cstr_name, cstr_vtable);
 | 
			
		||||
        }
 | 
			
		||||
        else if (type == "multiclass")
 | 
			
		||||
        {
 | 
			
		||||
            const char *cstr_typeoffset = pClassEntry->Attribute("typeoffset");
 | 
			
		||||
            int mclass = mem.setMultiClass(cstr_name, cstr_vtable, cstr_typeoffset);
 | 
			
		||||
            pClassSubEntry = pClassEntry->FirstChildElement();
 | 
			
		||||
            for(;pClassSubEntry;pClassSubEntry=pClassSubEntry->NextSiblingElement())
 | 
			
		||||
            {
 | 
			
		||||
                type = pClassSubEntry->Value();
 | 
			
		||||
                if(type== "class")
 | 
			
		||||
                {
 | 
			
		||||
                    cstr_name = pClassSubEntry->Attribute("name");
 | 
			
		||||
                    const char *cstr_value = pClassSubEntry->Attribute("type");
 | 
			
		||||
                    mem.setMultiClassChild(mclass,cstr_name,cstr_value);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void ProcessManager::ParseEntry (TiXmlElement* entry, memory_info& mem, map <string ,TiXmlElement *>& knownEntries)
 | 
			
		||||
{
 | 
			
		||||
    TiXmlElement* pMemEntry;
 | 
			
		||||
    const char *cstr_version = entry->Attribute("version");
 | 
			
		||||
    const char *cstr_os = entry->Attribute("os");
 | 
			
		||||
    const char *cstr_base = entry->Attribute("base");
 | 
			
		||||
    const char *cstr_rebase = entry->Attribute("rebase");
 | 
			
		||||
    if(cstr_base)
 | 
			
		||||
    {
 | 
			
		||||
        string base = cstr_base;
 | 
			
		||||
        ParseEntry(knownEntries[base], mem, knownEntries);
 | 
			
		||||
    }
 | 
			
		||||
    // mandatory attributes missing?
 | 
			
		||||
    if(!(cstr_version && cstr_os))
 | 
			
		||||
    {
 | 
			
		||||
        cerr << "Bad entry in memory.xml detected, version or os attribute is missing.";
 | 
			
		||||
        // skip if we don't have valid attributes
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    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
 | 
			
		||||
    {
 | 
			
		||||
        cerr << "unknown operating system " << os << endl;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    // 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();
 | 
			
		||||
        // check for missing parts
 | 
			
		||||
        string type, name, value;
 | 
			
		||||
        type = cstr_type;
 | 
			
		||||
        if(type == "VTable")
 | 
			
		||||
        {
 | 
			
		||||
            ParseVTable(pMemEntry, mem);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        if( !(cstr_name && cstr_value))
 | 
			
		||||
        {
 | 
			
		||||
            cerr << "underspecified MemInfo entry" << endl;
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        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
 | 
			
		||||
        {
 | 
			
		||||
            cerr << "Unknown MemInfo type: " << type << endl;
 | 
			
		||||
        }
 | 
			
		||||
    } // for
 | 
			
		||||
} // method
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// load the XML file with offsets
 | 
			
		||||
bool ProcessManager::loadDescriptors(string path_to_xml)
 | 
			
		||||
{
 | 
			
		||||
    TiXmlDocument doc( path_to_xml.c_str() );
 | 
			
		||||
    bool loadOkay = doc.LoadFile();
 | 
			
		||||
	TiXmlHandle hDoc(&doc);
 | 
			
		||||
	TiXmlElement* pElem;
 | 
			
		||||
	TiXmlHandle hRoot(0);
 | 
			
		||||
    memory_info mem;
 | 
			
		||||
 | 
			
		||||
    if ( loadOkay )
 | 
			
		||||
    {
 | 
			
		||||
        // block: name
 | 
			
		||||
        {
 | 
			
		||||
            pElem=hDoc.FirstChildElement().Element();
 | 
			
		||||
            // should always have a valid root but handle gracefully if it does
 | 
			
		||||
            if (!pElem)
 | 
			
		||||
            {
 | 
			
		||||
                cerr << "no pElem found" << endl;
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            string m_name=pElem->Value();
 | 
			
		||||
            if(m_name != "DFExtractor")
 | 
			
		||||
            {
 | 
			
		||||
                cerr << "DFExtractor != " << m_name << endl;
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            //cout << "got DFExtractor XML!" << endl;
 | 
			
		||||
            // save this for later
 | 
			
		||||
            hRoot=TiXmlHandle(pElem);
 | 
			
		||||
        }
 | 
			
		||||
        // transform elements
 | 
			
		||||
        {
 | 
			
		||||
            // trash existing list
 | 
			
		||||
            meminfo.clear();
 | 
			
		||||
            TiXmlElement* pMemInfo=hRoot.FirstChild( "MemoryDescriptors" ).FirstChild( "Entry" ).Element();
 | 
			
		||||
            map <string ,TiXmlElement *> map_pNamedEntries;
 | 
			
		||||
            vector <TiXmlElement *> v_pEntries;
 | 
			
		||||
            for( ; pMemInfo; pMemInfo=pMemInfo->NextSiblingElement("Entry"))
 | 
			
		||||
            {
 | 
			
		||||
                v_pEntries.push_back(pMemInfo);
 | 
			
		||||
                const char *id;
 | 
			
		||||
                if(id= pMemInfo->Attribute("id"))
 | 
			
		||||
                {
 | 
			
		||||
                    string str_id = id;
 | 
			
		||||
                    map_pNamedEntries[str_id] = pMemInfo;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            for(uint32_t i = 0; i< v_pEntries.size();i++)
 | 
			
		||||
            {
 | 
			
		||||
                memory_info mem;
 | 
			
		||||
                //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
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        // load failed
 | 
			
		||||
        cerr << "Can't load memory offsets from memory.xml" << endl;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint32_t ProcessManager::size()
 | 
			
		||||
{
 | 
			
		||||
    return processes.size();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Process * ProcessManager::operator[](uint32_t index)
 | 
			
		||||
{
 | 
			
		||||
    assert(index < processes.size());
 | 
			
		||||
    return processes[index];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ProcessManager::ProcessManager( string path_to_xml )
 | 
			
		||||
{
 | 
			
		||||
    currentProcess = NULL;
 | 
			
		||||
    currentProcessHandle = 0;
 | 
			
		||||
    loadDescriptors( path_to_xml );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ProcessManager::~ProcessManager()
 | 
			
		||||
{
 | 
			
		||||
    // delete all processes
 | 
			
		||||
    for(uint32_t i = 0;i < processes.size();i++)
 | 
			
		||||
    {
 | 
			
		||||
        delete processes[i];
 | 
			
		||||
    }
 | 
			
		||||
    //delete all generated memory_info stuff
 | 
			
		||||
    for(uint32_t i = 0;i < destroy_meminfo.size();i++)
 | 
			
		||||
    {
 | 
			
		||||
        delete destroy_meminfo[i];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,97 @@
 | 
			
		||||
/*
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef PROCESSMANAGER_H_INCLUDED
 | 
			
		||||
#define PROCESSMANAGER_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#ifdef LINUX_BUILD
 | 
			
		||||
typedef pid_t ProcessHandle;
 | 
			
		||||
#else
 | 
			
		||||
typedef HANDLE ProcessHandle;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
class memory_info;
 | 
			
		||||
class DataModel;
 | 
			
		||||
class TiXmlElement;
 | 
			
		||||
class Process;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
* Currently attached process and its handle
 | 
			
		||||
*/
 | 
			
		||||
extern Process * g_pProcess; ///< current process. non-NULL when picked
 | 
			
		||||
extern ProcessHandle g_ProcessHandle; ///< cache of handle to current process. used for speed reasons
 | 
			
		||||
extern FILE * g_ProcessMemFile; ///< opened /proc/PID/mem, valid when attached
 | 
			
		||||
 | 
			
		||||
class Process
 | 
			
		||||
{
 | 
			
		||||
    friend class ProcessManager;
 | 
			
		||||
    protected:
 | 
			
		||||
        Process(DataModel * dm, memory_info* mi, ProcessHandle ph, uint32_t pid);
 | 
			
		||||
        ~Process();
 | 
			
		||||
        DataModel* my_datamodel;
 | 
			
		||||
        memory_info * my_descriptor;
 | 
			
		||||
        ProcessHandle my_handle;
 | 
			
		||||
        uint32_t my_pid;
 | 
			
		||||
        string memFile;
 | 
			
		||||
        bool attached;
 | 
			
		||||
        void freeResources();
 | 
			
		||||
        void setMemFile(const string & memf);
 | 
			
		||||
    public:
 | 
			
		||||
        // Set up stuff so we can read memory
 | 
			
		||||
        bool attach();
 | 
			
		||||
        bool detach();
 | 
			
		||||
        // is the process still there?
 | 
			
		||||
        memory_info *getDescriptor();
 | 
			
		||||
        DataModel *getDataModel();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Process manager
 | 
			
		||||
 */
 | 
			
		||||
class ProcessManager
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    ProcessManager( string path_to_xml);
 | 
			
		||||
    ~ProcessManager();
 | 
			
		||||
    bool findProcessess();
 | 
			
		||||
    uint32_t size();
 | 
			
		||||
    Process * operator[](uint32_t index);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // memory info entries loaded from a file
 | 
			
		||||
    std::vector<memory_info> meminfo;
 | 
			
		||||
    // vector to keep track of dynamically created memory_info entries
 | 
			
		||||
    std::vector<memory_info *> destroy_meminfo;
 | 
			
		||||
    Process * currentProcess;
 | 
			
		||||
    ProcessHandle currentProcessHandle;
 | 
			
		||||
    std::vector<Process *> processes;
 | 
			
		||||
    bool loadDescriptors( string path_to_xml);
 | 
			
		||||
    void ParseVTable(TiXmlElement* vtable, memory_info& mem);
 | 
			
		||||
    void ParseEntry (TiXmlElement* entry, memory_info& mem, map <string ,TiXmlElement *>& knownEntries);
 | 
			
		||||
#ifdef LINUX_BUILD
 | 
			
		||||
    Process* addProcess(const string & exe,ProcessHandle PH,const string & memFile);
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // PROCESSMANAGER_H_INCLUDED
 | 
			
		||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								@ -0,0 +1,37 @@
 | 
			
		||||
/*
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef TILETYPES_H_INCLUDED
 | 
			
		||||
#define TILETYPES_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
/// TODO: turn into XML
 | 
			
		||||
 | 
			
		||||
bool isWallTerrain(int in);
 | 
			
		||||
bool isFloorTerrain(int in);
 | 
			
		||||
bool isRampTerrain(int in);
 | 
			
		||||
bool isStairTerrain(int in);
 | 
			
		||||
bool isOpenTerrain(int in);
 | 
			
		||||
int picktexture(int in);
 | 
			
		||||
 | 
			
		||||
#endif // TILETYPES_H_INCLUDED
 | 
			
		||||
@ -0,0 +1,250 @@
 | 
			
		||||
/*
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef TYPES_H_INCLUDED
 | 
			
		||||
#define TYPES_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
struct t_matgloss
 | 
			
		||||
{
 | 
			
		||||
       string id;
 | 
			
		||||
       uint8_t fore; // Annoyingly the offset for this differs between types
 | 
			
		||||
       uint8_t back;
 | 
			
		||||
       uint8_t bright;
 | 
			
		||||
};
 | 
			
		||||
struct t_vein
 | 
			
		||||
{
 | 
			
		||||
    uint32_t vtable;
 | 
			
		||||
    int16_t type;
 | 
			
		||||
    int16_t assignment[16];
 | 
			
		||||
    int16_t unknown;
 | 
			
		||||
    uint32_t flags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct t_matglossPair
 | 
			
		||||
{
 | 
			
		||||
    int16_t type;
 | 
			
		||||
    int16_t index;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// raw
 | 
			
		||||
struct t_construction_df40d
 | 
			
		||||
{
 | 
			
		||||
    int16_t x;
 | 
			
		||||
    int16_t y;
 | 
			
		||||
    int16_t z;
 | 
			
		||||
    int16_t unk1;
 | 
			
		||||
    int16_t unk2;
 | 
			
		||||
    t_matglossPair material; // 4B
 | 
			
		||||
//    int16_t mat_type;
 | 
			
		||||
//    int16_t mat_idx;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// cooked
 | 
			
		||||
struct t_construction
 | 
			
		||||
{
 | 
			
		||||
    uint16_t x;
 | 
			
		||||
    uint16_t y;
 | 
			
		||||
    uint16_t z;
 | 
			
		||||
    t_matglossPair material;
 | 
			
		||||
//    int16_t mat_type;
 | 
			
		||||
//    int16_t mat_idx;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
		dword vtable;
 | 
			
		||||
		int minx;
 | 
			
		||||
		int miny;
 | 
			
		||||
		int centerx;
 | 
			
		||||
		int maxx;
 | 
			
		||||
		int maxy;
 | 
			
		||||
		int centery;
 | 
			
		||||
		int z;
 | 
			
		||||
		dword height_not_used;
 | 
			
		||||
		word  mattype;
 | 
			
		||||
		word  matgloss;
 | 
			
		||||
		word  type; // NOTE: the actual field is in a different place
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//raw
 | 
			
		||||
struct t_building_df40d
 | 
			
		||||
{
 | 
			
		||||
    uint32_t vtable;
 | 
			
		||||
    uint32_t x1;
 | 
			
		||||
    uint32_t y1;
 | 
			
		||||
    uint32_t centerx;
 | 
			
		||||
    uint32_t x2;
 | 
			
		||||
    uint32_t y2;
 | 
			
		||||
    uint32_t centery;
 | 
			
		||||
    uint32_t z;
 | 
			
		||||
    uint32_t height;
 | 
			
		||||
    t_matglossPair material;
 | 
			
		||||
    // not complete
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//cooked
 | 
			
		||||
struct t_building
 | 
			
		||||
{
 | 
			
		||||
    uint32_t vtable;
 | 
			
		||||
 | 
			
		||||
    uint32_t x1;
 | 
			
		||||
    uint32_t y1;
 | 
			
		||||
 | 
			
		||||
    uint32_t x2;
 | 
			
		||||
    uint32_t y2;
 | 
			
		||||
 | 
			
		||||
    uint32_t z;
 | 
			
		||||
 | 
			
		||||
    t_matglossPair material;
 | 
			
		||||
 | 
			
		||||
    uint32_t type;
 | 
			
		||||
    // FIXME: not complete, we need building presence bitmaps for stuff like farm plots and stockpiles, orientation (N,E,S,W) and state (open/closed)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct t_tree_desc
 | 
			
		||||
{
 | 
			
		||||
    t_matglossPair material;
 | 
			
		||||
    uint16_t x;
 | 
			
		||||
    uint16_t y;
 | 
			
		||||
    uint16_t z;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// FIXME: in order in which the raw vectors appear in df memory, move to XML
 | 
			
		||||
enum RawType
 | 
			
		||||
{
 | 
			
		||||
    Mat_Wood,
 | 
			
		||||
    Mat_Stone,
 | 
			
		||||
    Mat_Plant,
 | 
			
		||||
    Mat_Metal,
 | 
			
		||||
    NUM_MATGLOSS_TYPES
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum BiomeOffset
 | 
			
		||||
{
 | 
			
		||||
    eNorthWest,
 | 
			
		||||
    eNorth,
 | 
			
		||||
    eNorthEast,
 | 
			
		||||
    eWest,
 | 
			
		||||
    eHere,
 | 
			
		||||
    eEast,
 | 
			
		||||
    eSouthWest,
 | 
			
		||||
    eSouth,
 | 
			
		||||
    eSouthEast,
 | 
			
		||||
    eBiomeCount
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// TODO: research this further? consult DF hacker wizards?
 | 
			
		||||
union t_designation
 | 
			
		||||
{
 | 
			
		||||
    uint32_t whole;
 | 
			
		||||
    struct {
 | 
			
		||||
    unsigned int flow_size : 3; // how much liquid is here?
 | 
			
		||||
    unsigned int pile : 1; // stockpile?
 | 
			
		||||
/*
 | 
			
		||||
 * All the different dig designations... needs more info, probably an enum
 | 
			
		||||
 */
 | 
			
		||||
    unsigned int dig : 3;
 | 
			
		||||
    unsigned int detail : 1;///<- wtf
 | 
			
		||||
    unsigned int detail_event : 1;///<- more wtf
 | 
			
		||||
    unsigned int hidden :1;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This one is rather involved, but necessary to retrieve the base layer matgloss index
 | 
			
		||||
 * see http://www.bay12games.com/forum/index.php?topic=608.msg253284#msg253284 for details
 | 
			
		||||
 */
 | 
			
		||||
    unsigned int geolayer_index :4;
 | 
			
		||||
    unsigned int light : 1;
 | 
			
		||||
    unsigned int subterranean : 1; // never seen the light of day?
 | 
			
		||||
    unsigned int skyview : 1; // sky is visible now, it rains in here when it rains
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Probably similar to the geolayer_index. Only with a different set of offsets and different data.
 | 
			
		||||
 * we don't use this yet
 | 
			
		||||
 */
 | 
			
		||||
    unsigned int biome : 4;
 | 
			
		||||
/*
 | 
			
		||||
0 = water
 | 
			
		||||
1 = magma
 | 
			
		||||
*/
 | 
			
		||||
    unsigned int liquid_type : 1;
 | 
			
		||||
    unsigned int water_table : 1; // srsly. wtf?
 | 
			
		||||
    unsigned int rained : 1; // does this mean actual rain (as in the blue blocks) or a wet tile?
 | 
			
		||||
    unsigned int traffic : 2; // needs enum
 | 
			
		||||
    unsigned int flow_forbid : 1; // idk wtf bbq
 | 
			
		||||
    unsigned int liquid_static : 1;
 | 
			
		||||
    unsigned int moss : 1;// I LOVE MOSS
 | 
			
		||||
    unsigned int feature_present : 1; // another wtf... is this required for magma pipes to work?
 | 
			
		||||
    unsigned int liquid_character : 2; // those ripples on streams?
 | 
			
		||||
    } bits;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// occupancy flags (rat,dwarf,horse,built wall,not build wall,etc)
 | 
			
		||||
union t_occupancy
 | 
			
		||||
{
 | 
			
		||||
    uint32_t whole;
 | 
			
		||||
    struct {
 | 
			
		||||
    unsigned int building : 3;// building type... should be an enum?
 | 
			
		||||
    // 7 = door
 | 
			
		||||
    unsigned int unit : 1;
 | 
			
		||||
    unsigned int unit_grounded : 1;
 | 
			
		||||
    unsigned int item : 1;
 | 
			
		||||
    // splatter. everyone loves splatter.
 | 
			
		||||
    unsigned int mud : 1;
 | 
			
		||||
    unsigned int vomit :1;
 | 
			
		||||
    unsigned int debris1 :1;
 | 
			
		||||
    unsigned int debris2 :1;
 | 
			
		||||
    unsigned int debris3 :1;
 | 
			
		||||
    unsigned int debris4 :1;
 | 
			
		||||
    unsigned int blood_g : 1;
 | 
			
		||||
    unsigned int blood_g2 : 1;
 | 
			
		||||
    unsigned int blood_b : 1;
 | 
			
		||||
    unsigned int blood_b2 : 1;
 | 
			
		||||
    unsigned int blood_y : 1;
 | 
			
		||||
    unsigned int blood_y2 : 1;
 | 
			
		||||
    unsigned int blood_m : 1;
 | 
			
		||||
    unsigned int blood_m2 : 1;
 | 
			
		||||
    unsigned int blood_c : 1;
 | 
			
		||||
    unsigned int blood_c2 : 1;
 | 
			
		||||
    unsigned int blood_w : 1;
 | 
			
		||||
    unsigned int blood_w2 : 1;
 | 
			
		||||
    unsigned int blood_o : 1;
 | 
			
		||||
    unsigned int blood_o2 : 1;
 | 
			
		||||
    unsigned int slime : 1;
 | 
			
		||||
    unsigned int slime2 : 1;
 | 
			
		||||
    unsigned int blood : 1;
 | 
			
		||||
    unsigned int blood2 : 1;
 | 
			
		||||
    unsigned int debris5 : 1;
 | 
			
		||||
    unsigned int snow : 1;
 | 
			
		||||
    } bits;
 | 
			
		||||
    struct {
 | 
			
		||||
        unsigned int building : 3;// building type... should be an enum?
 | 
			
		||||
        // 7 = door
 | 
			
		||||
        unsigned int unit : 1;
 | 
			
		||||
        unsigned int unit_grounded : 1;
 | 
			
		||||
        unsigned int item : 1;
 | 
			
		||||
        // splatter. everyone loves splatter.
 | 
			
		||||
        unsigned int splatter : 26;
 | 
			
		||||
    } unibits;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // TYPES_H_INCLUDED
 | 
			
		||||
@ -0,0 +1,67 @@
 | 
			
		||||
/*
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef DFVECTOR_H_INCLUDED
 | 
			
		||||
#define DFVECTOR_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
class DfVector
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
    // starting offset
 | 
			
		||||
    uint32_t start;
 | 
			
		||||
    // vector size
 | 
			
		||||
    uint32_t size;
 | 
			
		||||
    // vector item size
 | 
			
		||||
    uint32_t item_size;
 | 
			
		||||
    
 | 
			
		||||
public:
 | 
			
		||||
    DfVector(uint32_t _start, uint32_t _size, uint32_t _item_size):
 | 
			
		||||
        start(_start),size(_size),item_size(_item_size) {};
 | 
			
		||||
    DfVector(const DfVector & vec)
 | 
			
		||||
    {
 | 
			
		||||
        start = vec.start;
 | 
			
		||||
        size = vec.size;
 | 
			
		||||
        item_size = vec.item_size;
 | 
			
		||||
    };
 | 
			
		||||
    DfVector(){};
 | 
			
		||||
    // get offset of the specified index
 | 
			
		||||
    inline uint32_t operator[](uint32_t index)
 | 
			
		||||
    {
 | 
			
		||||
        assert(index < size);
 | 
			
		||||
        return start + index*item_size;
 | 
			
		||||
    };
 | 
			
		||||
    // get vector size
 | 
			
		||||
    inline uint32_t getSize()
 | 
			
		||||
    {
 | 
			
		||||
        return size;
 | 
			
		||||
    };
 | 
			
		||||
    // read item_size bytes from the right offset
 | 
			
		||||
    inline void read (uint32_t index, uint8_t *target)
 | 
			
		||||
    {
 | 
			
		||||
        assert(index < size);
 | 
			
		||||
        Mread (start + index*item_size, item_size, target);
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // DFVECTOR_H_INCLUDED
 | 
			
		||||
@ -0,0 +1,173 @@
 | 
			
		||||
/*
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * DO NOT USE THIS FILE DIRECTLY! USE MemAccess.h INSTEAD!
 | 
			
		||||
 */
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
uint8_t MreadByte (const uint32_t &offset)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t val;
 | 
			
		||||
    fseek(g_ProcessMemFile, offset,SEEK_SET);
 | 
			
		||||
    fread ( &val, sizeof(uint8_t), 1, g_ProcessMemFile );
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
void MreadByte (const uint32_t &offset, uint8_t &val )
 | 
			
		||||
{
 | 
			
		||||
    fseek(g_ProcessMemFile, offset,SEEK_SET);
 | 
			
		||||
    fread ( &val, sizeof(uint8_t), 1, g_ProcessMemFile );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
uint16_t MreadWord (const uint32_t &offset)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t val;
 | 
			
		||||
    fseek(g_ProcessMemFile, offset,SEEK_SET);
 | 
			
		||||
    fread ( &val, sizeof(uint16_t), 1, g_ProcessMemFile );
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
void MreadWord (const uint32_t &offset, uint16_t &val)
 | 
			
		||||
{
 | 
			
		||||
    fseek(g_ProcessMemFile, offset,SEEK_SET);
 | 
			
		||||
    fread ( &val, sizeof(uint16_t), 1, g_ProcessMemFile );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
uint32_t MreadDWord (const uint32_t &offset)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t val;
 | 
			
		||||
    fseek(g_ProcessMemFile, offset,SEEK_SET);
 | 
			
		||||
    fread ( &val, sizeof(uint32_t), 1, g_ProcessMemFile );
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
inline
 | 
			
		||||
void MreadDWord (const uint32_t &offset, uint32_t &val)
 | 
			
		||||
{
 | 
			
		||||
    fseek(g_ProcessMemFile, offset,SEEK_SET);
 | 
			
		||||
    fread ( &val, sizeof(uint32_t), 1, g_ProcessMemFile );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
uint64_t MreadQuad (const uint32_t &offset)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t val;
 | 
			
		||||
    fseek(g_ProcessMemFile, offset,SEEK_SET);
 | 
			
		||||
    fread ( &val, sizeof(uint32_t), 1, g_ProcessMemFile );
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
void MreadQuad (const uint32_t &offset, uint64_t &val)
 | 
			
		||||
{
 | 
			
		||||
    fseek(g_ProcessMemFile, offset,SEEK_SET);
 | 
			
		||||
    fread ( &val, sizeof(uint32_t), 1, g_ProcessMemFile );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
void Mread (const uint32_t &offset, const uint32_t &size, uint8_t *target)
 | 
			
		||||
{
 | 
			
		||||
    fseek(g_ProcessMemFile, offset,SEEK_SET);
 | 
			
		||||
    fread ( target, 1, size, g_ProcessMemFile );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
void MwriteDWord (uint32_t offset, uint32_t data)
 | 
			
		||||
{
 | 
			
		||||
    ptrace(PTRACE_POKEDATA,g_ProcessHandle, offset, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// using these is expensive.
 | 
			
		||||
inline
 | 
			
		||||
void MwriteWord (uint32_t offset, uint16_t data)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t orig = MreadDWord(offset);
 | 
			
		||||
    orig |= 0x0000FFFF;
 | 
			
		||||
    orig &= data;
 | 
			
		||||
    ptrace(PTRACE_POKEDATA,g_ProcessHandle, offset, orig);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
void MwriteByte (uint32_t offset, uint8_t data)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t orig = MreadDWord(offset);
 | 
			
		||||
    orig |= 0x000000FF;
 | 
			
		||||
    orig &= data;
 | 
			
		||||
    ptrace(PTRACE_POKEDATA,g_ProcessHandle, offset, orig);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// blah. I hate the kernel devs for crippling /proc/PID/mem. THIS IS RIDICULOUS
 | 
			
		||||
inline
 | 
			
		||||
bool Mwrite (uint32_t offset, uint32_t size, uint8_t *source)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t indexptr = 0;
 | 
			
		||||
    while (size > 0)
 | 
			
		||||
    {
 | 
			
		||||
        // default: we push 4 bytes
 | 
			
		||||
        if(size >= 4)
 | 
			
		||||
        {
 | 
			
		||||
            MwriteDWord(offset, *(uint32_t *) (source + indexptr));
 | 
			
		||||
            offset +=4;
 | 
			
		||||
            indexptr +=4;
 | 
			
		||||
            size -=4;
 | 
			
		||||
        }
 | 
			
		||||
        // last is either three or 2 bytes
 | 
			
		||||
        else if(size >= 2)
 | 
			
		||||
        {
 | 
			
		||||
            MwriteWord(offset, *(uint16_t *) (source + indexptr));
 | 
			
		||||
            offset +=2;
 | 
			
		||||
            indexptr +=2;
 | 
			
		||||
            size -=2;
 | 
			
		||||
        }
 | 
			
		||||
        // finishing move
 | 
			
		||||
        else if(size == 1)
 | 
			
		||||
        {
 | 
			
		||||
            MwriteByte(offset, *(uint8_t *) (source + indexptr));
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
const std::string MreadCString (uint32_t offset)
 | 
			
		||||
{
 | 
			
		||||
    std::string temp;
 | 
			
		||||
    char temp_c[256];
 | 
			
		||||
    int counter = 0;
 | 
			
		||||
    char r;
 | 
			
		||||
    do
 | 
			
		||||
    {
 | 
			
		||||
        r = MreadByte(offset+counter);
 | 
			
		||||
        temp_c[counter] = r;
 | 
			
		||||
        counter++;
 | 
			
		||||
    } while (r);
 | 
			
		||||
    temp_c[counter] = 0;
 | 
			
		||||
    temp = temp_c;
 | 
			
		||||
    return temp;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,156 @@
 | 
			
		||||
/*
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * DO NOT USE THIS FILE DIRECTLY! USE MemAccess.h INSTEAD!
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// let's hope this commented crap is never needed
 | 
			
		||||
    /*
 | 
			
		||||
    char buffer[256];
 | 
			
		||||
    DWORD oldProtect = 0;
 | 
			
		||||
    DWORD numRead = 0;
 | 
			
		||||
    VirtualProtectEx( hProc, (LPVOID)0x77810F34, 256, PAGE_EXECUTE_READWRITE, &oldProtect );
 | 
			
		||||
    ReadProcessMemory( hProc, (LPVOID)0x77810F34, buffer, 256, &numRead );
 | 
			
		||||
    VirtualProtectEx( hProc, (LPVOID)0x77810F34, 256, oldProtect, NULL ); //restore the original protection when you're done
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
// it would be possible to replace all this by macros
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
uint8_t MreadByte (const uint32_t &offset)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t result;
 | 
			
		||||
    ReadProcessMemory(g_ProcessHandle, (int*) offset, &result, sizeof(uint8_t), NULL);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
void MreadByte (const uint32_t &offset,uint8_t &result)
 | 
			
		||||
{
 | 
			
		||||
    ReadProcessMemory(g_ProcessHandle, (int*) offset, &result, sizeof(uint8_t), NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
uint16_t MreadWord (const uint32_t &offset)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t result;
 | 
			
		||||
    ReadProcessMemory(g_ProcessHandle, (int*) offset, &result, sizeof(uint16_t), NULL);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
void MreadWord (const uint32_t &offset, uint16_t &result)
 | 
			
		||||
{
 | 
			
		||||
    ReadProcessMemory(g_ProcessHandle, (int*) offset, &result, sizeof(uint16_t), NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
uint32_t MreadDWord (const uint32_t &offset)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t result;
 | 
			
		||||
    ReadProcessMemory(g_ProcessHandle, (int*) offset, &result, sizeof(uint32_t), NULL);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
void MreadDWord (const uint32_t &offset, uint32_t &result)
 | 
			
		||||
{
 | 
			
		||||
    ReadProcessMemory(g_ProcessHandle, (int*) offset, &result, sizeof(uint32_t), NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
uint64_t MreadQuad (const uint32_t &offset)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t result;
 | 
			
		||||
    ReadProcessMemory(g_ProcessHandle, (int*) offset, &result, sizeof(uint64_t), NULL);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
void MreadQuad (const uint32_t &offset, uint64_t &result)
 | 
			
		||||
{
 | 
			
		||||
    ReadProcessMemory(g_ProcessHandle, (int*) offset, &result, sizeof(uint64_t), NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
void Mread (const uint32_t &offset, uint32_t size, uint8_t *target)
 | 
			
		||||
{
 | 
			
		||||
    ReadProcessMemory(g_ProcessHandle, (int*) offset, target, size, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WRITING
 | 
			
		||||
inline
 | 
			
		||||
void MwriteDWord (const uint32_t offset, uint32_t data)
 | 
			
		||||
{
 | 
			
		||||
    WriteProcessMemory(g_ProcessHandle, (int*) offset, &data, sizeof(uint32_t), NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// using these is expensive.
 | 
			
		||||
inline
 | 
			
		||||
void MwriteWord (uint32_t offset, uint16_t data)
 | 
			
		||||
{
 | 
			
		||||
    WriteProcessMemory(g_ProcessHandle, (int*) offset, &data, sizeof(uint16_t), NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
void MwriteByte (uint32_t offset, uint8_t data)
 | 
			
		||||
{
 | 
			
		||||
    WriteProcessMemory(g_ProcessHandle, (int*) offset, &data, sizeof(uint8_t), NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
bool Mwrite (uint32_t offset, uint32_t size, uint8_t *source)
 | 
			
		||||
{
 | 
			
		||||
    WriteProcessMemory(g_ProcessHandle, (int*) offset, source, size, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///FIXME: reduce use of temporary objects
 | 
			
		||||
inline
 | 
			
		||||
const string MreadCString (const uint32_t &offset)
 | 
			
		||||
{
 | 
			
		||||
    string temp;
 | 
			
		||||
    char temp_c[256];
 | 
			
		||||
    int counter = 0;
 | 
			
		||||
    char r;
 | 
			
		||||
    do
 | 
			
		||||
    {
 | 
			
		||||
        r = MreadByte(offset+counter);
 | 
			
		||||
        temp_c[counter] = r;
 | 
			
		||||
        counter++;
 | 
			
		||||
    } while (r);
 | 
			
		||||
    temp_c[counter] = 0;
 | 
			
		||||
    temp = temp_c;
 | 
			
		||||
    return temp;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,661 @@
 | 
			
		||||
/*
 | 
			
		||||
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 "DFCommon.h"
 | 
			
		||||
// zlib helper functions for de/compressing files
 | 
			
		||||
#include "ZlibHelper.h"
 | 
			
		||||
#include "DfMapHeader.h"
 | 
			
		||||
 | 
			
		||||
// some bounds checking in debug mode. used in asserts
 | 
			
		||||
#define CheckBounds x < x_cell_count && x >= 0 && y < y_cell_count && y >= 0 && z < z_block_count && z >= 0
 | 
			
		||||
#define CheckBoundsXY x < x_cell_count && x >= 0 && y < y_cell_count && y >= 0
 | 
			
		||||
#define CheckBlockBounds x < x_block_count && x >= 0 && y < y_block_count && y >= 0 && z < z_block_count && z >= 0
 | 
			
		||||
 | 
			
		||||
// this expands into lots of ugly switch statement functions. some of them unused?, but kept for reference
 | 
			
		||||
#include "DFTileTypes.h"
 | 
			
		||||
 | 
			
		||||
// process vein vector into matgloss values...
 | 
			
		||||
void Block::collapseVeins()
 | 
			
		||||
{
 | 
			
		||||
    // iterate through assigned veins
 | 
			
		||||
    for( uint32_t i = 0; i < veins.size(); i++)
 | 
			
		||||
    {
 | 
			
		||||
        t_vein v = veins[i];
 | 
			
		||||
        //iterate through vein assignment bit arrays - one for every row
 | 
			
		||||
        for(uint32_t j = 0;j<16;j++)
 | 
			
		||||
        {
 | 
			
		||||
            //iterate through the bits
 | 
			
		||||
            for (uint32_t k = 0; k< 16;k++)
 | 
			
		||||
            {
 | 
			
		||||
                // and the bit array with a one-bit mask, check if the bit is set
 | 
			
		||||
                bool set = ((1 << k) & v.assignment[j]) >> k;
 | 
			
		||||
                if(set)
 | 
			
		||||
                {
 | 
			
		||||
                    material[k][j].type = Mat_Stone;
 | 
			
		||||
                    material[k][j].index = v.type;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DfMap::~DfMap()
 | 
			
		||||
{
 | 
			
		||||
    clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// TODO: make this sync
 | 
			
		||||
void DfMap::clear()
 | 
			
		||||
{
 | 
			
		||||
    if(valid)
 | 
			
		||||
    {
 | 
			
		||||
        valid = false;
 | 
			
		||||
        for(uint32_t i = 0; i < x_block_count*y_block_count*z_block_count;i++)
 | 
			
		||||
        {
 | 
			
		||||
            Block * b = block[i];
 | 
			
		||||
            if(b!=NULL)
 | 
			
		||||
            {
 | 
			
		||||
                delete b;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        delete[] block;
 | 
			
		||||
    }
 | 
			
		||||
    for (uint32_t i = eNorthWest; i< eBiomeCount;i++)
 | 
			
		||||
    {
 | 
			
		||||
        v_geology[i].clear();
 | 
			
		||||
        //geodebug[i].clear();
 | 
			
		||||
        //geoblockadresses[i] = 0;
 | 
			
		||||
        //regionadresses[i] = 0;
 | 
			
		||||
    }
 | 
			
		||||
    for(uint32_t counter = Mat_Wood; counter < NUM_MATGLOSS_TYPES; counter++)
 | 
			
		||||
    {
 | 
			
		||||
        v_matgloss[counter].clear();
 | 
			
		||||
    }
 | 
			
		||||
    // delete buildings, clear vector
 | 
			
		||||
    for(uint32_t i = 0; i < v_buildings.size(); i++)
 | 
			
		||||
    {
 | 
			
		||||
        delete v_buildings[i];
 | 
			
		||||
    }
 | 
			
		||||
    v_buildings.clear();
 | 
			
		||||
 | 
			
		||||
    // delete vegetation, clear vector
 | 
			
		||||
    for(uint32_t i = 0; i < v_trees.size(); i++)
 | 
			
		||||
    {
 | 
			
		||||
        delete v_trees[i];
 | 
			
		||||
    }
 | 
			
		||||
    v_trees.clear();
 | 
			
		||||
    // clear construction vector
 | 
			
		||||
    v_constructions.clear();
 | 
			
		||||
    blocks_allocated = 0;
 | 
			
		||||
    ///FIXME: destroy all the extracted data here
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void DfMap::getRegionCoords (uint32_t &x,uint32_t &y,uint32_t &z)
 | 
			
		||||
{
 | 
			
		||||
    x= regionX;
 | 
			
		||||
    y= regionY;
 | 
			
		||||
    z= regionZ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void DfMap::setRegionCoords (uint32_t x,uint32_t y,uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    regionX = x;
 | 
			
		||||
    regionY = y;
 | 
			
		||||
    regionZ = z;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void DfMap::allocBlockArray(uint32_t x,uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    clear();
 | 
			
		||||
    x_block_count = x;
 | 
			
		||||
    y_block_count = y;
 | 
			
		||||
    z_block_count = z;
 | 
			
		||||
    updateCellCount();
 | 
			
		||||
    block = new Block*[x_block_count*y_block_count*z_block_count];
 | 
			
		||||
    for (uint32_t i = 0; i < x_block_count*y_block_count*z_block_count; i++ )
 | 
			
		||||
    {
 | 
			
		||||
        block[i] = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    blocks_allocated = 0;
 | 
			
		||||
    valid = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DfMap::DfMap(uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    valid = false;
 | 
			
		||||
    allocBlockArray(x,y,z);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DfMap::DfMap(string FileName)
 | 
			
		||||
{
 | 
			
		||||
    valid = false;
 | 
			
		||||
    valid = load( FileName);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool DfMap::isValid ()
 | 
			
		||||
{
 | 
			
		||||
    return valid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Block * DfMap::getBlock (uint32_t x,uint32_t y,uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    if(isValid())
 | 
			
		||||
    {
 | 
			
		||||
        return block[x*y_block_count*z_block_count + y*z_block_count + z];
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
vector<t_building *> * DfMap::getBlockBuildingsVector(uint32_t x,uint32_t y,uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    Block * b = getBlock(x,y,z);
 | 
			
		||||
    if(b)
 | 
			
		||||
    {
 | 
			
		||||
        return &b->v_buildings;
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
vector<t_tree_desc *> *  DfMap::getBlockVegetationVector(uint32_t x,uint32_t y,uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    Block * b = getBlock(x,y,z);
 | 
			
		||||
    if(b)
 | 
			
		||||
    {
 | 
			
		||||
        return &b->v_trees;
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
t_tree_desc *DfMap::getTree (uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    for(uint32_t i = 0; i< v_trees.size();i++)
 | 
			
		||||
    {
 | 
			
		||||
        if(x == v_trees[i]->x
 | 
			
		||||
        && y == v_trees[i]->y
 | 
			
		||||
        && z == v_trees[i]->z)
 | 
			
		||||
        {
 | 
			
		||||
            return v_trees[i];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
t_building *DfMap::getBuilding (uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    for(uint32_t i = 0; i< v_buildings.size();i++)
 | 
			
		||||
    {
 | 
			
		||||
        if(x >= v_buildings[i]->x1 && x <= v_buildings[i]->x2
 | 
			
		||||
        && y >= v_buildings[i]->y1 && y <= v_buildings[i]->y2
 | 
			
		||||
        && z == v_buildings[i]->z)
 | 
			
		||||
        {
 | 
			
		||||
            return v_buildings[i];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Block * DfMap::allocBlock (uint32_t x,uint32_t y,uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    if(isValid())
 | 
			
		||||
    {
 | 
			
		||||
        if(block[x*y_block_count*z_block_count + y*z_block_count + z])
 | 
			
		||||
        {
 | 
			
		||||
            return block[x*y_block_count*z_block_count + y*z_block_count + z];
 | 
			
		||||
        }
 | 
			
		||||
        Block *b  = new Block;
 | 
			
		||||
        block[x*y_block_count*z_block_count + y*z_block_count + z] = b;
 | 
			
		||||
        blocks_allocated++;
 | 
			
		||||
        return b;
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void DfMap::updateCellCount()
 | 
			
		||||
{
 | 
			
		||||
    x_cell_count = x_block_count * BLOCK_SIZE;
 | 
			
		||||
    y_cell_count = y_block_count * BLOCK_SIZE;
 | 
			
		||||
    z_cell_count = z_block_count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void DfMap::applyGeoMatgloss(Block * b)
 | 
			
		||||
{
 | 
			
		||||
    // load layer matgloss
 | 
			
		||||
    for(int x_b = 0; x_b < BLOCK_SIZE; x_b++)
 | 
			
		||||
    {
 | 
			
		||||
        for(int y_b = 0; y_b < BLOCK_SIZE; y_b++)
 | 
			
		||||
        {
 | 
			
		||||
            int geolayer = b->designation[x_b][y_b].bits.geolayer_index;
 | 
			
		||||
            int biome = b->designation[x_b][y_b].bits.biome;
 | 
			
		||||
            b->material[x_b][y_b].type = Mat_Stone;
 | 
			
		||||
            b->material[x_b][y_b].index = v_geology[b->RegionOffsets[biome]][geolayer];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint8_t DfMap::getLiquidLevel(uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBounds);
 | 
			
		||||
 | 
			
		||||
    uint32_t x2, y2;
 | 
			
		||||
    convertToDfMapCoords(x, y, x, y, x2, y2);
 | 
			
		||||
    Block *b = getBlock(x,y,z);
 | 
			
		||||
    if(b != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return b->designation[x2][y2].bits.flow_size;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint16_t DfMap::getTileType(uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBounds);
 | 
			
		||||
 | 
			
		||||
    uint32_t x2, y2;
 | 
			
		||||
    convertToDfMapCoords(x, y, x, y, x2, y2);
 | 
			
		||||
    Block *b = getBlock(x,y,z);
 | 
			
		||||
    if(b != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return b->tile_type[x2][y2];
 | 
			
		||||
    }
 | 
			
		||||
    if(isTileSky(x,y,z,x2,y2))
 | 
			
		||||
    {
 | 
			
		||||
        return 32;
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint16_t DfMap::getTileType(uint32_t x, uint32_t y, uint32_t z, uint32_t blockX, uint32_t blockY)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBlockBounds);
 | 
			
		||||
    Block *b = getBlock(x,y,z);
 | 
			
		||||
    if(b != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return b->tile_type[blockX][blockY];
 | 
			
		||||
    }
 | 
			
		||||
    if(isTileSky(x,y,z,blockX,blockY))
 | 
			
		||||
    {
 | 
			
		||||
        return 32;
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint32_t DfMap::getDesignations(uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBounds);
 | 
			
		||||
    uint32_t x2, y2;
 | 
			
		||||
    convertToDfMapCoords(x, y, x, y, x2, y2);
 | 
			
		||||
    Block *b = getBlock(x,y,z);
 | 
			
		||||
    if(b != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return b->designation[x2][y2].whole;
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool DfMap::isBlockInitialized(uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    // because of the way DfMap is done, more than one check must be made.
 | 
			
		||||
    return getBlock(x,y,z) != NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint32_t DfMap::getOccupancies(uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBounds);
 | 
			
		||||
 | 
			
		||||
    uint32_t x2, y2;
 | 
			
		||||
    convertToDfMapCoords(x, y, x, y, x2, y2);
 | 
			
		||||
    Block *b = getBlock(x,y,z);
 | 
			
		||||
    if(b != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return b->occupancy[x2][y2].whole;
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void DfMap::getGeoRegion (uint32_t x, uint32_t y, uint32_t z, int32_t& geoX, int32_t& geoY)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBoundsXY);
 | 
			
		||||
    uint32_t x2, y2;
 | 
			
		||||
    convertToDfMapCoords(x, y, x, y, x2, y2);
 | 
			
		||||
    Block *b = getBlock(x,y,z);
 | 
			
		||||
    if(b != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        int biome = b->designation[x2][y2].bits.biome;
 | 
			
		||||
        int BiomeOffset = b->RegionOffsets[biome];
 | 
			
		||||
        int16_t X_biomeB = (regionX / 16) + (BiomeOffset % 3) - 1;
 | 
			
		||||
        int16_t Y_biomeB = (regionY / 16) + (BiomeOffset / 3) - 1;
 | 
			
		||||
        if(X_biomeB < 0) X_biomeB = 0;
 | 
			
		||||
        if(Y_biomeB < 0) Y_biomeB = 0;
 | 
			
		||||
        if( (uint32_t)X_biomeB >= worldSizeX)
 | 
			
		||||
        {
 | 
			
		||||
            X_biomeB = worldSizeX - 1;
 | 
			
		||||
        }
 | 
			
		||||
        if( (uint32_t)Y_biomeB >= worldSizeY)
 | 
			
		||||
        {
 | 
			
		||||
            Y_biomeB = worldSizeY - 1;
 | 
			
		||||
        }
 | 
			
		||||
        geoX = X_biomeB;
 | 
			
		||||
        geoY = Y_biomeB;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        geoX = regionX / 16;
 | 
			
		||||
        geoY = regionY / 16;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
t_matglossPair DfMap::getMaterialPair (uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBounds);
 | 
			
		||||
 | 
			
		||||
    uint32_t x2, y2;
 | 
			
		||||
    convertToDfMapCoords(x, y, x, y, x2, y2);
 | 
			
		||||
    Block *b = getBlock(x,y,z);
 | 
			
		||||
    if(b != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return b->material[x2][y2];
 | 
			
		||||
    }
 | 
			
		||||
    t_matglossPair fail = {-1,-1};
 | 
			
		||||
    return fail;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// this is what the vein structures say it is
 | 
			
		||||
string DfMap::getGeoMaterialString (uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBounds);
 | 
			
		||||
 | 
			
		||||
    uint32_t x2, y2;
 | 
			
		||||
    convertToDfMapCoords(x, y, x, y, x2, y2);
 | 
			
		||||
    Block *b = getBlock(x,y,z);
 | 
			
		||||
    if(b != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return getMaterialString(b->material[x2][y2].type, b->material[x2][y2].index);
 | 
			
		||||
    }
 | 
			
		||||
    string fallback = "UNKNOWN";
 | 
			
		||||
    return fallback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
string DfMap::getMaterialTypeString (uint32_t type)
 | 
			
		||||
{
 | 
			
		||||
    string ret = "";
 | 
			
		||||
    switch (type)
 | 
			
		||||
    {
 | 
			
		||||
        case 0:
 | 
			
		||||
        ret += "wood";
 | 
			
		||||
        break;
 | 
			
		||||
        case 1:
 | 
			
		||||
        ret += "stone/soil";
 | 
			
		||||
        break;
 | 
			
		||||
        case 2:
 | 
			
		||||
        ret += "metal";
 | 
			
		||||
        break;
 | 
			
		||||
        case 3:
 | 
			
		||||
        ret += "plant";
 | 
			
		||||
        break;
 | 
			
		||||
        case 10:
 | 
			
		||||
        ret += "leather";
 | 
			
		||||
        break;
 | 
			
		||||
        case 11:
 | 
			
		||||
        ret += "silk cloth";
 | 
			
		||||
        break;
 | 
			
		||||
        case 12:
 | 
			
		||||
        ret += "plant thread cloth";
 | 
			
		||||
        break;
 | 
			
		||||
        case 13: // green glass
 | 
			
		||||
        ret += "green glass";
 | 
			
		||||
        break;
 | 
			
		||||
        case 14: // clear glass
 | 
			
		||||
        ret += "clear glass";
 | 
			
		||||
        break;
 | 
			
		||||
        case 15: // crystal glass
 | 
			
		||||
        ret += "crystal glass";
 | 
			
		||||
        break;
 | 
			
		||||
        case 17:
 | 
			
		||||
        ret += "ice";
 | 
			
		||||
        break;
 | 
			
		||||
        case 18:
 | 
			
		||||
        ret += "charcoal";
 | 
			
		||||
        break;
 | 
			
		||||
        case 19:
 | 
			
		||||
        ret += "potash";
 | 
			
		||||
        break;
 | 
			
		||||
        case 20:
 | 
			
		||||
        ret += "ashes";
 | 
			
		||||
        break;
 | 
			
		||||
        case 21:
 | 
			
		||||
        ret += "pearlash";
 | 
			
		||||
        break;
 | 
			
		||||
        case 24:
 | 
			
		||||
        ret += "soap";
 | 
			
		||||
        break;
 | 
			
		||||
        default:
 | 
			
		||||
        ret += "unknown";
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
string DfMap::getMaterialString (uint32_t type, uint32_t index)
 | 
			
		||||
{
 | 
			
		||||
    if(index != 65535 && type >= 0 && type < NUM_MATGLOSS_TYPES)
 | 
			
		||||
    {
 | 
			
		||||
        if(index < v_matgloss[type].size())
 | 
			
		||||
        {
 | 
			
		||||
            return v_matgloss[type][index];
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            string fallback = "ERROR";
 | 
			
		||||
            return fallback;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    string fallback = "UNKNOWN";
 | 
			
		||||
    return fallback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint16_t DfMap::getNumMatGloss(uint16_t type)
 | 
			
		||||
{
 | 
			
		||||
    return v_matgloss[type].size();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
string DfMap::getBuildingTypeName(uint32_t index)
 | 
			
		||||
{
 | 
			
		||||
    if(index < v_buildingtypes.size())
 | 
			
		||||
    {
 | 
			
		||||
        return v_buildingtypes[index];
 | 
			
		||||
    }
 | 
			
		||||
    return string("error");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
string DfMap::getMatGlossString(uint16_t type,uint16_t index)
 | 
			
		||||
{
 | 
			
		||||
    if(index < v_matgloss[type].size())
 | 
			
		||||
    {
 | 
			
		||||
        return v_matgloss[type][index];
 | 
			
		||||
    }
 | 
			
		||||
    return string("error");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// matgloss part of the designation
 | 
			
		||||
unsigned int DfMap::getGeolayerIndex (uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBounds);
 | 
			
		||||
 | 
			
		||||
    uint32_t x2, y2;
 | 
			
		||||
    convertToDfMapCoords(x, y, x, y, x2, y2);
 | 
			
		||||
    Block *b = getBlock(x,y,z);
 | 
			
		||||
    if(b != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return b->designation[x2][y2].bits.geolayer_index;
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// matgloss part of the designation
 | 
			
		||||
unsigned int DfMap::getBiome (uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBounds);
 | 
			
		||||
 | 
			
		||||
    uint32_t x2, y2;
 | 
			
		||||
    convertToDfMapCoords(x, y, x, y, x2, y2);
 | 
			
		||||
    Block *b = getBlock(x,y,z);
 | 
			
		||||
    if(b != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return b->designation[x2][y2].bits.biome;
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool DfMap::isHidden (uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBounds);
 | 
			
		||||
    uint32_t x2, y2;
 | 
			
		||||
    convertToDfMapCoords(x, y, x, y, x2, y2);
 | 
			
		||||
    Block *b = getBlock(x,y,z);
 | 
			
		||||
    if(b != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return (b->designation[x2][y2].bits.hidden);
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool DfMap::isSubterranean (uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBounds);
 | 
			
		||||
    uint32_t x2, y2;
 | 
			
		||||
    convertToDfMapCoords(x, y, x, y, x2, y2);
 | 
			
		||||
    Block *b = getBlock(x,y,z);
 | 
			
		||||
    if(b != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return (b->designation[x2][y2].bits.subterranean);
 | 
			
		||||
    }
 | 
			
		||||
    if(isTileSky( x, y, z, x2, y2))
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// x,y,z - coords of block
 | 
			
		||||
// blockX,blockY - coords of tile inside block
 | 
			
		||||
bool DfMap::isTileSky(uint32_t x, uint32_t y, uint32_t z, uint32_t blockX, uint32_t blockY)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBounds);
 | 
			
		||||
    Block *b;
 | 
			
		||||
    // trace down through blocks until we hit an inited one or the base
 | 
			
		||||
    for (int i = z; i>= 0;i--)
 | 
			
		||||
    {
 | 
			
		||||
        b = getBlock(x,y,i);
 | 
			
		||||
        if(b)
 | 
			
		||||
        {
 | 
			
		||||
            // is the inited block open to the sky?
 | 
			
		||||
            return b->designation[blockX][blockY].bits.skyview;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // we hit base
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// is the sky above this tile visible?
 | 
			
		||||
bool DfMap::isSkyView (uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBounds);
 | 
			
		||||
    uint32_t x2, y2;
 | 
			
		||||
    convertToDfMapCoords(x, y, x, y, x2, y2);
 | 
			
		||||
    Block *b = getBlock(x,y,z);
 | 
			
		||||
    if(b != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return (b->designation[x2][y2].bits.skyview);
 | 
			
		||||
    }
 | 
			
		||||
    if(isTileSky(x,y,z,x2,y2))
 | 
			
		||||
    {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// is there light in this tile?
 | 
			
		||||
bool DfMap::isSunLit (uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBounds);
 | 
			
		||||
    uint32_t x2, y2;
 | 
			
		||||
    convertToDfMapCoords(x, y, x, y, x2, y2);
 | 
			
		||||
    Block *b = getBlock(x,y,z);
 | 
			
		||||
    if(b != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return (b->designation[x2][y2].bits.light);
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool DfMap::isMagma (uint32_t x, uint32_t y, uint32_t z)
 | 
			
		||||
{
 | 
			
		||||
    assert(CheckBounds);
 | 
			
		||||
    uint32_t x2, y2;
 | 
			
		||||
    convertToDfMapCoords(x, y, x, y, x2, y2);
 | 
			
		||||
    Block *b = getBlock(x,y,z);
 | 
			
		||||
    if(b != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return (b->designation[x2][y2].bits.liquid_type);
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,204 @@
 | 
			
		||||
/*
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef DFMAP_H_INCLUDED
 | 
			
		||||
#define DFMAP_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#define BLOCK_SIZE 16
 | 
			
		||||
 | 
			
		||||
class DfMapHeader;
 | 
			
		||||
 | 
			
		||||
class Block
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    // where does the Block come from?
 | 
			
		||||
    uint32_t origin;
 | 
			
		||||
    // generic tile type. determines how the tile behaves ingame
 | 
			
		||||
    uint16_t tile_type[BLOCK_SIZE][BLOCK_SIZE];
 | 
			
		||||
    t_designation designation[BLOCK_SIZE][BLOCK_SIZE];
 | 
			
		||||
    t_occupancy occupancy[BLOCK_SIZE][BLOCK_SIZE];
 | 
			
		||||
    // veins
 | 
			
		||||
    vector <t_vein> veins;
 | 
			
		||||
    t_matglossPair material[BLOCK_SIZE][BLOCK_SIZE];
 | 
			
		||||
    vector<t_building*> v_buildings;
 | 
			
		||||
    vector<t_tree_desc*> v_trees;
 | 
			
		||||
    void collapseVeins();
 | 
			
		||||
    /**
 | 
			
		||||
    // region offset modifiers... what a hack.
 | 
			
		||||
    // here we have double indexed offset into regions.
 | 
			
		||||
    // once inside t_designation, pointing into this, second time from here as a index modifier into region array (2d)
 | 
			
		||||
    // disassembled code where it's used follows. biome is biome from t_designation
 | 
			
		||||
    biome_stuffs = *(_BYTE *)((char)biome + offset_Block + 0x1D84);
 | 
			
		||||
    biome_stuffs_mod3 = biome_stuffs % 3;
 | 
			
		||||
    biome_stuffs_div3 = biome_stuffs / 3;
 | 
			
		||||
    biome_stuffs_mod3_ = biome_stuffs_mod3;
 | 
			
		||||
    if ( !biome_stuffs_mod3_ )
 | 
			
		||||
      --*(_WORD *)X_stuff;
 | 
			
		||||
    if ( biome_stuffs_mod3_ == 2 )
 | 
			
		||||
      ++*(_WORD *)X_stuff;
 | 
			
		||||
    if ( !biome_stuffs_div3 )
 | 
			
		||||
      --*(_WORD *)Y_stuff_;
 | 
			
		||||
    if ( biome_stuffs_div3 == 2 )
 | 
			
		||||
      ++*(_WORD *)Y_stuff_;
 | 
			
		||||
    */
 | 
			
		||||
    uint8_t RegionOffsets[16];// idk if the length is right here
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * This class can load and save DF maps
 | 
			
		||||
 */
 | 
			
		||||
class DfMap
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
    // allow extractor direct access to our data, avoid call lag and lots of self-serving methods
 | 
			
		||||
    friend class Extractor;
 | 
			
		||||
 | 
			
		||||
    Block **block;
 | 
			
		||||
    uint32_t blocks_allocated;
 | 
			
		||||
    bool valid;
 | 
			
		||||
 | 
			
		||||
    // converts the (x,y,z) cell coords to internal coords
 | 
			
		||||
    // out_y, out_x - block coords
 | 
			
		||||
    // out_y2, out_x2 - cell coords in that block
 | 
			
		||||
    inline void convertToDfMapCoords(uint32_t x, uint32_t y, uint32_t &out_x, uint32_t &out_y, uint32_t &out_x2, uint32_t &out_y2)
 | 
			
		||||
    {
 | 
			
		||||
        out_x = x / BLOCK_SIZE;
 | 
			
		||||
        out_x2 = x % BLOCK_SIZE;
 | 
			
		||||
        out_y = y / BLOCK_SIZE;
 | 
			
		||||
        out_y2 = y % BLOCK_SIZE;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    void allocBlockArray(uint32_t x,uint32_t y, uint32_t z);
 | 
			
		||||
    void updateCellCount();
 | 
			
		||||
 | 
			
		||||
    bool loadVersion1(FILE * Decompressed,DfMapHeader & h);
 | 
			
		||||
    bool writeVersion1(FILE * SaveFile);
 | 
			
		||||
 | 
			
		||||
    bool loadMatgloss2(FILE * Decompressed);
 | 
			
		||||
    bool loadBlocks2(FILE * Decompressed,DfMapHeader & h);
 | 
			
		||||
    bool loadRegion2(FILE * Decompressed);
 | 
			
		||||
    bool loadVersion2(FILE * Decompressed,DfMapHeader & h);
 | 
			
		||||
 | 
			
		||||
    void writeMatgloss2(FILE * SaveFile);
 | 
			
		||||
    void writeBlocks2(FILE * SaveFile);
 | 
			
		||||
    void writeRegion2(FILE * SaveFile);
 | 
			
		||||
    bool writeVersion2(FILE * SaveFile);
 | 
			
		||||
 | 
			
		||||
    uint32_t regionX;
 | 
			
		||||
    uint32_t regionY;
 | 
			
		||||
    uint32_t regionZ;
 | 
			
		||||
 | 
			
		||||
    ///FIXME: these belong to some world structure
 | 
			
		||||
    uint32_t worldSizeX;
 | 
			
		||||
    uint32_t worldSizeY;
 | 
			
		||||
 | 
			
		||||
    vector<uint16_t> v_geology[eBiomeCount];
 | 
			
		||||
    vector<string> v_matgloss[NUM_MATGLOSS_TYPES];
 | 
			
		||||
    vector<string> v_buildingtypes;
 | 
			
		||||
    vector<t_construction> v_constructions;
 | 
			
		||||
    vector<t_building*> v_buildings;
 | 
			
		||||
    vector<t_tree_desc*> v_trees;
 | 
			
		||||
    unsigned x_block_count, y_block_count, z_block_count; // block count
 | 
			
		||||
    unsigned x_cell_count, y_cell_count, z_cell_count;    // cell count
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    DfMap();
 | 
			
		||||
    DfMap(uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
    DfMap(string file_name);
 | 
			
		||||
    ~DfMap();
 | 
			
		||||
 | 
			
		||||
    /// TODO: rework matgloss
 | 
			
		||||
    void applyGeoMatgloss(Block * b);
 | 
			
		||||
    // accessing vectors of materials
 | 
			
		||||
    uint16_t getNumMatGloss(uint16_t type);
 | 
			
		||||
    string getMaterialTypeString (uint32_t type);
 | 
			
		||||
    string getMatGlossString(uint16_t type, uint16_t index);
 | 
			
		||||
    // accessing vectors of building types
 | 
			
		||||
    uint32_t getNumBuildingTypes();
 | 
			
		||||
    string getBuildingTypeName(uint32_t index);
 | 
			
		||||
 | 
			
		||||
    bool isValid();
 | 
			
		||||
    bool load(string FilePath);
 | 
			
		||||
    bool write(string FilePath);
 | 
			
		||||
    void clear();
 | 
			
		||||
 | 
			
		||||
    Block* getBlock(uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
    Block* allocBlock(uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
    bool   deallocBlock(uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
 | 
			
		||||
    vector<t_building *> * getBlockBuildingsVector(uint32_t x,uint32_t y,uint32_t z);
 | 
			
		||||
    vector<t_tree_desc *> * getBlockVegetationVector(uint32_t x,uint32_t y,uint32_t z);
 | 
			
		||||
 | 
			
		||||
    inline unsigned int getXBlocks()        { return x_block_count; }
 | 
			
		||||
    inline unsigned int getYBlocks()        { return y_block_count; }
 | 
			
		||||
    inline unsigned int getZBlocks()        { return z_block_count; }
 | 
			
		||||
 | 
			
		||||
    bool isTileSky(uint32_t x, uint32_t y, uint32_t z, uint32_t blockX, uint32_t blockY);
 | 
			
		||||
    uint16_t getTileType(uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
    uint16_t getTileType(uint32_t x, uint32_t y, uint32_t z, uint32_t blockX, uint32_t blockY);
 | 
			
		||||
 | 
			
		||||
    uint32_t getDesignations(uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
    uint32_t getOccupancies(uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
 | 
			
		||||
    // get tile material
 | 
			
		||||
    t_matglossPair getMaterialPair (uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
    string getGeoMaterialString (uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
    string getMaterialString (uint32_t type, uint32_t index);
 | 
			
		||||
 | 
			
		||||
    // get coords of region used for materials
 | 
			
		||||
    void getGeoRegion (uint32_t x, uint32_t y, uint32_t z, int32_t& geoX, int32_t& geoY);
 | 
			
		||||
 | 
			
		||||
    // matgloss part of the designation
 | 
			
		||||
    uint32_t getGeolayerIndex (uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
 | 
			
		||||
    void getRegionCoords (uint32_t &x,uint32_t &y,uint32_t &z);
 | 
			
		||||
    void setRegionCoords (uint32_t x,uint32_t y,uint32_t z);
 | 
			
		||||
 | 
			
		||||
    // what kind of building is here?
 | 
			
		||||
    //uint16_t getBuilding (uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
    t_building *getBuilding (uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
    t_tree_desc *getTree (uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
 | 
			
		||||
    unsigned int getBiome (uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
 | 
			
		||||
    int picktexture(int);
 | 
			
		||||
/*
 | 
			
		||||
    bool isOpenTerrain(int);
 | 
			
		||||
    bool isStairTerrain(int);
 | 
			
		||||
    bool isRampTerrain(int);
 | 
			
		||||
    bool isFloorTerrain(int);
 | 
			
		||||
    bool isWallTerrain(int);
 | 
			
		||||
*/
 | 
			
		||||
    bool isBlockInitialized(uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
 | 
			
		||||
    bool isHidden (uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
    bool isSubterranean (uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
    bool isSkyView (uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
    bool isSunLit (uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
    bool isMagma (uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
 | 
			
		||||
    uint8_t getLiquidLevel(uint32_t x, uint32_t y, uint32_t z);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // DFMAP_H_INCLUDED
 | 
			
		||||
@ -0,0 +1,41 @@
 | 
			
		||||
/*
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef DF_MAP_HEADER_H
 | 
			
		||||
#define DF_MAP_HEADER_H
 | 
			
		||||
 | 
			
		||||
static const char dmh_id[] = "!!URIST!!";
 | 
			
		||||
static const uint8_t dmh_ver = 1U;
 | 
			
		||||
 | 
			
		||||
// a header for save files
 | 
			
		||||
struct DfMapHeader
 | 
			
		||||
{
 | 
			
		||||
    char identifier[10]; // !!URIST!!
 | 
			
		||||
    uint8_t version; // DfMap/Header version; current: 1
 | 
			
		||||
    uint32_t reserved; // reserved 4 bytes
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // DF_MAP_HEADER_H
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,433 @@
 | 
			
		||||
/*
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// Extractor
 | 
			
		||||
#include "DFCommon.h"
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
#include "Extract.h"
 | 
			
		||||
#include "DFDataModel.h"
 | 
			
		||||
#include "DFMemInfo.h"
 | 
			
		||||
 | 
			
		||||
Extractor::Extractor()
 | 
			
		||||
{
 | 
			
		||||
    df_map = NULL; // important, null pointer means we don't have a map loaded
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Extractor::~Extractor()
 | 
			
		||||
{
 | 
			
		||||
    if(df_map !=NULL )
 | 
			
		||||
    {
 | 
			
		||||
        delete df_map;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool Extractor::dumpMemory( string path_to_xml)
 | 
			
		||||
{
 | 
			
		||||
    // create process manager, get first process
 | 
			
		||||
    ProcessManager pm(path_to_xml);
 | 
			
		||||
    if(!pm.findProcessess())
 | 
			
		||||
    {
 | 
			
		||||
        fprintf(stderr,"Can't find any suitable DF process\n");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    // attach to process
 | 
			
		||||
    printf("Attempting to Attach Process\n");
 | 
			
		||||
    ///FIXME: this won't do.
 | 
			
		||||
    Process * p = pm[0];
 | 
			
		||||
    DataModel * dm = p->getDataModel();
 | 
			
		||||
    if(!p->attach())
 | 
			
		||||
    {
 | 
			
		||||
        printf("Could not Attach Process, Aborting\n");
 | 
			
		||||
        return false; // couldn't attach to process, no go
 | 
			
		||||
    }
 | 
			
		||||
    printf("Process succesfully Attached\n");
 | 
			
		||||
    memory_info* offset_descriptor = p->getDescriptor();
 | 
			
		||||
 | 
			
		||||
    uint32_t map_loc, // location of the X array
 | 
			
		||||
            temp_loc, // block location
 | 
			
		||||
            temp_locx, // iterator for the X array
 | 
			
		||||
            temp_locy, // iterator for the Y array
 | 
			
		||||
            temp_locz; // iterator for the Z array
 | 
			
		||||
    unsigned blocks_read = 0U;
 | 
			
		||||
 | 
			
		||||
    // Read Map Data Blocks
 | 
			
		||||
    int map_offset = offset_descriptor->getAddress("map_data");;
 | 
			
		||||
    int x_count_offset = offset_descriptor->getAddress("x_count");
 | 
			
		||||
    int y_count_offset = offset_descriptor->getAddress("y_count");
 | 
			
		||||
    int z_count_offset = offset_descriptor->getAddress("z_count");
 | 
			
		||||
    int tile_type_offset = offset_descriptor->getOffset("type");
 | 
			
		||||
    int designation_offset = offset_descriptor->getOffset("designation");
 | 
			
		||||
    int occupancy_offset = offset_descriptor->getOffset("occupancy");
 | 
			
		||||
    int biome_stuffs = offset_descriptor->getOffset("biome_stuffs");
 | 
			
		||||
 | 
			
		||||
    // layers
 | 
			
		||||
    int region_x_offset = offset_descriptor->getAddress("region_x");
 | 
			
		||||
    int region_y_offset = offset_descriptor->getAddress("region_y");
 | 
			
		||||
    int region_z_offset =  offset_descriptor->getAddress("region_z");
 | 
			
		||||
    int world_offset =  offset_descriptor->getAddress("world");
 | 
			
		||||
    int world_regions_offset =  offset_descriptor->getOffset("w_regions_arr");
 | 
			
		||||
    int region_size =  offset_descriptor->getHexValue("region_size");
 | 
			
		||||
    int region_geo_index_offset =  offset_descriptor->getOffset("region_geo_index_off");
 | 
			
		||||
    int world_geoblocks_offset =  offset_descriptor->getOffset("w_geoblocks");
 | 
			
		||||
    int world_size_x = offset_descriptor->getOffset("world_size_x");
 | 
			
		||||
    int world_size_y = offset_descriptor->getOffset("world_size_y");
 | 
			
		||||
    int geolayer_geoblock_offset = offset_descriptor->getOffset("geolayer_geoblock_offset");
 | 
			
		||||
    // veins
 | 
			
		||||
    int veinvector = offset_descriptor->getOffset("v_vein");
 | 
			
		||||
    int veinsize = offset_descriptor->getHexValue("v_vein_size");
 | 
			
		||||
 | 
			
		||||
    int vegetation = offset_descriptor->getAddress("vegetation");
 | 
			
		||||
    int tree_desc_offset = offset_descriptor->getOffset("tree_desc_offset");
 | 
			
		||||
    // constructions
 | 
			
		||||
    int constructions = offset_descriptor->getAddress("constructions");
 | 
			
		||||
    // buildings
 | 
			
		||||
    int buildings = offset_descriptor->getAddress("buildings");
 | 
			
		||||
    /// TODO: what about building shape and orientation?
 | 
			
		||||
 | 
			
		||||
    // matgloss
 | 
			
		||||
    int matgloss_address = offset_descriptor->getAddress("matgloss");
 | 
			
		||||
    int matgloss_skip = offset_descriptor->getHexValue("matgloss_skip");
 | 
			
		||||
 | 
			
		||||
    bool have_geology = false;
 | 
			
		||||
 | 
			
		||||
    printf("Map offset: 0x%.8X\n", map_offset);
 | 
			
		||||
    map_loc = MreadDWord(map_offset);
 | 
			
		||||
 | 
			
		||||
    if (!map_loc)
 | 
			
		||||
    {
 | 
			
		||||
        printf("Could not find DF map information in memory, Aborting\n");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    printf("Map data Found at: 0x%.8X\n", map_loc);
 | 
			
		||||
 | 
			
		||||
    if(df_map != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        delete df_map;
 | 
			
		||||
    }
 | 
			
		||||
    df_map = new DfMap(MreadDWord(x_count_offset),MreadDWord(y_count_offset),MreadByte(z_count_offset));
 | 
			
		||||
 | 
			
		||||
    // read matgloss data from df if we can
 | 
			
		||||
    RawType matglossRawMapping[] = {Mat_Wood, Mat_Stone, Mat_Metal, Mat_Plant};
 | 
			
		||||
    if(matgloss_address && matgloss_skip)
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t addr = matgloss_address;
 | 
			
		||||
        uint32_t counter = Mat_Wood;
 | 
			
		||||
 | 
			
		||||
        for(; counter < NUM_MATGLOSS_TYPES; addr += matgloss_skip, counter++)
 | 
			
		||||
        {
 | 
			
		||||
            // get vector of matgloss pointers
 | 
			
		||||
            DfVector p_matgloss = dm->readVector(addr, 4);
 | 
			
		||||
 | 
			
		||||
            // iterate over it
 | 
			
		||||
            for (uint32_t i = 0; i< p_matgloss.getSize();i++)
 | 
			
		||||
            {
 | 
			
		||||
                uint32_t temp;
 | 
			
		||||
                string tmpstr;
 | 
			
		||||
 | 
			
		||||
                // read the matgloss pointer from the vector into temp
 | 
			
		||||
                p_matgloss.read((uint32_t)i,(uint8_t *)&temp);
 | 
			
		||||
 | 
			
		||||
                // read the string pointed at by temp
 | 
			
		||||
                tmpstr = dm->readSTLString(temp);
 | 
			
		||||
 | 
			
		||||
                // store it in the block
 | 
			
		||||
                df_map->v_matgloss[matglossRawMapping[counter]].push_back(tmpstr);
 | 
			
		||||
                printf("%d = %s\n",i,tmpstr.c_str());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(region_x_offset && region_y_offset && region_z_offset)
 | 
			
		||||
    {
 | 
			
		||||
        // we have offsets for region coordinates, get them.
 | 
			
		||||
        df_map->setRegionCoords(MreadDWord(region_x_offset),MreadDWord(region_y_offset),MreadDWord(region_z_offset));
 | 
			
		||||
 | 
			
		||||
        // extract layer geology data. we need all these to do that
 | 
			
		||||
        if(world_size_x && world_size_y && world_offset && world_regions_offset && world_geoblocks_offset && region_size && region_geo_index_offset && geolayer_geoblock_offset)
 | 
			
		||||
        {
 | 
			
		||||
            // get world size
 | 
			
		||||
            int worldSizeX = MreadWord(world_offset + world_size_x);
 | 
			
		||||
            int worldSizeY = MreadWord(world_offset + world_size_y);
 | 
			
		||||
            df_map->worldSizeX = worldSizeX;
 | 
			
		||||
            df_map->worldSizeY = worldSizeY;
 | 
			
		||||
            printf("World size. X=%d Y=%d\n",worldSizeX,worldSizeY);
 | 
			
		||||
 | 
			
		||||
            // get pointer to first part of 2d array of regions
 | 
			
		||||
            uint32_t regions = MreadDWord(world_offset + world_regions_offset);
 | 
			
		||||
            printf("regions. Offset=%d\n",regions);
 | 
			
		||||
 | 
			
		||||
            // read the 9 surrounding regions
 | 
			
		||||
            DfVector geoblocks = dm->readVector(world_offset + world_geoblocks_offset,4);
 | 
			
		||||
 | 
			
		||||
            // iterate over surrounding biomes. make sure we don't fall off the world
 | 
			
		||||
            for(int i = eNorthWest; i< eBiomeCount; i++)
 | 
			
		||||
            {
 | 
			
		||||
                // check bounds, fix them if needed
 | 
			
		||||
                int bioRX = df_map->regionX / 16 + (i%3) - 1;
 | 
			
		||||
                if( bioRX < 0) bioRX = 0;
 | 
			
		||||
                if( bioRX >= worldSizeX) bioRX = worldSizeX - 1;
 | 
			
		||||
                int bioRY = df_map->regionY / 16 + (i/3) - 1;
 | 
			
		||||
                if( bioRY < 0) bioRY = 0;
 | 
			
		||||
                if( bioRY >= worldSizeY) bioRY = worldSizeY - 1;
 | 
			
		||||
 | 
			
		||||
                /// TODO: encapsulate access to multidimensional arrays.
 | 
			
		||||
                // load region stuff here
 | 
			
		||||
                uint32_t geoX = MreadDWord(regions + bioRX*4);// get pointer to column of regions
 | 
			
		||||
 | 
			
		||||
                // geoX = base
 | 
			
		||||
                // bioRY = index
 | 
			
		||||
                // region_size = size of array objects
 | 
			
		||||
                // region_geo_index_off = offset into the array object
 | 
			
		||||
                uint16_t geoindex = MreadWord(geoX + bioRY*region_size + region_geo_index_offset);
 | 
			
		||||
                uint32_t geoblock_off;
 | 
			
		||||
 | 
			
		||||
                // get the geoblock from the geoblock vector using the geoindex
 | 
			
		||||
                geoblocks.read(geoindex,(uint8_t *) &geoblock_off);
 | 
			
		||||
 | 
			
		||||
                // get the layer pointer vector :D
 | 
			
		||||
                DfVector geolayers = dm->readVector(geoblock_off + geolayer_geoblock_offset , 4); // let's hope
 | 
			
		||||
 | 
			
		||||
                // make sure we don't load crap
 | 
			
		||||
                assert(geolayers.getSize() > 0 && geolayers.getSize() <= 16);
 | 
			
		||||
                for(uint32_t j = 0;j< geolayers.getSize();j++)
 | 
			
		||||
                {
 | 
			
		||||
                    int geol_offset;
 | 
			
		||||
 | 
			
		||||
                    // read pointer to a layer
 | 
			
		||||
                    geolayers.read(j, (uint8_t *) & geol_offset);
 | 
			
		||||
 | 
			
		||||
                    // read word at pointer + 2, store in our geology vectors
 | 
			
		||||
                    df_map->v_geology[i].push_back(MreadWord(geol_offset + 2));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            have_geology = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        // crap, can't get the real layer materials
 | 
			
		||||
        df_map->setRegionCoords(0,0,0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //read the memory from the map blocks
 | 
			
		||||
    for(uint32_t x = 0; x < df_map->x_block_count; x++)
 | 
			
		||||
    {
 | 
			
		||||
        temp_locx = map_loc + ( 4 * x );
 | 
			
		||||
        temp_locy = MreadDWord(temp_locx);
 | 
			
		||||
        for(uint32_t y = 0; y < df_map->y_block_count; y++)
 | 
			
		||||
        {
 | 
			
		||||
            temp_locz = MreadDWord(temp_locy);
 | 
			
		||||
            temp_locy += 4;
 | 
			
		||||
            for(uint32_t z = 0; z < df_map->z_block_count; z++)
 | 
			
		||||
            {
 | 
			
		||||
                temp_loc = MreadDWord(temp_locz);
 | 
			
		||||
                temp_locz += 4;
 | 
			
		||||
                if (temp_loc)
 | 
			
		||||
                {
 | 
			
		||||
                    Block * b = df_map->allocBlock(x,y,z);
 | 
			
		||||
                    b->origin = temp_loc; // save place of block in DF's memory for later
 | 
			
		||||
 | 
			
		||||
                    Mread(
 | 
			
		||||
                    /*Uint32 offset*/ temp_loc + tile_type_offset,
 | 
			
		||||
                    /*Uint32 size*/   sizeof(uint16_t)*BLOCK_SIZE*BLOCK_SIZE,
 | 
			
		||||
                    /*void *target*/  (uint8_t *)&b->tile_type
 | 
			
		||||
                           );
 | 
			
		||||
                    Mread(
 | 
			
		||||
                    /*Uint32 offset*/ temp_loc + designation_offset,
 | 
			
		||||
                    /*Uint32 size*/   sizeof(uint32_t)*BLOCK_SIZE*BLOCK_SIZE,
 | 
			
		||||
                    /*void *target*/  (uint8_t *)&b->designation
 | 
			
		||||
                           );
 | 
			
		||||
                    Mread(
 | 
			
		||||
                    /*Uint32 offset*/ temp_loc + occupancy_offset,
 | 
			
		||||
                    /*Uint32 size*/   sizeof(uint32_t)*BLOCK_SIZE*BLOCK_SIZE,
 | 
			
		||||
                    /*void *target*/  (uint8_t *)&b->occupancy
 | 
			
		||||
                           );
 | 
			
		||||
 | 
			
		||||
                    // set all materials to -1.
 | 
			
		||||
                    memset(b->material, -1, sizeof(int16_t) * 256);
 | 
			
		||||
                    if(biome_stuffs) // we got biome stuffs! we can try loading matgloss from here
 | 
			
		||||
                    {
 | 
			
		||||
                        Mread(
 | 
			
		||||
                        /*Uint32 offset*/ temp_loc + biome_stuffs,
 | 
			
		||||
                        /*Uint32 size*/   sizeof(uint8_t)*16,
 | 
			
		||||
                        /*void *target*/  (uint8_t *)&b->RegionOffsets
 | 
			
		||||
                               );
 | 
			
		||||
                        // if we have geology, we can use the geolayers to determine materials
 | 
			
		||||
                        if(have_geology)
 | 
			
		||||
                        {
 | 
			
		||||
                            df_map->applyGeoMatgloss(b);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        // can't load offsets, substitute local biome everywhere
 | 
			
		||||
                        memset(b->RegionOffsets,eHere,sizeof(b->RegionOffsets));
 | 
			
		||||
                    }
 | 
			
		||||
                    // load veins from the game
 | 
			
		||||
                    if(veinvector && veinsize)
 | 
			
		||||
                    {
 | 
			
		||||
                        assert(sizeof(t_vein) == veinsize);
 | 
			
		||||
                        // veins are stored as a vector of pointers to veins .. at least in df 40d11 on linux
 | 
			
		||||
                        /*pointer is 4 bytes! we work with a 32bit program here, no matter what architecture we compile khazad for*/
 | 
			
		||||
                        DfVector p_veins = dm->readVector(temp_loc + veinvector, 4);
 | 
			
		||||
                        // read all veins
 | 
			
		||||
                        for (uint32_t i = 0; i< p_veins.getSize();i++)
 | 
			
		||||
                        {
 | 
			
		||||
                            t_vein v;
 | 
			
		||||
                            uint32_t temp;
 | 
			
		||||
                            // read the vein pointer from the vector
 | 
			
		||||
                            p_veins.read((uint32_t)i,(uint8_t *)&temp);
 | 
			
		||||
                            // read the vein data (dereference pointer)
 | 
			
		||||
                            Mread(temp, veinsize, (uint8_t *)&v);
 | 
			
		||||
                            // store it in the block
 | 
			
		||||
                            b->veins.push_back(v);
 | 
			
		||||
                        }
 | 
			
		||||
                        b->collapseVeins(); // collapse *our* vein vector into vein matgloss data
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // read constructions, apply immediately.
 | 
			
		||||
    if(constructions)
 | 
			
		||||
    {
 | 
			
		||||
        // read the constructions vector
 | 
			
		||||
        DfVector p_cons = dm->readVector(constructions,4);
 | 
			
		||||
        // iterate
 | 
			
		||||
        for (uint32_t i = 0; i< p_cons.getSize();i++)
 | 
			
		||||
        {
 | 
			
		||||
            uint32_t temp;
 | 
			
		||||
            t_construction c;
 | 
			
		||||
            t_construction_df40d c_40d;
 | 
			
		||||
            // read pointer from vector at position
 | 
			
		||||
            p_cons.read((uint32_t)i,(uint8_t *)&temp);
 | 
			
		||||
            //read construction from memory
 | 
			
		||||
            Mread(temp, sizeof(t_construction_df40d), (uint8_t *)&c_40d);
 | 
			
		||||
            // stupid apply. this will probably be removed later
 | 
			
		||||
            Block * b = df_map->getBlock(c_40d.x/16,c_40d.y/16,c_40d.z);
 | 
			
		||||
            b->material[c_40d.x%16][c_40d.y%16] = c_40d.material;
 | 
			
		||||
            //b->material[c_40d.x%16][c_40d.y%16].index = c_40d.material.index;
 | 
			
		||||
            // transform
 | 
			
		||||
            c.x = c_40d.x;
 | 
			
		||||
            c.y = c_40d.y;
 | 
			
		||||
            c.z = c_40d.z;
 | 
			
		||||
            c.material = c_40d.material;
 | 
			
		||||
            // store for save/load
 | 
			
		||||
            df_map->v_constructions.push_back(c);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if(buildings)
 | 
			
		||||
    {
 | 
			
		||||
        // fill the building type vector first
 | 
			
		||||
        offset_descriptor->copyBuildings(df_map->v_buildingtypes);
 | 
			
		||||
        DfVector p_bld = dm->readVector(buildings,4);
 | 
			
		||||
        for (uint32_t i = 0; i< p_bld.getSize();i++)
 | 
			
		||||
        {
 | 
			
		||||
            uint32_t temp;
 | 
			
		||||
            t_building * bld = new t_building;
 | 
			
		||||
            t_building_df40d bld_40d;
 | 
			
		||||
            // read pointer from vector at position
 | 
			
		||||
            p_bld.read((uint32_t)i,(uint8_t *)&temp);
 | 
			
		||||
            //read construction from memory
 | 
			
		||||
            Mread(temp, sizeof(t_building_df40d), (uint8_t *)&bld_40d);
 | 
			
		||||
            // transform
 | 
			
		||||
            int32_t type = -1;
 | 
			
		||||
            offset_descriptor->resolveClassId(temp, type);
 | 
			
		||||
            bld->vtable = bld_40d.vtable;
 | 
			
		||||
            bld->type = type;
 | 
			
		||||
            bld->x1 = bld_40d.x1;
 | 
			
		||||
            bld->x2 = bld_40d.x2;
 | 
			
		||||
            bld->y1 = bld_40d.y1;
 | 
			
		||||
            bld->y2 = bld_40d.y2;
 | 
			
		||||
            bld->z = bld_40d.z;
 | 
			
		||||
            bld->material = bld_40d.material;
 | 
			
		||||
            // store for save/load. will need more processing.
 | 
			
		||||
            df_map->v_buildings.push_back(bld);
 | 
			
		||||
            ///FIXME: delete created building structs
 | 
			
		||||
            // save buildings in a block for later display
 | 
			
		||||
            Block * b = df_map->getBlock(bld->x1/16,bld->y1/16,bld->z);
 | 
			
		||||
            b->v_buildings.push_back(bld);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if(vegetation && tree_desc_offset)
 | 
			
		||||
    {
 | 
			
		||||
        DfVector p_tree = dm->readVector(vegetation,4);
 | 
			
		||||
        for (uint32_t i = 0; i< p_tree.getSize();i++)
 | 
			
		||||
        {
 | 
			
		||||
            uint32_t temp;
 | 
			
		||||
            t_tree_desc * tree = new t_tree_desc;
 | 
			
		||||
            // read pointer from vector at position
 | 
			
		||||
            p_tree.read((uint32_t)i,(uint8_t *)&temp);
 | 
			
		||||
            //read construction from memory
 | 
			
		||||
            Mread(temp + tree_desc_offset, sizeof(t_tree_desc), (uint8_t *)tree);
 | 
			
		||||
            // fix bad stuff
 | 
			
		||||
            if(tree->material.type == 2) tree->material.type = 3;
 | 
			
		||||
            // store for save/load. will need more processing.
 | 
			
		||||
            df_map->v_trees.push_back(tree);
 | 
			
		||||
            // save buildings in a block for later display
 | 
			
		||||
            Block * b = df_map->getBlock(tree->x/16,tree->y/16,tree->z);
 | 
			
		||||
            b->v_trees.push_back(tree);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    printf("Blocks read into memory: %d\n", blocks_read);
 | 
			
		||||
    p->detach();
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
// wrappers!
 | 
			
		||||
bool Extractor::loadMap(string FileName)
 | 
			
		||||
{
 | 
			
		||||
    if(df_map == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        df_map = new DfMap(FileName);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        df_map->load(FileName);
 | 
			
		||||
    }
 | 
			
		||||
    return df_map->isValid();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Extractor::writeMap(string FileName)
 | 
			
		||||
{
 | 
			
		||||
    if(df_map == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    return df_map->write(FileName);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Extractor::isMapLoaded()
 | 
			
		||||
{
 | 
			
		||||
    if(df_map != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        if(df_map->isValid())
 | 
			
		||||
        {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,51 @@
 | 
			
		||||
/*
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/* Memory research
 | 
			
		||||
    http://dwarffortresswiki.net/index.php/User:Rick/memory.ini#A_table_of_available_settings
 | 
			
		||||
    http://dwarffortresswiki.net/index.php/User:Rick/Memory_research#Tile_Block
 | 
			
		||||
    http://dwarffortresswiki.net/index.php/User:AzureLightning/Memory_research
 | 
			
		||||
    http://dwarffortresswiki.net/index.php/User:Iluxan/Memory_research
 | 
			
		||||
 */
 | 
			
		||||
#ifndef EXTRACT_HEADER
 | 
			
		||||
#define EXTRACT_HEADER
 | 
			
		||||
 | 
			
		||||
class DfMap;
 | 
			
		||||
 | 
			
		||||
class Extractor
 | 
			
		||||
{
 | 
			
		||||
protected:
 | 
			
		||||
    DfMap *df_map;   // DF extracted map structure
 | 
			
		||||
    
 | 
			
		||||
public:
 | 
			
		||||
    bool Init();
 | 
			
		||||
    Extractor();
 | 
			
		||||
    ~Extractor();
 | 
			
		||||
    bool loadMap(string FileName);
 | 
			
		||||
    bool writeMap(string FileName);
 | 
			
		||||
    bool isMapLoaded();
 | 
			
		||||
    DfMap *getMap() {return df_map;};
 | 
			
		||||
    bool dumpMemory( string path_to_xml);
 | 
			
		||||
};
 | 
			
		||||
#endif // EXTRACT_HEADER
 | 
			
		||||
@ -0,0 +1,188 @@
 | 
			
		||||
/*
 | 
			
		||||
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 "DFCommon.h"
 | 
			
		||||
#include "DfMap.h"
 | 
			
		||||
#include "DfMapHeader.h"
 | 
			
		||||
#include "ZlibHelper.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool DfMap::write(string FilePath)
 | 
			
		||||
{
 | 
			
		||||
    FILE *SaveFile;
 | 
			
		||||
    SaveFile = fopen(FilePath.c_str(),"wb");
 | 
			
		||||
    DfMapHeader df_map_header;
 | 
			
		||||
 | 
			
		||||
    if(SaveFile == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        printf("Can\'t create file for write.\n");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        // gather information to fill dfmapheader
 | 
			
		||||
        strcpy(df_map_header.identifier, dmh_id);
 | 
			
		||||
        df_map_header.version = dmh_ver;
 | 
			
		||||
        df_map_header.reserved = 0/*sizeof(DfMapHeader)*/;
 | 
			
		||||
        
 | 
			
		||||
        // save map header
 | 
			
		||||
        fwrite(&df_map_header, sizeof(DfMapHeader), 1, SaveFile);
 | 
			
		||||
        
 | 
			
		||||
        // save map
 | 
			
		||||
        writeVersion1(SaveFile);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // reopen file for reading
 | 
			
		||||
    freopen (FilePath.c_str(),"rb",SaveFile);
 | 
			
		||||
    if(SaveFile == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        printf("Can\'t create file for read.\n");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FILE *SaveCompressedFile;
 | 
			
		||||
    string CompressedFilePath = FilePath + ".comp";
 | 
			
		||||
 | 
			
		||||
    SaveCompressedFile = fopen(CompressedFilePath.c_str(),"wb");
 | 
			
		||||
    if(SaveCompressedFile == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        printf("Can\'t create a compressed file for write\n");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // compress
 | 
			
		||||
    printf("Compressing... ");
 | 
			
		||||
    int ret = def(SaveFile, SaveCompressedFile, Z_BEST_COMPRESSION);
 | 
			
		||||
    if (ret != Z_OK)
 | 
			
		||||
    {
 | 
			
		||||
        zerr(ret);
 | 
			
		||||
    }
 | 
			
		||||
    printf("DONE\n");
 | 
			
		||||
 | 
			
		||||
    fclose(SaveFile);
 | 
			
		||||
    fclose(SaveCompressedFile);
 | 
			
		||||
    remove(FilePath.c_str());
 | 
			
		||||
    rename(CompressedFilePath.c_str(), FilePath.c_str());
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool DfMap::load(string FilePath)
 | 
			
		||||
{
 | 
			
		||||
    string DecompressedFilePath = FilePath + ".decomp";
 | 
			
		||||
    FILE *ToDecompress;
 | 
			
		||||
    FILE *Decompressed;
 | 
			
		||||
    DfMapHeader df_map_header;
 | 
			
		||||
    bool isok = false;
 | 
			
		||||
 | 
			
		||||
    // open file for writing decompressed data
 | 
			
		||||
    Decompressed = fopen(DecompressedFilePath.c_str(), "wb");
 | 
			
		||||
    if  (Decompressed == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        printf("Can\'t open a decompressed file for write.\n");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // open compressed file
 | 
			
		||||
    ToDecompress = fopen(FilePath.c_str(),"rb");
 | 
			
		||||
    if  (ToDecompress == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        printf("Can\'t open file for read.\n");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // decompress
 | 
			
		||||
    printf("Decompressing... ");
 | 
			
		||||
    int ret = inf(/*source*/ToDecompress,/*destination*/Decompressed);
 | 
			
		||||
 | 
			
		||||
    printf("DONE\n");
 | 
			
		||||
 | 
			
		||||
    if (ret != Z_OK)
 | 
			
		||||
    {
 | 
			
		||||
        zerr(ret);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // OK, close file with compressed data
 | 
			
		||||
    fclose(ToDecompress);
 | 
			
		||||
    
 | 
			
		||||
    // reopen decompressed file for reading
 | 
			
		||||
    freopen(DecompressedFilePath.c_str(), "rb", Decompressed);
 | 
			
		||||
    if  (Decompressed == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        printf("Can\'t create decompressed file for read.\n");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // check, if the file is big enough to contain the header
 | 
			
		||||
    fseek(Decompressed, 0, SEEK_END);
 | 
			
		||||
 | 
			
		||||
    if (ftell(Decompressed) < (int32_t)sizeof(DfMapHeader))
 | 
			
		||||
    {
 | 
			
		||||
    	printf("This Khazad map file is corrupted - file too small.\n");
 | 
			
		||||
    	return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // read the header
 | 
			
		||||
    fseek(Decompressed, 0, SEEK_SET);
 | 
			
		||||
    fread(&df_map_header, sizeof(DfMapHeader), 1, Decompressed);
 | 
			
		||||
 | 
			
		||||
    // check, if it's a Khazad map file
 | 
			
		||||
    if (strcmp(df_map_header.identifier,dmh_id) != 0)
 | 
			
		||||
    {
 | 
			
		||||
    	printf("This file is not a Khazad map file.\n");
 | 
			
		||||
    	return false;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // ALERT: flush all map data. This is very important.
 | 
			
		||||
    clear();
 | 
			
		||||
    
 | 
			
		||||
    switch(df_map_header.version)
 | 
			
		||||
    {
 | 
			
		||||
        /*
 | 
			
		||||
            Basic format without matgloss. Kept for compatibility reasons.
 | 
			
		||||
            Saved from version 0.0.5
 | 
			
		||||
        */
 | 
			
		||||
        case 1:
 | 
			
		||||
            isok = loadVersion1(Decompressed, df_map_header);
 | 
			
		||||
            break;
 | 
			
		||||
        
 | 
			
		||||
        /*
 | 
			
		||||
            v2 format
 | 
			
		||||
            Saved from some SVN version. this format is dead
 | 
			
		||||
        */
 | 
			
		||||
        case 2:
 | 
			
		||||
            //isok = loadVersion2(Decompressed, df_map_header);
 | 
			
		||||
            isok = false;
 | 
			
		||||
            break;
 | 
			
		||||
        
 | 
			
		||||
        default:
 | 
			
		||||
            printf("Unknown Khazad map file version(%3d).\n", df_map_header.version);
 | 
			
		||||
            isok = false;
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // close decompressed file and delete it
 | 
			
		||||
    fclose(Decompressed);
 | 
			
		||||
    remove(DecompressedFilePath.c_str());
 | 
			
		||||
    return isok;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,106 @@
 | 
			
		||||
/*
 | 
			
		||||
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 "DFCommon.h"
 | 
			
		||||
#include "DfMap.h"
 | 
			
		||||
#include "DfMapHeader.h"
 | 
			
		||||
#include "ZlibHelper.h"
 | 
			
		||||
 | 
			
		||||
// LOAD v1 BLOCKS
 | 
			
		||||
bool DfMap::loadVersion1(FILE * Decompressed,DfMapHeader & h)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t x, y, z;
 | 
			
		||||
    uint32_t tile_block_count; // how many tile blocks to read from the data location
 | 
			
		||||
 | 
			
		||||
    // load new size information
 | 
			
		||||
    fread(&tile_block_count, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
    fread(&x_block_count, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
    fread(&y_block_count, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
    fread(&z_block_count, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
    
 | 
			
		||||
    // make sure those size variables are in sync
 | 
			
		||||
    updateCellCount();
 | 
			
		||||
    
 | 
			
		||||
    // alloc new space for our new size
 | 
			
		||||
    allocBlockArray(x_block_count,y_block_count,z_block_count);
 | 
			
		||||
 | 
			
		||||
    // let's load the blocks
 | 
			
		||||
    for (uint32_t tile_block = 0U; tile_block < tile_block_count; ++tile_block)
 | 
			
		||||
    {
 | 
			
		||||
        // block position - we can omit empty blocks this way
 | 
			
		||||
        fread(&x, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
        fread(&y, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
        fread(&z, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
        
 | 
			
		||||
        Block * b = allocBlock(x,y,z);
 | 
			
		||||
 | 
			
		||||
        // read data
 | 
			
		||||
        fread(&b->tile_type, sizeof(b->tile_type), 1, Decompressed);
 | 
			
		||||
        fread(&b->designation, sizeof(b->designation), 1, Decompressed);
 | 
			
		||||
        fread(&b->occupancy, sizeof(b->occupancy), 1, Decompressed);
 | 
			
		||||
        memset(b->material, -1, sizeof(b->material));
 | 
			
		||||
        
 | 
			
		||||
        // can't load offsets, substitute local biome everywhere
 | 
			
		||||
        memset(b->RegionOffsets,eHere,sizeof(b->RegionOffsets));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    printf("Blocks read into memory: %d\n", tile_block_count);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SAVE v1 BLOCKS
 | 
			
		||||
bool DfMap::writeVersion1(FILE * SaveFile)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t x, y, z;
 | 
			
		||||
    // write size information - total blocks and map size
 | 
			
		||||
    fwrite(&blocks_allocated, sizeof(uint32_t), 1, SaveFile);
 | 
			
		||||
    fwrite(&x_block_count, sizeof(uint32_t), 1, SaveFile);
 | 
			
		||||
    fwrite(&y_block_count, sizeof(uint32_t), 1, SaveFile);
 | 
			
		||||
    fwrite(&z_block_count, sizeof(uint32_t), 1, SaveFile);
 | 
			
		||||
    
 | 
			
		||||
    // write each non-empty block
 | 
			
		||||
    for (x = 0; x < x_block_count; x++ )
 | 
			
		||||
    {
 | 
			
		||||
        for (y = 0; y < y_block_count; y++ )
 | 
			
		||||
        {
 | 
			
		||||
            for (z = 0; z < z_block_count; z++ )
 | 
			
		||||
            {
 | 
			
		||||
                Block *b = getBlock(x,y,z);
 | 
			
		||||
                if(b != NULL)
 | 
			
		||||
                {
 | 
			
		||||
                    // first goes block position
 | 
			
		||||
                    fwrite(&x, sizeof(uint32_t), 1, SaveFile);
 | 
			
		||||
                    fwrite(&y, sizeof(uint32_t), 1, SaveFile);
 | 
			
		||||
                    fwrite(&z, sizeof(uint32_t), 1, SaveFile);
 | 
			
		||||
                    // then block data
 | 
			
		||||
                    fwrite(&b->tile_type, sizeof(uint16_t), BLOCK_SIZE*BLOCK_SIZE, SaveFile);
 | 
			
		||||
                    fwrite(&b->designation, sizeof(uint32_t), BLOCK_SIZE*BLOCK_SIZE, SaveFile);
 | 
			
		||||
                    fwrite(&b->occupancy, sizeof(uint32_t), BLOCK_SIZE*BLOCK_SIZE, SaveFile);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,196 @@
 | 
			
		||||
/*
 | 
			
		||||
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 "DFCommon.h"
 | 
			
		||||
#include "DfMap.h"
 | 
			
		||||
#include "DfMapHeader.h"
 | 
			
		||||
#include "ZlibHelper.h"
 | 
			
		||||
/*
 | 
			
		||||
bool DfMap::loadMatgloss2(FILE * Decompressed)
 | 
			
		||||
{
 | 
			
		||||
    char buffer [256];
 | 
			
		||||
    uint32_t nummatgloss;
 | 
			
		||||
    uint32_t temp;
 | 
			
		||||
    fread(&nummatgloss, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
    ///FIXME: buffer overrun possible? probably not. but fix it anyway.
 | 
			
		||||
    for(uint32_t i = 0; i< nummatgloss;i++)
 | 
			
		||||
    {
 | 
			
		||||
        fread(&temp, sizeof(uint32_t), 1, Decompressed); // string length
 | 
			
		||||
        fread(&buffer, sizeof(char), temp, Decompressed); // string
 | 
			
		||||
        buffer[temp] = 0;
 | 
			
		||||
        v_matgloss[Mat_Stone].push_back(buffer);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
bool DfMap::loadBlocks2(FILE * Decompressed,DfMapHeader & h)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t x, y, z;
 | 
			
		||||
    uint32_t numveins;
 | 
			
		||||
    t_vein vein;
 | 
			
		||||
 | 
			
		||||
//    for (uint32_t tile_block = 0U; tile_block < h.tile_block_count; ++tile_block)
 | 
			
		||||
    {
 | 
			
		||||
        fread(&x, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
        fread(&y, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
        fread(&z, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
 | 
			
		||||
        Block * b = allocBlock(x,y,z);
 | 
			
		||||
 | 
			
		||||
        fread(&b->tile_type, sizeof(b->tile_type), 1, Decompressed);
 | 
			
		||||
        fread(&b->designation, sizeof(b->designation), 1, Decompressed);
 | 
			
		||||
        fread(&b->occupancy, sizeof(b->occupancy), 1, Decompressed);
 | 
			
		||||
        fread(&b->RegionOffsets,sizeof(b->RegionOffsets),1,Decompressed);
 | 
			
		||||
        // load all veins of this block
 | 
			
		||||
        fread(&numveins, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
        if(v_matgloss[Mat_Stone].size())
 | 
			
		||||
        {
 | 
			
		||||
            applyGeoMatgloss(b);
 | 
			
		||||
        }
 | 
			
		||||
        for(uint32_t i = 0; i < numveins; i++)
 | 
			
		||||
        {
 | 
			
		||||
            fread(&vein,sizeof(t_vein),1,Decompressed);
 | 
			
		||||
            b->veins.push_back(vein);
 | 
			
		||||
        }
 | 
			
		||||
        if(numveins)
 | 
			
		||||
            b->collapseVeins();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
bool DfMap::loadRegion2(FILE * Decompressed)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t temp, temp2;
 | 
			
		||||
    for(uint32_t i = eNorthWest; i< eBiomeCount;i++)
 | 
			
		||||
    {
 | 
			
		||||
        fread(&temp, sizeof(uint32_t), 1, Decompressed); // layer vector length
 | 
			
		||||
        for(uint32_t j = 0; j < temp;j++) // load all geolayers into vectors (just 16bit matgloss indices)
 | 
			
		||||
        {
 | 
			
		||||
            fread(&temp2, sizeof(uint16_t), 1, Decompressed);
 | 
			
		||||
            v_geology[i].push_back(temp2);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
bool DfMap::loadVersion2(FILE * Decompressed,DfMapHeader & h)
 | 
			
		||||
{
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
    uint32_t tile_block_count; // how many tile blocks to read from the data location
 | 
			
		||||
 | 
			
		||||
    //uint32_t x_block_count, y_block_count, z_block_count; // DF's map block count
 | 
			
		||||
 | 
			
		||||
    fread(&tile_block_count, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
    fread(&x_block_count, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
    fread(&y_block_count, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
    fread(&z_block_count, sizeof(uint32_t), 1, Decompressed);
 | 
			
		||||
 | 
			
		||||
    // load new size information
 | 
			
		||||
    //x_block_count = h.x_block_count;
 | 
			
		||||
    //y_block_count = h.y_block_count;
 | 
			
		||||
    //z_block_count = h.z_block_count;
 | 
			
		||||
    // make sure those size variables are in sync
 | 
			
		||||
    updateCellCount();
 | 
			
		||||
    // alloc new space for our new size
 | 
			
		||||
    allocBlockArray(x_block_count,y_block_count,z_block_count);
 | 
			
		||||
 | 
			
		||||
//    fseek(Decompressed, h.map_data_location, SEEK_SET);
 | 
			
		||||
 | 
			
		||||
    // read matgloss vector
 | 
			
		||||
    loadMatgloss2(Decompressed);
 | 
			
		||||
    // read region data
 | 
			
		||||
    loadRegion2(Decompressed);
 | 
			
		||||
    // read blocks
 | 
			
		||||
    loadBlocks2(Decompressed,h);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DfMap::writeMatgloss2(FILE * SaveFile)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t nummatgloss = v_matgloss[Mat_Stone].size();
 | 
			
		||||
    fwrite(&nummatgloss, sizeof(uint32_t), 1, SaveFile);
 | 
			
		||||
    for(uint32_t i = 0; i< nummatgloss;i++)
 | 
			
		||||
    {
 | 
			
		||||
        const char *saveme = v_matgloss[Mat_Stone][i].c_str();
 | 
			
		||||
        uint32_t length = v_matgloss[Mat_Stone][i].size();
 | 
			
		||||
        fwrite(&length, sizeof(uint32_t),1,SaveFile);
 | 
			
		||||
        fwrite(saveme, sizeof(char), length, SaveFile);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DfMap::writeRegion2(FILE * SaveFile)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t temp, temp2;
 | 
			
		||||
    for(uint32_t i = eNorthWest; i< eBiomeCount;i++)
 | 
			
		||||
    {
 | 
			
		||||
        temp = v_geology[i].size();
 | 
			
		||||
        fwrite(&temp, sizeof(uint32_t), 1, SaveFile); // layer vector length
 | 
			
		||||
        for(uint32_t j = 0; j < temp;j++) // write all geolayers (just 16bit matgloss indices)
 | 
			
		||||
        {
 | 
			
		||||
            temp2 = v_geology[i][j];
 | 
			
		||||
            fwrite(&temp2, sizeof(uint16_t), 1, SaveFile);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DfMap::writeBlocks2(FILE * SaveFile)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t x, y, z, numveins;
 | 
			
		||||
    for (x = 0; x < x_block_count; x++ )
 | 
			
		||||
    {
 | 
			
		||||
        for (y = 0; y < y_block_count; y++ )
 | 
			
		||||
        {
 | 
			
		||||
            for (z = 0; z < z_block_count; z++ )
 | 
			
		||||
            {
 | 
			
		||||
                Block *b = getBlock(x,y,z);
 | 
			
		||||
                if(b != NULL)
 | 
			
		||||
                {
 | 
			
		||||
                    // which block it is
 | 
			
		||||
                    fwrite(&x, sizeof(uint32_t), 1, SaveFile);
 | 
			
		||||
                    fwrite(&y, sizeof(uint32_t), 1, SaveFile);
 | 
			
		||||
                    fwrite(&z, sizeof(uint32_t), 1, SaveFile);
 | 
			
		||||
                    // block data
 | 
			
		||||
                    fwrite(&b->tile_type, sizeof(uint16_t), BLOCK_SIZE*BLOCK_SIZE, SaveFile);
 | 
			
		||||
                    fwrite(&b->designation, sizeof(uint32_t), BLOCK_SIZE*BLOCK_SIZE, SaveFile);
 | 
			
		||||
                    fwrite(&b->occupancy, sizeof(uint32_t), BLOCK_SIZE*BLOCK_SIZE, SaveFile);
 | 
			
		||||
                    fwrite(&b->RegionOffsets, sizeof(b->RegionOffsets), 1, SaveFile);
 | 
			
		||||
                    // write all veins
 | 
			
		||||
                    numveins = b->veins.size();
 | 
			
		||||
                    fwrite(&numveins, sizeof(uint32_t), 1, SaveFile);
 | 
			
		||||
                    for(uint32_t i = 0; i < numveins; i++)
 | 
			
		||||
                    {
 | 
			
		||||
                        fwrite(&b->veins[i],sizeof(t_vein),1,SaveFile);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool DfMap::writeVersion2(FILE * SaveFile)
 | 
			
		||||
{
 | 
			
		||||
    // write matgloss vector
 | 
			
		||||
    writeMatgloss2(SaveFile);
 | 
			
		||||
    // write region data
 | 
			
		||||
    writeRegion2(SaveFile);
 | 
			
		||||
    // write blocks
 | 
			
		||||
    writeBlocks2(SaveFile);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
@ -0,0 +1,160 @@
 | 
			
		||||
// SOURCE: http://www.zlib.net/zpipe.c
 | 
			
		||||
 | 
			
		||||
#ifndef ZLIB_HELPER_HEADER
 | 
			
		||||
#define ZLIB_HELPER_HEADER
 | 
			
		||||
 | 
			
		||||
#include <zlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
//#define CHUNK 16384
 | 
			
		||||
#define CHUNK 262144
 | 
			
		||||
 | 
			
		||||
/* Compress from file source to file dest until EOF on source.
 | 
			
		||||
   def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
 | 
			
		||||
   allocated for processing, Z_STREAM_ERROR if an invalid compression
 | 
			
		||||
   level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
 | 
			
		||||
   version of the library linked do not match, or Z_ERRNO if there is
 | 
			
		||||
   an error reading or writing the files. */
 | 
			
		||||
inline int def(FILE *source, FILE *dest, int level)
 | 
			
		||||
{
 | 
			
		||||
    int ret, flush;
 | 
			
		||||
    unsigned have;
 | 
			
		||||
    z_stream strm;
 | 
			
		||||
    unsigned char in[CHUNK];
 | 
			
		||||
    unsigned char out[CHUNK];
 | 
			
		||||
 | 
			
		||||
    /* allocate deflate state */
 | 
			
		||||
    strm.zalloc = Z_NULL;
 | 
			
		||||
    strm.zfree = Z_NULL;
 | 
			
		||||
    strm.opaque = Z_NULL;
 | 
			
		||||
    ret = deflateInit(&strm, level);
 | 
			
		||||
    if (ret != Z_OK)
 | 
			
		||||
        return ret;
 | 
			
		||||
 | 
			
		||||
    /* compress until end of file */
 | 
			
		||||
    do {
 | 
			
		||||
        strm.avail_in = fread(in, 1, CHUNK, source);
 | 
			
		||||
        if (ferror(source)) {
 | 
			
		||||
            (void)deflateEnd(&strm);
 | 
			
		||||
            return Z_ERRNO;
 | 
			
		||||
        }
 | 
			
		||||
        flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
 | 
			
		||||
        strm.next_in = in;
 | 
			
		||||
 | 
			
		||||
        /* run deflate() on input until output buffer not full, finish
 | 
			
		||||
           compression if all of source has been read in */
 | 
			
		||||
        do {
 | 
			
		||||
            strm.avail_out = CHUNK;
 | 
			
		||||
            strm.next_out = out;
 | 
			
		||||
            ret = deflate(&strm, flush);    /* no bad return value */
 | 
			
		||||
            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
 | 
			
		||||
            have = CHUNK - strm.avail_out;
 | 
			
		||||
            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
 | 
			
		||||
                (void)deflateEnd(&strm);
 | 
			
		||||
                return Z_ERRNO;
 | 
			
		||||
            }
 | 
			
		||||
        } while (strm.avail_out == 0);
 | 
			
		||||
        assert(strm.avail_in == 0);     /* all input will be used */
 | 
			
		||||
 | 
			
		||||
        /* done when last data in file processed */
 | 
			
		||||
    } while (flush != Z_FINISH);
 | 
			
		||||
    assert(ret == Z_STREAM_END);        /* stream will be complete */
 | 
			
		||||
 | 
			
		||||
    /* clean up and return */
 | 
			
		||||
    (void)deflateEnd(&strm);
 | 
			
		||||
    return Z_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Decompress from file source to file dest until stream ends or EOF.
 | 
			
		||||
   inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
 | 
			
		||||
   allocated for processing, Z_DATA_ERROR if the deflate data is
 | 
			
		||||
   invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
 | 
			
		||||
   the version of the library linked do not match, or Z_ERRNO if there
 | 
			
		||||
   is an error reading or writing the files. */
 | 
			
		||||
inline int inf(FILE *source, FILE *dest)
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    unsigned have;
 | 
			
		||||
    z_stream strm;
 | 
			
		||||
    unsigned char in[CHUNK];
 | 
			
		||||
    unsigned char out[CHUNK];
 | 
			
		||||
 | 
			
		||||
    /* allocate inflate state */
 | 
			
		||||
    strm.zalloc = Z_NULL;
 | 
			
		||||
    strm.zfree = Z_NULL;
 | 
			
		||||
    strm.opaque = Z_NULL;
 | 
			
		||||
    strm.avail_in = 0;
 | 
			
		||||
    strm.next_in = Z_NULL;
 | 
			
		||||
    ret = inflateInit(&strm);
 | 
			
		||||
    if (ret != Z_OK)
 | 
			
		||||
        return ret;
 | 
			
		||||
 | 
			
		||||
    /* decompress until deflate stream ends or end of file */
 | 
			
		||||
    do {
 | 
			
		||||
        strm.avail_in = fread(in, 1, CHUNK, source);
 | 
			
		||||
        if (ferror(source)) {
 | 
			
		||||
            (void)inflateEnd(&strm);
 | 
			
		||||
            return Z_ERRNO;
 | 
			
		||||
        }
 | 
			
		||||
        if (strm.avail_in == 0)
 | 
			
		||||
            break;
 | 
			
		||||
        strm.next_in = in;
 | 
			
		||||
 | 
			
		||||
        /* run inflate() on input until output buffer not full */
 | 
			
		||||
        do {
 | 
			
		||||
            strm.avail_out = CHUNK;
 | 
			
		||||
            strm.next_out = out;
 | 
			
		||||
            ret = inflate(&strm, Z_NO_FLUSH);
 | 
			
		||||
            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
 | 
			
		||||
            switch (ret) {
 | 
			
		||||
            case Z_NEED_DICT:
 | 
			
		||||
                ret = Z_DATA_ERROR;     /* and fall through */
 | 
			
		||||
            case Z_DATA_ERROR:
 | 
			
		||||
            case Z_MEM_ERROR:
 | 
			
		||||
                (void)inflateEnd(&strm);
 | 
			
		||||
                return ret;
 | 
			
		||||
            }
 | 
			
		||||
            have = CHUNK - strm.avail_out;
 | 
			
		||||
            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
 | 
			
		||||
                (void)inflateEnd(&strm);
 | 
			
		||||
                return Z_ERRNO;
 | 
			
		||||
            }
 | 
			
		||||
        } while (strm.avail_out == 0);
 | 
			
		||||
 | 
			
		||||
        /* done when inflate() says it's done */
 | 
			
		||||
    } while (ret != Z_STREAM_END);
 | 
			
		||||
 | 
			
		||||
    /* clean up and return */
 | 
			
		||||
    (void)inflateEnd(&strm);
 | 
			
		||||
    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* report a zlib or i/o error */
 | 
			
		||||
inline void zerr(int ret)
 | 
			
		||||
{
 | 
			
		||||
    printf("zpipe: %d\n", ret);
 | 
			
		||||
    switch (ret) {
 | 
			
		||||
    case Z_ERRNO:
 | 
			
		||||
        if (ferror(stdin))
 | 
			
		||||
            fprintf(stderr,"error reading stdin\n");
 | 
			
		||||
        if (ferror(stdout))
 | 
			
		||||
            fprintf(stderr,"error writing stdout\n");
 | 
			
		||||
        break;
 | 
			
		||||
    case Z_STREAM_ERROR:
 | 
			
		||||
        printf("invalid compression level\n");
 | 
			
		||||
        break;
 | 
			
		||||
    case Z_DATA_ERROR:
 | 
			
		||||
        printf("invalid or incomplete deflate data\n");
 | 
			
		||||
        break;
 | 
			
		||||
    case Z_MEM_ERROR:
 | 
			
		||||
        printf("out of memory\n");
 | 
			
		||||
        break;
 | 
			
		||||
    case Z_VERSION_ERROR:
 | 
			
		||||
        printf("zlib version mismatch!\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // ZLIB_HELPER_HEADER
 | 
			
		||||
@ -0,0 +1,332 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 	This is the C++ implementation of the MD5 Message-Digest
 | 
			
		||||
 * 	Algorithm desrcipted in RFC 1321.
 | 
			
		||||
 * 	I translated the C code from this RFC to C++.
 | 
			
		||||
 * 	There is now warranty.
 | 
			
		||||
 *
 | 
			
		||||
 * 	Feb. 12. 2005
 | 
			
		||||
 * 	Benjamin Grüdelbach
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Changed unsigned long int types into uint32_t to make this work on 64bit systems.
 | 
			
		||||
 * Sep. 5. 2009
 | 
			
		||||
 * Petr Mrázek
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *	Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
 | 
			
		||||
 *	rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 *	License to copy and use this software is granted provided that it
 | 
			
		||||
 *	is identified as the "RSA Data Security, Inc. MD5 Message-Digest
 | 
			
		||||
 *	Algorithm" in all material mentioning or referencing this software
 | 
			
		||||
 *	or this function.
 | 
			
		||||
 *
 | 
			
		||||
 *	License is also granted to make and use derivative works provided
 | 
			
		||||
 *	that such works are identified as "derived from the RSA Data
 | 
			
		||||
 *	Security, Inc. MD5 Message-Digest Algorithm" in all material
 | 
			
		||||
 *	mentioning or referencing the derived work.
 | 
			
		||||
 *
 | 
			
		||||
 *	RSA Data Security, Inc. makes no representations concerning either
 | 
			
		||||
 *	the merchantability of this software or the suitability of this
 | 
			
		||||
 *	software for any particular purpose. It is provided "as is"
 | 
			
		||||
 *	without express or implied warranty of any kind.
 | 
			
		||||
 *
 | 
			
		||||
 *	These notices must be retained in any copies of any part of this
 | 
			
		||||
 *	documentation and/or software.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//md5 class include
 | 
			
		||||
#include "md5.h"
 | 
			
		||||
 | 
			
		||||
// Constants for MD5Transform routine.
 | 
			
		||||
#define S11 7
 | 
			
		||||
#define S12 12
 | 
			
		||||
#define S13 17
 | 
			
		||||
#define S14 22
 | 
			
		||||
#define S21 5
 | 
			
		||||
#define S22 9
 | 
			
		||||
#define S23 14
 | 
			
		||||
#define S24 20
 | 
			
		||||
#define S31 4
 | 
			
		||||
#define S32 11
 | 
			
		||||
#define S33 16
 | 
			
		||||
#define S34 23
 | 
			
		||||
#define S41 6
 | 
			
		||||
#define S42 10
 | 
			
		||||
#define S43 15
 | 
			
		||||
#define S44 21
 | 
			
		||||
 | 
			
		||||
static unsigned char PADDING[64] = {
 | 
			
		||||
  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | 
			
		||||
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | 
			
		||||
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* F, G, H and I are basic MD5 functions. */
 | 
			
		||||
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
 | 
			
		||||
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
 | 
			
		||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
 | 
			
		||||
#define I(x, y, z) ((y) ^ ((x) | (~z)))
 | 
			
		||||
 | 
			
		||||
/* ROTATE_LEFT rotates x left n bits. */
 | 
			
		||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
 | 
			
		||||
Rotation is separate from addition to prevent recomputation.
 | 
			
		||||
*/
 | 
			
		||||
#define FF(a, b, c, d, x, s, ac) { \
 | 
			
		||||
 (a) += F ((b), (c), (d)) + (x) + (unsigned long int)(ac); \
 | 
			
		||||
 (a) = ROTATE_LEFT ((a), (s)); \
 | 
			
		||||
 (a) += (b); \
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#define GG(a, b, c, d, x, s, ac) { \
 | 
			
		||||
 (a) += G ((b), (c), (d)) + (x) + (unsigned long int)(ac); \
 | 
			
		||||
 (a) = ROTATE_LEFT ((a), (s)); \
 | 
			
		||||
 (a) += (b); \
 | 
			
		||||
  }
 | 
			
		||||
#define HH(a, b, c, d, x, s, ac) { \
 | 
			
		||||
 (a) += H ((b), (c), (d)) + (x) + (unsigned long int)(ac); \
 | 
			
		||||
 (a) = ROTATE_LEFT ((a), (s)); \
 | 
			
		||||
 (a) += (b); \
 | 
			
		||||
  }
 | 
			
		||||
#define II(a, b, c, d, x, s, ac) { \
 | 
			
		||||
 (a) += I ((b), (c), (d)) + (x) + (unsigned long int)(ac); \
 | 
			
		||||
 (a) = ROTATE_LEFT ((a), (s)); \
 | 
			
		||||
 (a) += (b); \
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
/* MD5 initialization. Begins an MD5 operation, writing a new context. */
 | 
			
		||||
void MD5::MD5Init (MD5_CTX *context)
 | 
			
		||||
{
 | 
			
		||||
	  context->count[0] = context->count[1] = 0;
 | 
			
		||||
	  context->state[0] = 0x67452301;
 | 
			
		||||
	  context->state[1] = 0xefcdab89;
 | 
			
		||||
	  context->state[2] = 0x98badcfe;
 | 
			
		||||
	  context->state[3] = 0x10325476;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	 MD5 block update operation. Continues an MD5 message-digest
 | 
			
		||||
	 operation, processing another message block, and updating the
 | 
			
		||||
	 context.
 | 
			
		||||
*/
 | 
			
		||||
void MD5::MD5Update (MD5_CTX *context, unsigned char *input, unsigned int inputLen)
 | 
			
		||||
{
 | 
			
		||||
	  unsigned int i, index, partLen;
 | 
			
		||||
 | 
			
		||||
	  /* Compute number of bytes mod 64 */
 | 
			
		||||
	  index = (unsigned int)((context->count[0] >> 3) & 0x3F);
 | 
			
		||||
 | 
			
		||||
	  /* Update number of bits */
 | 
			
		||||
	  if ( (context->count[0] += ((unsigned long int)inputLen << 3))
 | 
			
		||||
	       < ((unsigned long int)inputLen << 3))
 | 
			
		||||
		context->count[1]++;
 | 
			
		||||
 | 
			
		||||
	  context->count[1] += ((unsigned long int)inputLen >> 29);
 | 
			
		||||
	  partLen = 64 - index;
 | 
			
		||||
 | 
			
		||||
	  /*
 | 
			
		||||
	   * Transform as many times as possible.
 | 
			
		||||
	   */
 | 
			
		||||
	  if (inputLen >= partLen)
 | 
			
		||||
	  {
 | 
			
		||||
		 MD5_memcpy ((POINTER)&context->buffer[index], (POINTER)input, partLen);
 | 
			
		||||
		 MD5Transform (context->state, context->buffer);
 | 
			
		||||
 | 
			
		||||
		 for (i = partLen; i + 63 < inputLen; i += 64)
 | 
			
		||||
		   MD5Transform (context->state, &input[i]);
 | 
			
		||||
 | 
			
		||||
		 index = 0;
 | 
			
		||||
	  }
 | 
			
		||||
	  else
 | 
			
		||||
	 	i = 0;
 | 
			
		||||
 | 
			
		||||
	  /* Buffer remaining input */
 | 
			
		||||
	  MD5_memcpy ((POINTER)&context->buffer[index],
 | 
			
		||||
	              (POINTER)&input[i],
 | 
			
		||||
		      inputLen-i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * MD5 finalization. Ends an MD5 message-digest operation, writing the
 | 
			
		||||
 * the message digest and zeroizing the context.
 | 
			
		||||
 */
 | 
			
		||||
void MD5::MD5Final (unsigned char digest[16], MD5_CTX *context)
 | 
			
		||||
{
 | 
			
		||||
	unsigned char bits[8];
 | 
			
		||||
	unsigned int index, padLen;
 | 
			
		||||
 | 
			
		||||
	/* Save number of bits */
 | 
			
		||||
	Encode (bits, context->count, 8);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Pad out to 56 mod 64.
 | 
			
		||||
	 */
 | 
			
		||||
	index = (unsigned int)((context->count[0] >> 3) & 0x3f);
 | 
			
		||||
	padLen = (index < 56) ? (56 - index) : (120 - index);
 | 
			
		||||
	MD5Update (context, PADDING, padLen);
 | 
			
		||||
 | 
			
		||||
	/* Append length (before padding) */
 | 
			
		||||
	MD5Update (context, bits, 8);
 | 
			
		||||
 | 
			
		||||
	/* Store state in digest */
 | 
			
		||||
	Encode (digest, context->state, 16);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Zeroize sensitive information.
 | 
			
		||||
	 */
 | 
			
		||||
	MD5_memset ((POINTER)context, 0, sizeof (*context));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * MD5 basic transformation. Transforms state based on block.
 | 
			
		||||
 */
 | 
			
		||||
void MD5::MD5Transform (uint32_t state[4], unsigned char block[64])
 | 
			
		||||
{
 | 
			
		||||
	uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
 | 
			
		||||
 | 
			
		||||
	Decode (x, block, 64);
 | 
			
		||||
 | 
			
		||||
	/* Round 1 */
 | 
			
		||||
	FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
 | 
			
		||||
	FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
 | 
			
		||||
	FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
 | 
			
		||||
	FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
 | 
			
		||||
	FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
 | 
			
		||||
	FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
 | 
			
		||||
	FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
 | 
			
		||||
	FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
 | 
			
		||||
	FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
 | 
			
		||||
	FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
 | 
			
		||||
	FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
 | 
			
		||||
	FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
 | 
			
		||||
	FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
 | 
			
		||||
	FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
 | 
			
		||||
	FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
 | 
			
		||||
	FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
 | 
			
		||||
 | 
			
		||||
	/* Round 2 */
 | 
			
		||||
	GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
 | 
			
		||||
	GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
 | 
			
		||||
	GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
 | 
			
		||||
	GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
 | 
			
		||||
	GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
 | 
			
		||||
	GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
 | 
			
		||||
	GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
 | 
			
		||||
	GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
 | 
			
		||||
	GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
 | 
			
		||||
	GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
 | 
			
		||||
	GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
 | 
			
		||||
 | 
			
		||||
	GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
 | 
			
		||||
	GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
 | 
			
		||||
	GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
 | 
			
		||||
	GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
 | 
			
		||||
	GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
 | 
			
		||||
 | 
			
		||||
	/* Round 3 */
 | 
			
		||||
	HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
 | 
			
		||||
	HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
 | 
			
		||||
	HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
 | 
			
		||||
	HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
 | 
			
		||||
	HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
 | 
			
		||||
	HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
 | 
			
		||||
	HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
 | 
			
		||||
	HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
 | 
			
		||||
	HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
 | 
			
		||||
	HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
 | 
			
		||||
	HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
 | 
			
		||||
	HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
 | 
			
		||||
	HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
 | 
			
		||||
	HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
 | 
			
		||||
	HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
 | 
			
		||||
	HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
 | 
			
		||||
 | 
			
		||||
	/* Round 4 */
 | 
			
		||||
	II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
 | 
			
		||||
	II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
 | 
			
		||||
	II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
 | 
			
		||||
	II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
 | 
			
		||||
	II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
 | 
			
		||||
	II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
 | 
			
		||||
	II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
 | 
			
		||||
	II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
 | 
			
		||||
	II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
 | 
			
		||||
	II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
 | 
			
		||||
	II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
 | 
			
		||||
	II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
 | 
			
		||||
	II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
 | 
			
		||||
	II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
 | 
			
		||||
	II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
 | 
			
		||||
	II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
 | 
			
		||||
 | 
			
		||||
	state[0] += a;
 | 
			
		||||
	state[1] += b;
 | 
			
		||||
	state[2] += c;
 | 
			
		||||
	state[3] += d;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Zeroize sensitive information.
 | 
			
		||||
	 */
 | 
			
		||||
	MD5_memset ((POINTER)x, 0, sizeof (x));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Encodes input (unsigned long int) into output (unsigned char). Assumes len is
 | 
			
		||||
 * a multiple of 4.
 | 
			
		||||
 */
 | 
			
		||||
void MD5::Encode (unsigned char *output, uint32_t *input, unsigned int len)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int i, j;
 | 
			
		||||
 | 
			
		||||
	for (i = 0, j = 0; j < len; i++, j += 4) {
 | 
			
		||||
		output[j] = (unsigned char)(input[i] & 0xff);
 | 
			
		||||
		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
 | 
			
		||||
		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
 | 
			
		||||
		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Decodes input (unsigned char) into output (unsigned long int). Assumes len is
 | 
			
		||||
 * a multiple of 4.
 | 
			
		||||
 */
 | 
			
		||||
void MD5::Decode (uint32_t *output, unsigned char *input, unsigned int len)
 | 
			
		||||
{
 | 
			
		||||
	  unsigned int i, j;
 | 
			
		||||
 | 
			
		||||
	  for (i = 0, j = 0; j < len; i++, j += 4)
 | 
			
		||||
		 output[i] = ((uint32_t)input[j]) |
 | 
			
		||||
			     (((uint32_t)input[j+1]) << 8) |
 | 
			
		||||
			     (((uint32_t)input[j+2]) << 16) |
 | 
			
		||||
			     (((uint32_t)input[j+3]) << 24);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Note: Replace "for loop" with standard memcpy if possible.
 | 
			
		||||
 */
 | 
			
		||||
void MD5::MD5_memcpy (POINTER output, POINTER input, unsigned int len)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < len; i++)
 | 
			
		||||
		output[i] = input[i];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Note: Replace "for loop" with standard memset if possible.
 | 
			
		||||
 */
 | 
			
		||||
void MD5::MD5_memset (POINTER output,int value,unsigned int len)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
	for (i = 0; i < len; i++)
 | 
			
		||||
		((char *)output)[i] = (char)value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * EOF
 | 
			
		||||
 */
 | 
			
		||||
@ -0,0 +1,92 @@
 | 
			
		||||
/*
 | 
			
		||||
 *	This is the C++ implementation of the MD5 Message-Digest
 | 
			
		||||
 *	Algorithm desrcipted in RFC 1321.
 | 
			
		||||
 *	I translated the C code from this RFC to C++.
 | 
			
		||||
 *	There is now warranty.
 | 
			
		||||
 *
 | 
			
		||||
 *	Feb. 12. 2005
 | 
			
		||||
 *	Benjamin Grüdelbach
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Changed unsigned long int types into uint32_t to make this work on 64bit systems.
 | 
			
		||||
 * Sep. 5. 2009
 | 
			
		||||
 * Petr Mrázek
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
 | 
			
		||||
 * rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * License to copy and use this software is granted provided that it
 | 
			
		||||
 * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
 | 
			
		||||
 * Algorithm" in all material mentioning or referencing this software
 | 
			
		||||
 * or this function.
 | 
			
		||||
 *
 | 
			
		||||
 * License is also granted to make and use derivative works provided
 | 
			
		||||
 * that such works are identified as "derived from the RSA Data
 | 
			
		||||
 * Security, Inc. MD5 Message-Digest Algorithm" in all material
 | 
			
		||||
 * mentioning or referencing the derived work.
 | 
			
		||||
 *
 | 
			
		||||
 * RSA Data Security, Inc. makes no representations concerning either
 | 
			
		||||
 * the merchantability of this software or the suitability of this
 | 
			
		||||
 * software for any particular purpose. It is provided "as is"
 | 
			
		||||
 * without express or implied warranty of any kind.
 | 
			
		||||
 *
 | 
			
		||||
 * These notices must be retained in any copies of any part of this
 | 
			
		||||
 * documentation and/or software.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//----------------------------------------------------------------------
 | 
			
		||||
//include protection
 | 
			
		||||
#ifndef MD5_H
 | 
			
		||||
#define MD5_H
 | 
			
		||||
 | 
			
		||||
//----------------------------------------------------------------------
 | 
			
		||||
//STL includes
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
//----------------------------------------------------------------------
 | 
			
		||||
//typedefs
 | 
			
		||||
typedef unsigned char *POINTER;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * MD5 context.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
	uint32_t state[4];   	      /* state (ABCD) */
 | 
			
		||||
	uint32_t count[2]; 	      /* number of bits, modulo 2^64 (lsb first) */
 | 
			
		||||
	unsigned char buffer[64];	      /* input buffer */
 | 
			
		||||
} MD5_CTX;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * MD5 class
 | 
			
		||||
 */
 | 
			
		||||
class MD5
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
 | 
			
		||||
        void MD5Transform (uint32_t state[4], unsigned char block[64]);
 | 
			
		||||
		void Encode (unsigned char*, uint32_t*, unsigned int);
 | 
			
		||||
		void Decode (uint32_t*, unsigned char*, unsigned int);
 | 
			
		||||
		void MD5_memcpy (POINTER, POINTER, unsigned int);
 | 
			
		||||
		void MD5_memset (POINTER, int, unsigned int);
 | 
			
		||||
 | 
			
		||||
	public:
 | 
			
		||||
 | 
			
		||||
		void MD5Init (MD5_CTX*);
 | 
			
		||||
		void MD5Update (MD5_CTX*, unsigned char*, unsigned int);
 | 
			
		||||
		void MD5Final (unsigned char [16], MD5_CTX*);
 | 
			
		||||
 | 
			
		||||
	MD5(){};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//----------------------------------------------------------------------
 | 
			
		||||
//End of include protection
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * EOF
 | 
			
		||||
 */
 | 
			
		||||
@ -0,0 +1,140 @@
 | 
			
		||||
/*
 | 
			
		||||
 *	This is part of my wrapper-class to create
 | 
			
		||||
 *	a MD5 Hash from a string and a file.
 | 
			
		||||
 *
 | 
			
		||||
 *	This code is completly free, you
 | 
			
		||||
 *	can copy it, modify it, or do
 | 
			
		||||
 *	what ever you want with it.
 | 
			
		||||
 *
 | 
			
		||||
 *	Feb. 2005
 | 
			
		||||
 *	Benjamin Grüdelbach
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Changed unsigned long int types into uint32_t to make this work on 64bit systems.
 | 
			
		||||
 * Sep. 5. 2009
 | 
			
		||||
 * Petr Mrázek
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//----------------------------------------------------------------------
 | 
			
		||||
//basic includes
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
//my includes
 | 
			
		||||
#include "md5wrapper.h"
 | 
			
		||||
#include "md5.h"
 | 
			
		||||
 | 
			
		||||
//---------privates--------------------------
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * internal hash function, calling
 | 
			
		||||
 * the basic methods from md5.h
 | 
			
		||||
 */
 | 
			
		||||
std::string md5wrapper::hashit(std::string text)
 | 
			
		||||
{
 | 
			
		||||
	MD5_CTX ctx;
 | 
			
		||||
 | 
			
		||||
	//init md5
 | 
			
		||||
	md5->MD5Init(&ctx);
 | 
			
		||||
	//update with our string
 | 
			
		||||
	md5->MD5Update(&ctx,
 | 
			
		||||
		 (unsigned char*)text.c_str(),
 | 
			
		||||
		 text.length());
 | 
			
		||||
 | 
			
		||||
	//create the hash
 | 
			
		||||
	unsigned char buff[16] = "";
 | 
			
		||||
	md5->MD5Final((unsigned char*)buff,&ctx);
 | 
			
		||||
 | 
			
		||||
	//converte the hash to a string and return it
 | 
			
		||||
	return convToString(buff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * converts the numeric hash to
 | 
			
		||||
 * a valid std::string.
 | 
			
		||||
 * (based on Jim Howard's code;
 | 
			
		||||
 * http://www.codeproject.com/cpp/cmd5.asp)
 | 
			
		||||
 */
 | 
			
		||||
std::string md5wrapper::convToString(unsigned char *bytes)
 | 
			
		||||
{
 | 
			
		||||
	char asciihash[33];
 | 
			
		||||
 | 
			
		||||
	int p = 0;
 | 
			
		||||
	for(int i=0; i<16; i++)
 | 
			
		||||
	{
 | 
			
		||||
		::sprintf(&asciihash[p],"%02x",bytes[i]);
 | 
			
		||||
		p += 2;
 | 
			
		||||
	}
 | 
			
		||||
	asciihash[32] = '\0';
 | 
			
		||||
	return std::string(asciihash);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//---------publics--------------------------
 | 
			
		||||
 | 
			
		||||
//constructor
 | 
			
		||||
md5wrapper::md5wrapper()
 | 
			
		||||
{
 | 
			
		||||
	md5 = new MD5();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//destructor
 | 
			
		||||
md5wrapper::~md5wrapper()
 | 
			
		||||
{
 | 
			
		||||
	delete md5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * creates a MD5 hash from
 | 
			
		||||
 * "text" and returns it as
 | 
			
		||||
 * string
 | 
			
		||||
 */
 | 
			
		||||
std::string md5wrapper::getHashFromString(std::string text)
 | 
			
		||||
{
 | 
			
		||||
	return this->hashit(text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * creates a MD5 hash from
 | 
			
		||||
 * a file specified in "filename" and
 | 
			
		||||
 * returns it as string
 | 
			
		||||
 * (based on Ronald L. Rivest's code
 | 
			
		||||
 * from RFC1321 "The MD5 Message-Digest Algorithm")
 | 
			
		||||
 */
 | 
			
		||||
std::string md5wrapper::getHashFromFile(std::string filename)
 | 
			
		||||
{
 | 
			
		||||
	FILE *file;
 | 
			
		||||
  	MD5_CTX context;
 | 
			
		||||
 | 
			
		||||
	int len;
 | 
			
		||||
  	unsigned char buffer[1024], digest[16];
 | 
			
		||||
 | 
			
		||||
	//open file
 | 
			
		||||
  	if ((file = fopen (filename.c_str(), "rb")) == NULL)
 | 
			
		||||
	{
 | 
			
		||||
		return "-1";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//init md5
 | 
			
		||||
 	md5->MD5Init (&context);
 | 
			
		||||
 | 
			
		||||
	//read the filecontent
 | 
			
		||||
	while ( (len = fread (buffer, 1, 1024, file)) )
 | 
			
		||||
   	{
 | 
			
		||||
		md5->MD5Update (&context, buffer, len);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	generate hash, close the file and return the
 | 
			
		||||
	hash as std::string
 | 
			
		||||
	*/
 | 
			
		||||
	md5->MD5Final (digest, &context);
 | 
			
		||||
 	fclose (file);
 | 
			
		||||
	return convToString(digest);
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * EOF
 | 
			
		||||
 */
 | 
			
		||||
@ -0,0 +1,73 @@
 | 
			
		||||
/*
 | 
			
		||||
 *	This is my wrapper-class to create
 | 
			
		||||
 *	a MD5 Hash from a string and a file.
 | 
			
		||||
 *
 | 
			
		||||
 *	This code is completly free, you
 | 
			
		||||
 *	can copy it, modify it, or do
 | 
			
		||||
 *	what ever you want with it.
 | 
			
		||||
 *
 | 
			
		||||
 *	Feb. 2005
 | 
			
		||||
 *	Benjamin Grüdelbach
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Changed unsigned long int types into uint32_t to make this work on 64bit systems.
 | 
			
		||||
 * Sep. 5. 2009
 | 
			
		||||
 * Petr Mrázek
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//include protection
 | 
			
		||||
#ifndef MD5WRAPPER_H
 | 
			
		||||
#define MD5WRAPPER_H
 | 
			
		||||
 | 
			
		||||
//basic includes
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
//forwards
 | 
			
		||||
class MD5;
 | 
			
		||||
 | 
			
		||||
class md5wrapper
 | 
			
		||||
{
 | 
			
		||||
	private:
 | 
			
		||||
		MD5 *md5;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * internal hash function, calling
 | 
			
		||||
		 * the basic methods from md5.h
 | 
			
		||||
		 */
 | 
			
		||||
		std::string hashit(std::string text);
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * converts the numeric giets to
 | 
			
		||||
		 * a valid std::string
 | 
			
		||||
		 */
 | 
			
		||||
		std::string convToString(unsigned char *bytes);
 | 
			
		||||
	public:
 | 
			
		||||
		//constructor
 | 
			
		||||
		md5wrapper();
 | 
			
		||||
 | 
			
		||||
		//destructor
 | 
			
		||||
		~md5wrapper();
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * creates a MD5 hash from
 | 
			
		||||
		 * "text" and returns it as
 | 
			
		||||
		 * string
 | 
			
		||||
		 */
 | 
			
		||||
		std::string getHashFromString(std::string text);
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * creates a MD5 hash from
 | 
			
		||||
		 * a file specified in "filename" and
 | 
			
		||||
		 * returns it as string
 | 
			
		||||
		 */
 | 
			
		||||
		std::string getHashFromFile(std::string filename);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//include protection
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * EOF
 | 
			
		||||
 */
 | 
			
		||||
@ -0,0 +1,116 @@
 | 
			
		||||
/*
 | 
			
		||||
www.sourceforge.net/projects/tinyxml
 | 
			
		||||
Original file by Yves Berquin.
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * THIS FILE WAS ALTERED BY Tyge Løvset, 7. April 2005.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef TIXML_USE_STL
 | 
			
		||||
 | 
			
		||||
#include "tinystr.h"
 | 
			
		||||
 | 
			
		||||
// Error value for find primitive
 | 
			
		||||
const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Null rep.
 | 
			
		||||
TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void TiXmlString::reserve (size_type cap)
 | 
			
		||||
{
 | 
			
		||||
	if (cap > capacity())
 | 
			
		||||
	{
 | 
			
		||||
		TiXmlString tmp;
 | 
			
		||||
		tmp.init(length(), cap);
 | 
			
		||||
		memcpy(tmp.start(), data(), length());
 | 
			
		||||
		swap(tmp);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TiXmlString& TiXmlString::assign(const char* str, size_type len)
 | 
			
		||||
{
 | 
			
		||||
	size_type cap = capacity();
 | 
			
		||||
	if (len > cap || cap > 3*(len + 8))
 | 
			
		||||
	{
 | 
			
		||||
		TiXmlString tmp;
 | 
			
		||||
		tmp.init(len);
 | 
			
		||||
		memcpy(tmp.start(), str, len);
 | 
			
		||||
		swap(tmp);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		memmove(start(), str, len);
 | 
			
		||||
		set_size(len);
 | 
			
		||||
	}
 | 
			
		||||
	return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TiXmlString& TiXmlString::append(const char* str, size_type len)
 | 
			
		||||
{
 | 
			
		||||
	size_type newsize = length() + len;
 | 
			
		||||
	if (newsize > capacity())
 | 
			
		||||
	{
 | 
			
		||||
		reserve (newsize + capacity());
 | 
			
		||||
	}
 | 
			
		||||
	memmove(finish(), str, len);
 | 
			
		||||
	set_size(newsize);
 | 
			
		||||
	return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TiXmlString operator + (const TiXmlString & a, const TiXmlString & b)
 | 
			
		||||
{
 | 
			
		||||
	TiXmlString tmp;
 | 
			
		||||
	tmp.reserve(a.length() + b.length());
 | 
			
		||||
	tmp += a;
 | 
			
		||||
	tmp += b;
 | 
			
		||||
	return tmp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TiXmlString operator + (const TiXmlString & a, const char* b)
 | 
			
		||||
{
 | 
			
		||||
	TiXmlString tmp;
 | 
			
		||||
	TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) );
 | 
			
		||||
	tmp.reserve(a.length() + b_len);
 | 
			
		||||
	tmp += a;
 | 
			
		||||
	tmp.append(b, b_len);
 | 
			
		||||
	return tmp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TiXmlString operator + (const char* a, const TiXmlString & b)
 | 
			
		||||
{
 | 
			
		||||
	TiXmlString tmp;
 | 
			
		||||
	TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) );
 | 
			
		||||
	tmp.reserve(a_len + b.length());
 | 
			
		||||
	tmp.append(a, a_len);
 | 
			
		||||
	tmp += b;
 | 
			
		||||
	return tmp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif	// TIXML_USE_STL
 | 
			
		||||
@ -0,0 +1,319 @@
 | 
			
		||||
/*
 | 
			
		||||
www.sourceforge.net/projects/tinyxml
 | 
			
		||||
Original file by Yves Berquin.
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005.
 | 
			
		||||
 *
 | 
			
		||||
 * - completely rewritten. compact, clean, and fast implementation.
 | 
			
		||||
 * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems)
 | 
			
		||||
 * - fixed reserve() to work as per specification.
 | 
			
		||||
 * - fixed buggy compares operator==(), operator<(), and operator>()
 | 
			
		||||
 * - fixed operator+=() to take a const ref argument, following spec.
 | 
			
		||||
 * - added "copy" constructor with length, and most compare operators.
 | 
			
		||||
 * - added swap(), clear(), size(), capacity(), operator+().
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef TIXML_USE_STL
 | 
			
		||||
 | 
			
		||||
#ifndef TIXML_STRING_INCLUDED
 | 
			
		||||
#define TIXML_STRING_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
/*	The support for explicit isn't that universal, and it isn't really
 | 
			
		||||
	required - it is used to check that the TiXmlString class isn't incorrectly
 | 
			
		||||
	used. Be nice to old compilers and macro it here:
 | 
			
		||||
*/
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200 )
 | 
			
		||||
	// Microsoft visual studio, version 6 and higher.
 | 
			
		||||
	#define TIXML_EXPLICIT explicit
 | 
			
		||||
#elif defined(__GNUC__) && (__GNUC__ >= 3 )
 | 
			
		||||
	// GCC version 3 and higher.s
 | 
			
		||||
	#define TIXML_EXPLICIT explicit
 | 
			
		||||
#else
 | 
			
		||||
	#define TIXML_EXPLICIT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
   TiXmlString is an emulation of a subset of the std::string template.
 | 
			
		||||
   Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
 | 
			
		||||
   Only the member functions relevant to the TinyXML project have been implemented.
 | 
			
		||||
   The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
 | 
			
		||||
   a string and there's no more room, we allocate a buffer twice as big as we need.
 | 
			
		||||
*/
 | 
			
		||||
class TiXmlString
 | 
			
		||||
{
 | 
			
		||||
  public :
 | 
			
		||||
	// The size type used
 | 
			
		||||
  	typedef size_t size_type;
 | 
			
		||||
 | 
			
		||||
	// Error value for find primitive
 | 
			
		||||
	static const size_type npos; // = -1;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// TiXmlString empty constructor
 | 
			
		||||
	TiXmlString () : rep_(&nullrep_)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TiXmlString copy constructor
 | 
			
		||||
	TiXmlString ( const TiXmlString & copy) : rep_(0)
 | 
			
		||||
	{
 | 
			
		||||
		init(copy.length());
 | 
			
		||||
		memcpy(start(), copy.data(), length());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TiXmlString constructor, based on a string
 | 
			
		||||
	TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0)
 | 
			
		||||
	{
 | 
			
		||||
		init( static_cast<size_type>( strlen(copy) ));
 | 
			
		||||
		memcpy(start(), copy, length());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TiXmlString constructor, based on a string
 | 
			
		||||
	TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0)
 | 
			
		||||
	{
 | 
			
		||||
		init(len);
 | 
			
		||||
		memcpy(start(), str, len);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TiXmlString destructor
 | 
			
		||||
	~TiXmlString ()
 | 
			
		||||
	{
 | 
			
		||||
		quit();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// = operator
 | 
			
		||||
	TiXmlString& operator = (const char * copy)
 | 
			
		||||
	{
 | 
			
		||||
		return assign( copy, (size_type)strlen(copy));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// = operator
 | 
			
		||||
	TiXmlString& operator = (const TiXmlString & copy)
 | 
			
		||||
	{
 | 
			
		||||
		return assign(copy.start(), copy.length());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// += operator. Maps to append
 | 
			
		||||
	TiXmlString& operator += (const char * suffix)
 | 
			
		||||
	{
 | 
			
		||||
		return append(suffix, static_cast<size_type>( strlen(suffix) ));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// += operator. Maps to append
 | 
			
		||||
	TiXmlString& operator += (char single)
 | 
			
		||||
	{
 | 
			
		||||
		return append(&single, 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// += operator. Maps to append
 | 
			
		||||
	TiXmlString& operator += (const TiXmlString & suffix)
 | 
			
		||||
	{
 | 
			
		||||
		return append(suffix.data(), suffix.length());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// Convert a TiXmlString into a null-terminated char *
 | 
			
		||||
	const char * c_str () const { return rep_->str; }
 | 
			
		||||
 | 
			
		||||
	// Convert a TiXmlString into a char * (need not be null terminated).
 | 
			
		||||
	const char * data () const { return rep_->str; }
 | 
			
		||||
 | 
			
		||||
	// Return the length of a TiXmlString
 | 
			
		||||
	size_type length () const { return rep_->size; }
 | 
			
		||||
 | 
			
		||||
	// Alias for length()
 | 
			
		||||
	size_type size () const { return rep_->size; }
 | 
			
		||||
 | 
			
		||||
	// Checks if a TiXmlString is empty
 | 
			
		||||
	bool empty () const { return rep_->size == 0; }
 | 
			
		||||
 | 
			
		||||
	// Return capacity of string
 | 
			
		||||
	size_type capacity () const { return rep_->capacity; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// single char extraction
 | 
			
		||||
	const char& at (size_type index) const
 | 
			
		||||
	{
 | 
			
		||||
		assert( index < length() );
 | 
			
		||||
		return rep_->str[ index ];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// [] operator
 | 
			
		||||
	char& operator [] (size_type index) const
 | 
			
		||||
	{
 | 
			
		||||
		assert( index < length() );
 | 
			
		||||
		return rep_->str[ index ];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// find a char in a string. Return TiXmlString::npos if not found
 | 
			
		||||
	size_type find (char lookup) const
 | 
			
		||||
	{
 | 
			
		||||
		return find(lookup, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// find a char in a string from an offset. Return TiXmlString::npos if not found
 | 
			
		||||
	size_type find (char tofind, size_type offset) const
 | 
			
		||||
	{
 | 
			
		||||
		if (offset >= length()) return npos;
 | 
			
		||||
 | 
			
		||||
		for (const char* p = c_str() + offset; *p != '\0'; ++p)
 | 
			
		||||
		{
 | 
			
		||||
		   if (*p == tofind) return static_cast< size_type >( p - c_str() );
 | 
			
		||||
		}
 | 
			
		||||
		return npos;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void clear ()
 | 
			
		||||
	{
 | 
			
		||||
		//Lee:
 | 
			
		||||
		//The original was just too strange, though correct:
 | 
			
		||||
		//	TiXmlString().swap(*this);
 | 
			
		||||
		//Instead use the quit & re-init:
 | 
			
		||||
		quit();
 | 
			
		||||
		init(0,0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*	Function to reserve a big amount of data when we know we'll need it. Be aware that this
 | 
			
		||||
		function DOES NOT clear the content of the TiXmlString if any exists.
 | 
			
		||||
	*/
 | 
			
		||||
	void reserve (size_type cap);
 | 
			
		||||
 | 
			
		||||
	TiXmlString& assign (const char* str, size_type len);
 | 
			
		||||
 | 
			
		||||
	TiXmlString& append (const char* str, size_type len);
 | 
			
		||||
 | 
			
		||||
	void swap (TiXmlString& other)
 | 
			
		||||
	{
 | 
			
		||||
		Rep* r = rep_;
 | 
			
		||||
		rep_ = other.rep_;
 | 
			
		||||
		other.rep_ = r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
 | 
			
		||||
	void init(size_type sz) { init(sz, sz); }
 | 
			
		||||
	void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; }
 | 
			
		||||
	char* start() const { return rep_->str; }
 | 
			
		||||
	char* finish() const { return rep_->str + rep_->size; }
 | 
			
		||||
 | 
			
		||||
	struct Rep
 | 
			
		||||
	{
 | 
			
		||||
		size_type size, capacity;
 | 
			
		||||
		char str[1];
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	void init(size_type sz, size_type cap)
 | 
			
		||||
	{
 | 
			
		||||
		if (cap)
 | 
			
		||||
		{
 | 
			
		||||
			// Lee: the original form:
 | 
			
		||||
			//	rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));
 | 
			
		||||
			// doesn't work in some cases of new being overloaded. Switching
 | 
			
		||||
			// to the normal allocation, although use an 'int' for systems
 | 
			
		||||
			// that are overly picky about structure alignment.
 | 
			
		||||
			const size_type bytesNeeded = sizeof(Rep) + cap;
 | 
			
		||||
			const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); 
 | 
			
		||||
			rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] );
 | 
			
		||||
 | 
			
		||||
			rep_->str[ rep_->size = sz ] = '\0';
 | 
			
		||||
			rep_->capacity = cap;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			rep_ = &nullrep_;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void quit()
 | 
			
		||||
	{
 | 
			
		||||
		if (rep_ != &nullrep_)
 | 
			
		||||
		{
 | 
			
		||||
			// The rep_ is really an array of ints. (see the allocator, above).
 | 
			
		||||
			// Cast it back before delete, so the compiler won't incorrectly call destructors.
 | 
			
		||||
			delete [] ( reinterpret_cast<int*>( rep_ ) );
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Rep * rep_;
 | 
			
		||||
	static Rep nullrep_;
 | 
			
		||||
 | 
			
		||||
} ;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline bool operator == (const TiXmlString & a, const TiXmlString & b)
 | 
			
		||||
{
 | 
			
		||||
	return    ( a.length() == b.length() )				// optimization on some platforms
 | 
			
		||||
	       && ( strcmp(a.c_str(), b.c_str()) == 0 );	// actual compare
 | 
			
		||||
}
 | 
			
		||||
inline bool operator < (const TiXmlString & a, const TiXmlString & b)
 | 
			
		||||
{
 | 
			
		||||
	return strcmp(a.c_str(), b.c_str()) < 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); }
 | 
			
		||||
inline bool operator >  (const TiXmlString & a, const TiXmlString & b) { return b < a; }
 | 
			
		||||
inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); }
 | 
			
		||||
inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); }
 | 
			
		||||
 | 
			
		||||
inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; }
 | 
			
		||||
inline bool operator == (const char* a, const TiXmlString & b) { return b == a; }
 | 
			
		||||
inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); }
 | 
			
		||||
inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); }
 | 
			
		||||
 | 
			
		||||
TiXmlString operator + (const TiXmlString & a, const TiXmlString & b);
 | 
			
		||||
TiXmlString operator + (const TiXmlString & a, const char* b);
 | 
			
		||||
TiXmlString operator + (const char* a, const TiXmlString & b);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
   TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
 | 
			
		||||
   Only the operators that we need for TinyXML have been developped.
 | 
			
		||||
*/
 | 
			
		||||
class TiXmlOutStream : public TiXmlString
 | 
			
		||||
{
 | 
			
		||||
public :
 | 
			
		||||
 | 
			
		||||
	// TiXmlOutStream << operator.
 | 
			
		||||
	TiXmlOutStream & operator << (const TiXmlString & in)
 | 
			
		||||
	{
 | 
			
		||||
		*this += in;
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TiXmlOutStream << operator.
 | 
			
		||||
	TiXmlOutStream & operator << (const char * in)
 | 
			
		||||
	{
 | 
			
		||||
		*this += in;
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
} ;
 | 
			
		||||
 | 
			
		||||
#endif	// TIXML_STRING_INCLUDED
 | 
			
		||||
#endif	// TIXML_USE_STL
 | 
			
		||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								@ -0,0 +1,53 @@
 | 
			
		||||
/*
 | 
			
		||||
www.sourceforge.net/projects/tinyxml
 | 
			
		||||
Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
 | 
			
		||||
 | 
			
		||||
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 "tinyxml.h"
 | 
			
		||||
 | 
			
		||||
// The goal of the seperate error file is to make the first
 | 
			
		||||
// step towards localization. tinyxml (currently) only supports
 | 
			
		||||
// english error messages, but the could now be translated.
 | 
			
		||||
//
 | 
			
		||||
// It also cleans up the code a bit.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] =
 | 
			
		||||
{
 | 
			
		||||
	"No error",
 | 
			
		||||
	"Error",
 | 
			
		||||
	"Failed to open file",
 | 
			
		||||
	"Memory allocation failed.",
 | 
			
		||||
	"Error parsing Element.",
 | 
			
		||||
	"Failed to read Element name",
 | 
			
		||||
	"Error reading Element value.",
 | 
			
		||||
	"Error reading Attributes.",
 | 
			
		||||
	"Error: empty tag.",
 | 
			
		||||
	"Error reading end tag.",
 | 
			
		||||
	"Error parsing Unknown.",
 | 
			
		||||
	"Error parsing Comment.",
 | 
			
		||||
	"Error parsing Declaration.",
 | 
			
		||||
	"Error document empty.",
 | 
			
		||||
	"Error null (0) or unexpected EOF found in input stream.",
 | 
			
		||||
	"Error parsing CDATA.",
 | 
			
		||||
	"Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.",
 | 
			
		||||
};
 | 
			
		||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								@ -0,0 +1,553 @@
 | 
			
		||||
<?xml version="1.0" ?>
 | 
			
		||||
<DFExtractor>
 | 
			
		||||
<!-- USE A FIXED WIDTH FONT! -->
 | 
			
		||||
  <MemoryDescriptors>
 | 
			
		||||
       _____________________________________________
 | 
			
		||||
       |\'-._(   /                                 |
 | 
			
		||||
       | \  .'-._\                            ,   ,|
 | 
			
		||||
       |-.\'    .-;                         .'\`-' |
 | 
			
		||||
       |   \  .' (                       _.'   \   |
 | 
			
		||||
       |.--.\'   _)                   ;-;       \._|
 | 
			
		||||
       |    ` _\(_)/_                  \ `'-,_,-'\ |
 | 
			
		||||
       jgs____ /(O)\  _________________/____)_`-._\|
 | 
			
		||||
       |                                           |
 | 
			
		||||
       |         Old unsupported versions          |
 | 
			
		||||
       |------------------------------------------->
 | 
			
		||||
 | 
			
		||||
    <!--<Entry version="v0.27.176.38a" os="windows">
 | 
			
		||||
        <HexValue name="pe_timestamp">0x47B6FAC2</HexValue>
 | 
			
		||||
        <Address name="map_data">0x014A4EAC</Address>
 | 
			
		||||
        <Address name="x_count">0x014A4EC4</Address>
 | 
			
		||||
        <Address name="y_count">0x014A4EC8</Address>
 | 
			
		||||
        <Address name="z_count">0x014A4ECC</Address>
 | 
			
		||||
        <Offset name="type">0x005E</Offset>
 | 
			
		||||
        <Offset name="designation">0x0260</Offset>
 | 
			
		||||
        <Offset name="occupancy">0x0660</Offset>
 | 
			
		||||
    </Entry>
 | 
			
		||||
    <Entry version="v0.28.181.40c" os="windows">
 | 
			
		||||
        <HexValue name="pe_timestamp">0x48AD802B</HexValue>
 | 
			
		||||
        <Address name="map_data">0x015C3D60</Address>
 | 
			
		||||
        <Address name="x_count">0x015C3D78</Address>
 | 
			
		||||
        <Address name="y_count">0x015C3D7C</Address>
 | 
			
		||||
        <Address name="z_count">0x015C3D80</Address>
 | 
			
		||||
        <Offset name="type">0x0062</Offset>
 | 
			
		||||
        <Offset name="designation">0x0264</Offset>
 | 
			
		||||
        <Offset name="occupancy">0x0664</Offset>
 | 
			
		||||
    </Entry>-->
 | 
			
		||||
 | 
			
		||||
                    .,:rsr,
 | 
			
		||||
                  :2;,;r2A@@5
 | 
			
		||||
                  @2::s5A#@@@ @r.       .
 | 
			
		||||
                 sd;:riXA#@@ :@@@Gir;;AS9
 | 
			
		||||
                 Bs::sS3A#@2 @@#AhXirsS#;
 | 
			
		||||
                iHrLr5d#@@@ .@#95sr;;rie
 | 
			
		||||
                i*'    `*@3 @@A2sr;:;r#5
 | 
			
		||||
                :..:rll:    @@A5sr::r3@
 | 
			
		||||
               @Hr;iZ#@@@@   `:rr;;;;:
 | 
			
		||||
              S@r.;i2#@@@  @s.      ..
 | 
			
		||||
              @2::ri2A@@# B@G2ir:...5i
 | 
			
		||||
             :@r,r3X##@@  @G5sr:..,:A
 | 
			
		||||
            .@Ar;;rSB@@# H#2sr;,..,is
 | 
			
		||||
            .'       `* ,@ASs;:..,:B
 | 
			
		||||
                         ;rr;:,..,:.
 | 
			
		||||
                             `''' 
 | 
			
		||||
                  W I N D O W S
 | 
			
		||||
                       and
 | 
			
		||||
                     W I N E
 | 
			
		||||
 | 
			
		||||
    <Entry version="v0.28.181.40d" os="windows" id="40dwin">
 | 
			
		||||
        <!-- identification -->
 | 
			
		||||
        <HexValue name="pe_timestamp">0x48C330DF</HexValue>
 | 
			
		||||
        <String name="md5">2c686c26307dcccd7c36cc79737ebe4f</String>
 | 
			
		||||
 | 
			
		||||
        <!-- map data -->
 | 
			
		||||
        <Address name="map_data">0x015C4D58</Address>
 | 
			
		||||
        <Address name="constructions">0x0156F8B0</Address>
 | 
			
		||||
        <Address name="buildings">0x015838a0</Address>
 | 
			
		||||
        <Address name="vegetation">0x01587A24</Address>
 | 
			
		||||
 | 
			
		||||
        <!-- size of the map -->
 | 
			
		||||
        <Address name="x_count">0x015C4D70</Address>
 | 
			
		||||
        <Address name="y_count">0x015C4D74</Address>
 | 
			
		||||
        <Address name="z_count">0x015C4D78</Address>
 | 
			
		||||
 | 
			
		||||
        <!-- position of the map in world coords -->
 | 
			
		||||
        <Address name="region_x">0x015C4D88</Address>
 | 
			
		||||
        <Address name="region_y">0x015C4D8C</Address>
 | 
			
		||||
        <Address name="region_z">0x015C4D90</Address>
 | 
			
		||||
 | 
			
		||||
        <!-- map block offsets -->
 | 
			
		||||
        <Offset name="v_vein">0x08</Offset>
 | 
			
		||||
        <HexValue name="v_vein_size">0x2C</HexValue>
 | 
			
		||||
        <Offset name="type">0x0062</Offset>
 | 
			
		||||
        <Offset name="designation">0x0264</Offset>
 | 
			
		||||
        <Offset name="occupancy">0x0664</Offset>
 | 
			
		||||
        <Offset name="biome_stuffs">0x1D64</Offset>
 | 
			
		||||
 | 
			
		||||
        <!-- tree and shrub offsets -->
 | 
			
		||||
        <Offset name="tree_desc_offset">0x70</Offset>
 | 
			
		||||
 | 
			
		||||
        <!-- the world and its offsets -->
 | 
			
		||||
        <Address name="world">0x015C6388</Address>
 | 
			
		||||
        <Offset name="world_size_x">0x84</Offset>
 | 
			
		||||
        <Offset name="world_size_y">0x86</Offset>
 | 
			
		||||
        <Offset name="w_geoblocks">0x684</Offset>
 | 
			
		||||
        <Offset name="w_regions_arr">0x6B4</Offset>
 | 
			
		||||
 | 
			
		||||
        <!-- values for the region structure -->
 | 
			
		||||
        <HexValue name="region_size">0x5C</HexValue>
 | 
			
		||||
        <Offset name="region_geo_index_off">0x58</Offset>
 | 
			
		||||
 | 
			
		||||
        <!-- geoblock offset(s?) -->
 | 
			
		||||
        <Offset name="geolayer_geoblock_offset">0x4</Offset>
 | 
			
		||||
 | 
			
		||||
        <!-- matgloss vectors -->
 | 
			
		||||
        <Address name="matgloss">0x015C6D70</Address>
 | 
			
		||||
        <HexValue name="matgloss_skip">0x10</HexValue>
 | 
			
		||||
 | 
			
		||||
        <!-- only stone and metal have color loaded... -->
 | 
			
		||||
        <Offset name="matgloss_stone_color">0x84</Offset>
 | 
			
		||||
        <Offset name="matgloss_metal_color">0x60</Offset>
 | 
			
		||||
 | 
			
		||||
        <VTable>
 | 
			
		||||
            <class vtable="0x00979fe4" name="stockpile" />
 | 
			
		||||
            <class vtable="0x00979d34" name="zone" />
 | 
			
		||||
            <class vtable="0x0097e7ec" name="construction_blueprint" />
 | 
			
		||||
            <!-- BUILDINGS -->
 | 
			
		||||
            <class vtable="0x0097e3cc" name="wagon"/>
 | 
			
		||||
            <class vtable="0x0097b3ac" name="armor_stand"/>
 | 
			
		||||
            <class vtable="0x0097d1ec" name="bed"/>
 | 
			
		||||
            <class vtable="0x0097d4ac" name="seat"/>
 | 
			
		||||
            <class vtable="0x0097d76c" name="burial_receptacle"/>
 | 
			
		||||
            <class vtable="0x0097b50c" name="door"/>
 | 
			
		||||
            <class vtable="0x0097b92c" name="floodgate"/>
 | 
			
		||||
            <class vtable="0x0097b66c" name="floor_hatch"/>
 | 
			
		||||
            <class vtable="0x0097ba8c" name="wall_grate"/>
 | 
			
		||||
            <class vtable="0x0097bbec" name="floor_grate"/>
 | 
			
		||||
            <class vtable="0x0097bd4c" name="vertical_bars"/>
 | 
			
		||||
            <class vtable="0x0097beac" name="floor_bars"/>
 | 
			
		||||
            <class vtable="0x0097b0ec" name="cabinet"/>
 | 
			
		||||
            <class vtable="0x0097af8c" name="container"/>
 | 
			
		||||
            <multiclass vtable="0x0097e10c" name="workshop" typeoffset="0xC8">
 | 
			
		||||
                <class name="alchemists_laboratory" type="0x0"/>
 | 
			
		||||
                <class name="carpenters_workshop"   type="0x1"/>
 | 
			
		||||
                <class name="farmers_workshop"      type="0x2"/>
 | 
			
		||||
                <class name="masons_workshop"       type="0x3"/>
 | 
			
		||||
                <class name="craftdwarfs_workshop"  type="0x4"/>
 | 
			
		||||
                <class name="jewelers_workshop"     type="0x5"/>
 | 
			
		||||
                <class name="metalsmiths_workshop"  type="0x6"/>
 | 
			
		||||
                <class name="magma_forge"           type="0x7"/>
 | 
			
		||||
                <class name="bowyers_workshop"      type="0x8"/>
 | 
			
		||||
                <class name="mechanics_workshop"    type="0x9"/>
 | 
			
		||||
                <class name="siege_workshop"        type="0xA"/>
 | 
			
		||||
                <class name="butchers_shop"         type="0xB"/>
 | 
			
		||||
                <class name="leather_works"         type="0xC"/>
 | 
			
		||||
                <class name="tanners_shop"          type="0xD"/>
 | 
			
		||||
                <class name="clothiers_shop"        type="0xE"/>
 | 
			
		||||
                <class name="fishery"               type="0xF"/>
 | 
			
		||||
                <class name="still"                 type="0x10"/>
 | 
			
		||||
                <class name="loom"                  type="0x11"/>
 | 
			
		||||
                <class name="quern"                 type="0x12"/>
 | 
			
		||||
                <class name="kennels"               type="0x13"/>
 | 
			
		||||
                <class name="kitchen"               type="0x14"/>
 | 
			
		||||
                <class name="ashery"                type="0x15"/>
 | 
			
		||||
                <class name="dyers_shop"            type="0x16"/>
 | 
			
		||||
                <class name="millstone"             type="0x17"/>
 | 
			
		||||
            </multiclass>
 | 
			
		||||
            <class vtable="0x0097dcec" name="farm_plot"/>
 | 
			
		||||
            <class vtable="0x0097b24c" name="weapon_rack"/>
 | 
			
		||||
            <class vtable="0x0097d8cc" name="statue"/>
 | 
			
		||||
            <class vtable="0x0097d34c" name="table"/>
 | 
			
		||||
            <class vtable="0x0097e68c" name="paved_road"/>
 | 
			
		||||
            <class vtable="0x0097b7cc" name="bridge"/>
 | 
			
		||||
            <class vtable="0x00979e84" name="well"/>
 | 
			
		||||
            <multiclass vtable="0x0097d08c" name="siege engine" typeoffset="0xC8">
 | 
			
		||||
                <class name="catapult"              type="0x0"/>
 | 
			
		||||
                <class name="ballista"              type="0x1"/>
 | 
			
		||||
            </multiclass>
 | 
			
		||||
            <multiclass vtable="0x0097dfac" name="furnace" typeoffset="0xDA">
 | 
			
		||||
                <class name="wood_furnace"          type="0x0"/>
 | 
			
		||||
                <class name="smelter"               type="0x1"/>
 | 
			
		||||
                <class name="glass_furnace"         type="0x2"/>
 | 
			
		||||
                <class name="kiln"                  type="0x3"/>
 | 
			
		||||
                <class name="magma_smelter"         type="0x4"/>
 | 
			
		||||
                <class name="magma_glass_furnace"   type="0x5"/>
 | 
			
		||||
                <class name="magma_kiln"            type="0x6"/>
 | 
			
		||||
            </multiclass>
 | 
			
		||||
            <class vtable="0x0097db8c" name="glass_window"/>
 | 
			
		||||
            <class vtable="0x0097da2c" name="gem_window"/>
 | 
			
		||||
            <class vtable="0x0097e26c" name="trade_depot"/>
 | 
			
		||||
            <multiclass vtable="0x0097c00c" name="mechanism" typeoffset="0xC8">
 | 
			
		||||
                <class name="lever"                 type="0x0"/>
 | 
			
		||||
                <class name="pressure_plate"        type="0x1"/>
 | 
			
		||||
                <class name="cage_trap"             type="0x2"/>
 | 
			
		||||
                <class name="stonefall_trap"        type="0x3"/>
 | 
			
		||||
                <class name="weapon_trap"           type="0x4"/>
 | 
			
		||||
            </multiclass>
 | 
			
		||||
            <class vtable="0x0097c6ec" name="spike" />
 | 
			
		||||
            <class vtable="0x0097de4c" name="animal_trap" />
 | 
			
		||||
            <class vtable="0x0097c9ac" name="screw_pump"/>
 | 
			
		||||
            <class vtable="0x0097cb0c" name="water_wheel"/>
 | 
			
		||||
            <class vtable="0x0097cc6c" name="windmill"/>
 | 
			
		||||
            <class vtable="0x0097c16c" name="gear_assembly"/>
 | 
			
		||||
            <class vtable="0x0097c2cc" name="horizontal_axle"/>
 | 
			
		||||
            <class vtable="0x0097c42c" name="vertical_axle"/>
 | 
			
		||||
            <class vtable="0x0097c58c" name="support"/>
 | 
			
		||||
            <class vtable="0x0097cf2c" name="cage"/>
 | 
			
		||||
            <class vtable="0x0097c84c" name="archery_target"/>
 | 
			
		||||
            <class vtable="0x0097cdcc" name="restraint"/>
 | 
			
		||||
        </VTable>
 | 
			
		||||
    </Entry>
 | 
			
		||||
    <!-- Windows 40d## sub-versions, should inherit only vtable from 40d -->
 | 
			
		||||
    <Entry version="v0.28.181.40d9" os="windows" id="40d9win" base="40dwin">
 | 
			
		||||
        <!-- identification -->
 | 
			
		||||
        <HexValue name="pe_timestamp">0x4967C2E0</HexValue>
 | 
			
		||||
        <String name="md5">aea5a207b8b1cda942502f97a429f6c3</String>
 | 
			
		||||
 | 
			
		||||
        <!-- map data -->
 | 
			
		||||
        <Address name="map_data">0x01531EC0</Address>
 | 
			
		||||
        <Address name="constructions">0x014da5e0</Address>
 | 
			
		||||
        <Address name="buildings">0x014ee978</Address>
 | 
			
		||||
        <Address name="vegetation">0x014F4B4C</Address>
 | 
			
		||||
        <!-- tree and shrub offsets -->
 | 
			
		||||
        <Offset name="tree_desc_offset">0x70</Offset>
 | 
			
		||||
 | 
			
		||||
        <!-- size of the map -->
 | 
			
		||||
        <Address name="x_count">0x01531EE0</Address>
 | 
			
		||||
        <Address name="y_count">0x01531EE4</Address>
 | 
			
		||||
        <Address name="z_count">0x01531EE8</Address>
 | 
			
		||||
 | 
			
		||||
        <!-- position of the map in world coords -->
 | 
			
		||||
        <Address name="region_x">0x01531EF8</Address>
 | 
			
		||||
        <Address name="region_y">0x01531EFC</Address>
 | 
			
		||||
        <Address name="region_z">0x01531F00</Address>
 | 
			
		||||
 | 
			
		||||
        <!-- map block offsets -->
 | 
			
		||||
        <Offset name="v_vein">0x10</Offset>
 | 
			
		||||
        <HexValue name="v_vein_size">0x2C</HexValue>
 | 
			
		||||
        <Offset name="type">0x0082</Offset>
 | 
			
		||||
        <Offset name="designation">0x0284</Offset>
 | 
			
		||||
        <Offset name="occupancy">0x0684</Offset>
 | 
			
		||||
        <Offset name="biome_stuffs">0x1D84</Offset>
 | 
			
		||||
 | 
			
		||||
        <!-- the world and its offsets -->
 | 
			
		||||
        <Address name="world">0x015334F8</Address>
 | 
			
		||||
        <Offset name="world_size_x">0x84</Offset>
 | 
			
		||||
        <Offset name="world_size_y">0x86</Offset>
 | 
			
		||||
        <Offset name="w_geoblocks">0x75C</Offset>
 | 
			
		||||
        <Offset name="w_regions_arr">0x79C</Offset>
 | 
			
		||||
 | 
			
		||||
        <!-- values for the region structure -->
 | 
			
		||||
        <HexValue name="region_size">0x64</HexValue>
 | 
			
		||||
        <Offset name="region_geo_index_off">0x60</Offset>
 | 
			
		||||
 | 
			
		||||
        <!-- geoblock offset(s?) -->
 | 
			
		||||
        <Offset name="geolayer_geoblock_offset">0xC</Offset>
 | 
			
		||||
 | 
			
		||||
        <!-- matgloss vectors -->
 | 
			
		||||
        <Address name="matgloss">0x01534030</Address>
 | 
			
		||||
        <HexValue name="matgloss_skip">0x18</HexValue>
 | 
			
		||||
 | 
			
		||||
        <!-- door: 0x8ea1e4 -->
 | 
			
		||||
        <VTable rebase="-0x91328">
 | 
			
		||||
            <!-- Isn't it just /lovely/ how simple things become?
 | 
			
		||||
                When you specify only typeoffset, nothing else is touched. Same for vtable. -->
 | 
			
		||||
            <multiclass name="workshop" typeoffset="0x100" />
 | 
			
		||||
            <multiclass name="siege engine" typeoffset="0x100" />
 | 
			
		||||
            <multiclass name="furnace" typeoffset="0x11A" />
 | 
			
		||||
            <multiclass name="mechanism" typeoffset="0x100" />
 | 
			
		||||
        </VTable>
 | 
			
		||||
    </Entry>
 | 
			
		||||
    <Entry version="v0.28.181.40d11" os="windows" rebase="0x2d388" id="40d11win" base="40d9win">
 | 
			
		||||
        <!-- identification -->
 | 
			
		||||
        <HexValue name="pe_timestamp">0x49C82D3F</HexValue>
 | 
			
		||||
        <String name="md5">6f81231b845e9c9dc29aaf57705ccc7c</String>
 | 
			
		||||
        <!-- door: 0x8e91e4 -->
 | 
			
		||||
        <VTable rebase="-0x1000" />
 | 
			
		||||
    </Entry>
 | 
			
		||||
    <Entry version="v0.28.181.40d12" os="windows" id="40d12win" base="40d11win">
 | 
			
		||||
        <!-- identification -->
 | 
			
		||||
        <HexValue name="pe_timestamp">0x4A3CCB7F</HexValue>
 | 
			
		||||
        <String name="md5">6ea1de36af8e1666bd6478736e298c4c</String>
 | 
			
		||||
 | 
			
		||||
        <!-- map data -->
 | 
			
		||||
        <Address name="map_data">0x015FACCC</Address>
 | 
			
		||||
        <Address name="constructions">0x015A33B8</Address>
 | 
			
		||||
        <Address name="buildings">0x015B7750</Address>
 | 
			
		||||
        <Address name="vegetation">0x015BD924</Address>
 | 
			
		||||
 | 
			
		||||
        <!-- size of the map -->
 | 
			
		||||
        <Address name="x_count">0x015FACEC</Address>
 | 
			
		||||
        <Address name="y_count">0x015FACF0</Address>
 | 
			
		||||
        <Address name="z_count">0x015FACF4</Address>
 | 
			
		||||
 | 
			
		||||
        <!-- position of the map in world coords -->
 | 
			
		||||
        <Address name="region_x">0x015FAD04</Address>
 | 
			
		||||
        <Address name="region_y">0x015FAD08</Address>
 | 
			
		||||
        <Address name="region_z">0x015FAD0C</Address>
 | 
			
		||||
 | 
			
		||||
        <!-- the world and its offsets -->
 | 
			
		||||
        <Address name="world">0x015FC304</Address>
 | 
			
		||||
        <!-- matgloss vectors -->
 | 
			
		||||
        <Address name="matgloss">0x015FCE3C</Address>
 | 
			
		||||
        <!-- door: 0x8db5e4 -->
 | 
			
		||||
        <VTable rebase="-0xDC00" />
 | 
			
		||||
    </Entry>
 | 
			
		||||
    <Entry version="v0.28.181.40d13" os="windows" id="40d13win" base="40d12win" rebase="0x5090">
 | 
			
		||||
        <!-- identification -->
 | 
			
		||||
        <HexValue name="pe_timestamp">0x4A51C26E</HexValue>
 | 
			
		||||
        <String name="md5">04a8d8ce311d8ac75e4241bef68d3147</String>
 | 
			
		||||
        <!-- map_data = 0x015FFD5C -->
 | 
			
		||||
        <!-- door: 0x8df5ec -->
 | 
			
		||||
        <VTable rebase="0x4008" />
 | 
			
		||||
    </Entry>
 | 
			
		||||
    <Entry version="v0.28.181.40d14" os="windows" id="40d14win" base="40d13win" rebase="0x2010">
 | 
			
		||||
        <!-- identification -->
 | 
			
		||||
        <HexValue name="pe_timestamp">0x4A8623D2</HexValue>
 | 
			
		||||
        <String name="md5">781a2e51be4056a7320108f8f0df8a13</String>
 | 
			
		||||
        <!-- map_data = 0x01601D6C -->
 | 
			
		||||
        <!-- door: 0x8e15dc -->
 | 
			
		||||
        <VTable rebase="0x1FF0" />
 | 
			
		||||
    </Entry>
 | 
			
		||||
    <Entry version="v0.28.181.40d15" os="windows" id="40d15win" base="40d14win" rebase="0x18">
 | 
			
		||||
        <!-- identification -->
 | 
			
		||||
        <HexValue name="pe_timestamp">0x4A9A6090</HexValue>
 | 
			
		||||
        <String name="md5">12cc4a3dbb6e6dfd7bc7aee458b9471a</String>
 | 
			
		||||
        <!-- map_data = 0x01601D84 -->
 | 
			
		||||
        <!-- door: 0x8e15d4 -->
 | 
			
		||||
        <VTable rebase="-0x8" />
 | 
			
		||||
    </Entry>
 | 
			
		||||
    <Entry version="v0.28.181.40d16" os="windows" base="40d15win">
 | 
			
		||||
        <!-- identification -->
 | 
			
		||||
        <HexValue name="pe_timestamp">0x4A9B1A72</HexValue>
 | 
			
		||||
        <String name="md5">59ab29021aca9f3c66b1ab102fb3ceea</String>
 | 
			
		||||
        <!-- map_data = 0x01601D84 -->
 | 
			
		||||
        <!-- door: 0x8e15d4, no VTable rebase needed -->
 | 
			
		||||
    </Entry>
 | 
			
		||||
 | 
			
		||||
                            .-"""-.
 | 
			
		||||
                           '       \
 | 
			
		||||
                          |,.  ,-.  |
 | 
			
		||||
                          |()L( ()| |
 | 
			
		||||
                          |,'  `".| |
 | 
			
		||||
                          |.___.',| `
 | 
			
		||||
                         .j `--"' `  `.
 | 
			
		||||
                        / '        '   \
 | 
			
		||||
                       / /          `   `.
 | 
			
		||||
                      / /            `    .
 | 
			
		||||
                     / /              l   |
 | 
			
		||||
                    . ,   L I N U X   |   |
 | 
			
		||||
                    ,"`.             .|   |
 | 
			
		||||
                 _.'   ``.          | `..-'l
 | 
			
		||||
                |       `.`,        |      `.
 | 
			
		||||
                |         `.    __.j         )
 | 
			
		||||
                |__        |--""___|      ,-'
 | 
			
		||||
                   `"--...,+""""   `._,.-' 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <Entry version="v0.28.181.40d9" os="linux" id="40d9lin">
 | 
			
		||||
        <!-- identification -->
 | 
			
		||||
        <String name="md5">992afd73855e787860277f53d18afcbb</String>
 | 
			
		||||
 | 
			
		||||
        <!-- map data -->
 | 
			
		||||
        <Address name="map_data">0x09372FC0</Address>
 | 
			
		||||
        <Address name="constructions">0x0931ED38</Address>
 | 
			
		||||
        <!-- srsly, WTF? -->
 | 
			
		||||
        <!--<Address name="buildings">0x09332B54</Address>-->
 | 
			
		||||
        <Address name="buildings">0x09332B60</Address>
 | 
			
		||||
        <!--<Address name="buildings">0x09332B90</Address>-->
 | 
			
		||||
        <!--<Address name="buildings">0x09332C80</Address>-->
 | 
			
		||||
        <!--<Address name="buildings">0x09332EF0</Address>-->
 | 
			
		||||
        <Address name="vegetation">0x09335CB0</Address>
 | 
			
		||||
        <!-- tree and shrub offsets -->
 | 
			
		||||
        <Offset name="tree_desc_offset">0x40</Offset>
 | 
			
		||||
 | 
			
		||||
        <!-- size of the map -->
 | 
			
		||||
        <Address name="x_count">0x09372FD4</Address>
 | 
			
		||||
        <Address name="y_count">0x09372FD8</Address>
 | 
			
		||||
        <Address name="z_count">0x09372FDC</Address>
 | 
			
		||||
 | 
			
		||||
        <!-- position of the map in world coords -->
 | 
			
		||||
        <Address name="region_x">0x09372FEC</Address>
 | 
			
		||||
        <Address name="region_y">0x09372FF0</Address>
 | 
			
		||||
        <Address name="region_z">0x09372FF4</Address>
 | 
			
		||||
 | 
			
		||||
        <!-- map block offsets -->
 | 
			
		||||
        <Offset name="v_vein">0x08</Offset>
 | 
			
		||||
        <HexValue name="v_vein_size">0x2C</HexValue>
 | 
			
		||||
        <Offset name="type">0x0052</Offset>
 | 
			
		||||
        <Offset name="designation">0x0254</Offset>
 | 
			
		||||
        <Offset name="occupancy">0x0654</Offset>
 | 
			
		||||
        <Offset name="biome_stuffs">0x1D54</Offset>
 | 
			
		||||
 | 
			
		||||
        <!-- the world and its offsets -->
 | 
			
		||||
        <Address name="world">0x093745EC</Address>
 | 
			
		||||
        <Offset name="world_size_x">0x54</Offset>
 | 
			
		||||
        <Offset name="world_size_y">0x56</Offset>
 | 
			
		||||
        <Offset name="w_geoblocks">0x5A4</Offset>
 | 
			
		||||
        <Offset name="w_regions_arr">0x5C8</Offset>
 | 
			
		||||
 | 
			
		||||
        <!-- values for the region structure -->
 | 
			
		||||
        <HexValue name="region_size">0x58</HexValue>
 | 
			
		||||
        <Offset name="region_geo_index_off">0x54</Offset>
 | 
			
		||||
 | 
			
		||||
        <!-- geoblock offset(s?) -->
 | 
			
		||||
        <Offset name="geolayer_geoblock_offset">0x4</Offset>
 | 
			
		||||
 | 
			
		||||
        <!-- matgloss vectors -->
 | 
			
		||||
        <Address name="matgloss">0x9374E88</Address>
 | 
			
		||||
        <HexValue name="matgloss_skip">0xC</HexValue>
 | 
			
		||||
        <VTable>
 | 
			
		||||
            <class vtable="0x087981a8" name="stockpile" />
 | 
			
		||||
            <class vtable="0x08799e08" name="zone" />
 | 
			
		||||
            <class vtable="0x08797448" name="construction_blueprint" />
 | 
			
		||||
            <!-- BUILDINGS -->
 | 
			
		||||
            <class vtable="0x0879a0e8" name="wagon"/>
 | 
			
		||||
            <class vtable="0x08798a88" name="armor_stand"/>
 | 
			
		||||
            <class vtable="0x08798908" name="bed"/>
 | 
			
		||||
            <class vtable="0x08799088" name="seat"/>
 | 
			
		||||
            <class vtable="0x08798028" name="burial_receptacle"/>
 | 
			
		||||
            <class vtable="0x0879a868" name="door"/>
 | 
			
		||||
            <class vtable="0x0879b168" name="floodgate"/>
 | 
			
		||||
            <class vtable="0x0879a6e8" name="floor_hatch"/>
 | 
			
		||||
            <class vtable="0x0879ae68" name="wall_grate"/>
 | 
			
		||||
            <class vtable="0x0879afe8" name="floor_grate"/>
 | 
			
		||||
            <class vtable="0x0879ace8" name="vertical_bars"/>
 | 
			
		||||
            <class vtable="0x0879ab68" name="floor_bars"/>
 | 
			
		||||
            <class vtable="0x0879a568" name="cabinet"/>
 | 
			
		||||
            <class vtable="0x0879a3e8" name="container"/>
 | 
			
		||||
            <multiclass vtable="0x08799688" name="workshop" typeoffset="0xAC">
 | 
			
		||||
                <class name="alchemists_laboratory" type="0x0"/>
 | 
			
		||||
                <class name="carpenters_workshop"   type="0x1"/>
 | 
			
		||||
                <class name="farmers_workshop"      type="0x2"/>
 | 
			
		||||
                <class name="masons_workshop"       type="0x3"/>
 | 
			
		||||
                <class name="craftdwarfs_workshop"  type="0x4"/>
 | 
			
		||||
                <class name="jewelers_workshop"     type="0x5"/>
 | 
			
		||||
                <class name="metalsmiths_workshop"  type="0x6"/>
 | 
			
		||||
                <class name="magma_forge"           type="0x7"/>
 | 
			
		||||
                <class name="bowyers_workshop"      type="0x8"/>
 | 
			
		||||
                <class name="mechanics_workshop"    type="0x9"/>
 | 
			
		||||
                <class name="siege_workshop"        type="0xA"/>
 | 
			
		||||
                <class name="butchers_shop"         type="0xB"/>
 | 
			
		||||
                <class name="leather_works"         type="0xC"/>
 | 
			
		||||
                <class name="tanners_shop"          type="0xD"/>
 | 
			
		||||
                <class name="clothiers_shop"        type="0xE"/>
 | 
			
		||||
                <class name="fishery"               type="0xF"/>
 | 
			
		||||
                <class name="still"                 type="0x10"/>
 | 
			
		||||
                <class name="loom"                  type="0x11"/>
 | 
			
		||||
                <class name="quern"                 type="0x12"/>
 | 
			
		||||
                <class name="kennels"               type="0x13"/>
 | 
			
		||||
                <class name="kitchen"               type="0x14"/>
 | 
			
		||||
                <class name="ashery"                type="0x15"/>
 | 
			
		||||
                <class name="dyers_shop"            type="0x16"/>
 | 
			
		||||
                <class name="millstone"             type="0x17"/>
 | 
			
		||||
            </multiclass>
 | 
			
		||||
            <class vtable="0x08799c88" name="farm_plot"/>
 | 
			
		||||
            <class vtable="0x08798c08" name="weapon_rack"/>
 | 
			
		||||
            <class vtable="0x08798488" name="statue"/>
 | 
			
		||||
            <class vtable="0x08798d88" name="table"/>
 | 
			
		||||
            <class vtable="0x08797ea8" name="paved_road"/>
 | 
			
		||||
            <class vtable="0x0879a9e8" name="bridge"/>
 | 
			
		||||
            <class vtable="0x08798608" name="well"/>
 | 
			
		||||
            <multiclass vtable="0x8799808" name="siege engine" typeoffset="0xAC">
 | 
			
		||||
                <class name="catapult"              type="0x0"/>
 | 
			
		||||
                <class name="ballista"              type="0x1"/>
 | 
			
		||||
            </multiclass>
 | 
			
		||||
            <multiclass vtable="0x08799b08" name="furnace" typeoffset="0xBA">
 | 
			
		||||
                <class name="wood_furnace"          type="0x0"/>
 | 
			
		||||
                <class name="smelter"               type="0x1"/>
 | 
			
		||||
                <class name="glass_furnace"         type="0x2"/>
 | 
			
		||||
                <class name="kiln"                  type="0x3"/>
 | 
			
		||||
                <class name="magma_smelter"         type="0x4"/>
 | 
			
		||||
                <class name="magma_glass_furnace"   type="0x5"/>
 | 
			
		||||
                <class name="magma_kiln"            type="0x6"/>
 | 
			
		||||
            </multiclass>
 | 
			
		||||
            <class vtable="0x0879bae8" name="glass_window"/>
 | 
			
		||||
            <class vtable="0x0879b948" name="gem_window"/>
 | 
			
		||||
            <class vtable="0x08799f68" name="trade_depot"/>
 | 
			
		||||
            <multiclass vtable="0x08799988" name="mechanism" typeoffset="0xAC">
 | 
			
		||||
                <class name="lever"                 type="0x0"/>
 | 
			
		||||
                <class name="pressure_plate"        type="0x1"/>
 | 
			
		||||
                <class name="cage_trap"             type="0x2"/>
 | 
			
		||||
                <class name="stonefall_trap"        type="0x3"/>
 | 
			
		||||
                <class name="weapon_trap"           type="0x4"/>
 | 
			
		||||
            </multiclass>
 | 
			
		||||
            <class vtable="0x08799208" name="spike" />
 | 
			
		||||
            <class vtable="0x08798f08" name="animal_trap" />
 | 
			
		||||
            <class vtable="0x08796cc8" name="screw_pump"/>
 | 
			
		||||
            <class vtable="0x08796fc8" name="water_wheel"/>
 | 
			
		||||
            <class vtable="0x08796e48" name="windmill"/>
 | 
			
		||||
            <class vtable="0x087978a8" name="gear_assembly"/>
 | 
			
		||||
            <class vtable="0x08797148" name="horizontal_axle"/>
 | 
			
		||||
            <class vtable="0x087972c8" name="vertical_axle"/>
 | 
			
		||||
            <class vtable="0x08799388" name="support"/>
 | 
			
		||||
            <class vtable="0x08797a28" name="cage"/>
 | 
			
		||||
            <class vtable="0x08799508" name="archery_target"/>
 | 
			
		||||
            <class vtable="0x08797ba8" name="restraint"/>
 | 
			
		||||
        </VTable>
 | 
			
		||||
    </Entry>
 | 
			
		||||
    <Entry version="v0.28.181.40d11" os="linux" base="40d9lin" rebase="-0x73820">
 | 
			
		||||
        <!-- identification -->
 | 
			
		||||
        <String name="md5">fb8ecac8a12af5d0d7b1707078985d0d</String>
 | 
			
		||||
        <!--TODO: <Address name="notes">0x092ab244</Address>-->
 | 
			
		||||
        <VTable rebase="-0x5e360" />
 | 
			
		||||
    </Entry>
 | 
			
		||||
    <!-- re-specified addresses here, offsets and hexvals remain same -->
 | 
			
		||||
    <Entry version="v0.28.181.40d12" os="linux" base="40d9lin" id="40d12lin">
 | 
			
		||||
        <!-- identification -->
 | 
			
		||||
        <String name="md5">4367c59934cbcf14f43fd3af6444c455</String>
 | 
			
		||||
 | 
			
		||||
        <!-- map data -->
 | 
			
		||||
        <Address name="map_data">0x08F95BBC</Address>
 | 
			
		||||
        <Address name="constructions">0x08F41918</Address>
 | 
			
		||||
        <Address name="buildings">0x08F55740</Address>
 | 
			
		||||
        <Address name="vegetation">0x08F58890</Address>
 | 
			
		||||
 | 
			
		||||
        <!-- size of the map -->
 | 
			
		||||
        <Address name="x_count">0x08F95BD0</Address>
 | 
			
		||||
        <Address name="y_count">0x08F95BD4</Address>
 | 
			
		||||
        <Address name="z_count">0x08F95BD8</Address>
 | 
			
		||||
 | 
			
		||||
        <!-- position of the map in world coords -->
 | 
			
		||||
        <Address name="region_x">0x08F95BE8</Address>
 | 
			
		||||
        <Address name="region_y">0x08F95BEC</Address>
 | 
			
		||||
        <Address name="region_z">0x08F95BF0</Address>
 | 
			
		||||
 | 
			
		||||
        <!-- the world and its offsets -->
 | 
			
		||||
        <Address name="world">0x08F971E8</Address>
 | 
			
		||||
 | 
			
		||||
        <!-- matgloss vectors -->
 | 
			
		||||
        <Address name="matgloss">0x08F97A84</Address>
 | 
			
		||||
        <VTable rebase="-0xd6f00" />
 | 
			
		||||
        <!--<class vtable="0x086C3968" name="door"/>-->
 | 
			
		||||
    </Entry>
 | 
			
		||||
    <Entry version="v0.28.181.40d13" os="linux" id="40d13lin" base="40d12lin" rebase="0x5020">
 | 
			
		||||
        <!-- identification -->
 | 
			
		||||
        <String name="md5">2f3cb9d720e9fe8844c02c72a2b20bbd</String>
 | 
			
		||||
        <!-- map_data = 0x8F9ABDC -->
 | 
			
		||||
        <VTable rebase="0x3A00" />
 | 
			
		||||
        <!--<class vtable="0x086C7368" name="door"/>-->
 | 
			
		||||
    </Entry>
 | 
			
		||||
    <Entry version="v0.28.181.40d14" os="linux" id="40d14lin" base="40d13lin">
 | 
			
		||||
        <!-- identification -->
 | 
			
		||||
        <String name="md5">dab3ce6bc074529706a1e5fe1273108c</String>
 | 
			
		||||
        <!-- map_data = 0x8F9ABDC -->
 | 
			
		||||
        <VTable rebase="0x300" />
 | 
			
		||||
        <!--<class vtable="0x086C7668" name="door"/>-->
 | 
			
		||||
    </Entry>
 | 
			
		||||
    <Entry version="v0.28.181.40d15" os="linux" id="40d15lin" base="40d14lin">
 | 
			
		||||
        <!-- identification -->
 | 
			
		||||
        <String name="md5">4f55a1dcc326786271f221de23c425b5</String>
 | 
			
		||||
        <!-- map_data = 0x8F9ABDC -->
 | 
			
		||||
        <VTable rebase="0x260" />
 | 
			
		||||
        <!--<class vtable="0x086c78c8" name="door"/>-->
 | 
			
		||||
    </Entry>
 | 
			
		||||
    <Entry version="v0.28.181.40d16" os="linux" base="40d15lin">
 | 
			
		||||
        <!-- identification -->
 | 
			
		||||
        <String name="md5">022b933926e08da49c6df8649295f2b7</String>
 | 
			
		||||
        <!-- map_data = 0x8F9ABDC -->
 | 
			
		||||
        <!--<class vtable="0x086c78c8" name="door"/>-->
 | 
			
		||||
    </Entry>
 | 
			
		||||
</MemoryDescriptors>
 | 
			
		||||
<!-- Windows logo by M$, spiderweb by jgs -->
 | 
			
		||||
</DFExtractor>
 | 
			
		||||
@ -0,0 +1,22 @@
 | 
			
		||||
# don't use this file directly. use the one in the root folder of the project
 | 
			
		||||
 | 
			
		||||
# this is required to ensure we use the right configuration for the system.
 | 
			
		||||
IF(UNIX)
 | 
			
		||||
add_definitions(-DLINUX_BUILD)
 | 
			
		||||
ENDIF(UNIX)
 | 
			
		||||
 | 
			
		||||
# a benchmark program
 | 
			
		||||
ADD_EXECUTABLE(expbench expbench.cpp)
 | 
			
		||||
TARGET_LINK_LIBRARIES(expbench dfhack)
 | 
			
		||||
 | 
			
		||||
# a reveal clone
 | 
			
		||||
ADD_EXECUTABLE(reveal reveal.cpp)
 | 
			
		||||
TARGET_LINK_LIBRARIES(reveal dfhack)
 | 
			
		||||
 | 
			
		||||
# prospector - produces a list of available materials and their quantities
 | 
			
		||||
ADD_EXECUTABLE(prospector prospector.cpp)
 | 
			
		||||
TARGET_LINK_LIBRARIES(prospector dfhack)
 | 
			
		||||
 | 
			
		||||
# cleanmap - removes mud, snow, blood and similar stuff from a map. farmers beware
 | 
			
		||||
ADD_EXECUTABLE(cleanmap cleanmap.cpp)
 | 
			
		||||
TARGET_LINK_LIBRARIES(cleanmap dfhack)
 | 
			
		||||
@ -0,0 +1,50 @@
 | 
			
		||||
// Map cleaner. Removes all the snow, mud spills, blood and vomit from map tiles.
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
#include <DFTypes.h>
 | 
			
		||||
#include <DFHackAPI.h>
 | 
			
		||||
 | 
			
		||||
int main (void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t x_max,y_max,z_max;
 | 
			
		||||
    uint32_t num_blocks = 0;
 | 
			
		||||
    uint32_t bytes_read = 0;
 | 
			
		||||
    t_occupancy occupancies[256];
 | 
			
		||||
    
 | 
			
		||||
    DFHackAPI DF("Memory.xml");
 | 
			
		||||
    if(!DF.Attach())
 | 
			
		||||
    {
 | 
			
		||||
        cerr << "DF not found" << endl;
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    DF.InitMap();
 | 
			
		||||
    DF.getSize(x_max,y_max,z_max);
 | 
			
		||||
    
 | 
			
		||||
    // walk the map
 | 
			
		||||
    for(uint32_t x = 0; x< x_max;x++)
 | 
			
		||||
    {
 | 
			
		||||
        for(uint32_t y = 0; y< y_max;y++)
 | 
			
		||||
        {
 | 
			
		||||
            for(uint32_t z = 0; z< z_max;z++)
 | 
			
		||||
            {
 | 
			
		||||
                if(DF.isValidBlock(x,y,z))
 | 
			
		||||
                {
 | 
			
		||||
                    // read block designations
 | 
			
		||||
                    DF.ReadOccupancy(x,y,z, (uint32_t *) occupancies);
 | 
			
		||||
                    // change the hidden flag to 0
 | 
			
		||||
                    for (uint32_t i = 0; i < 256;i++)
 | 
			
		||||
                    {
 | 
			
		||||
                        occupancies[i].unibits.splatter = 0;
 | 
			
		||||
                    }
 | 
			
		||||
                    // write the designations back
 | 
			
		||||
                    DF.WriteOccupancy(x,y,z, (uint32_t *) occupancies);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,50 @@
 | 
			
		||||
// This program exports the entire map from DF. Takes roughly 6.6 seconds for 1000 cycles on my Linux machine. ~px
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
#include <DFTypes.h>
 | 
			
		||||
#include <DFHackAPI.h>
 | 
			
		||||
 | 
			
		||||
int main (void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t x_max,y_max,z_max;
 | 
			
		||||
    uint32_t num_blocks = 0;
 | 
			
		||||
    uint32_t bytes_read = 0;
 | 
			
		||||
    uint16_t tiletypes[16][16];
 | 
			
		||||
    t_designation designations[16][16];
 | 
			
		||||
    t_occupancy occupancies[16][16];
 | 
			
		||||
    
 | 
			
		||||
    DFHackAPI DF("Memory.xml");
 | 
			
		||||
    if(!DF.Attach())
 | 
			
		||||
    {
 | 
			
		||||
        cerr << "DF not found" << endl;
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    DF.InitMap();
 | 
			
		||||
    DF.getSize(x_max,y_max,z_max);
 | 
			
		||||
    
 | 
			
		||||
    for(uint32_t i = 0; i< 1000;i++)
 | 
			
		||||
    for(uint32_t x = 0; x< x_max;x++)
 | 
			
		||||
    {
 | 
			
		||||
        for(uint32_t y = 0; y< y_max;y++)
 | 
			
		||||
        {
 | 
			
		||||
            for(uint32_t z = 0; z< z_max;z++)
 | 
			
		||||
            {
 | 
			
		||||
                if(DF.isValidBlock(x,y,z))
 | 
			
		||||
                {
 | 
			
		||||
                    DF.ReadTileTypes(x,y,z, (uint16_t *) tiletypes);
 | 
			
		||||
                    DF.ReadDesignations(x,y,z, (uint32_t *) designations);
 | 
			
		||||
                    DF.ReadOccupancy(x,y,z, (uint32_t *) occupancies);
 | 
			
		||||
                    num_blocks ++;
 | 
			
		||||
                    bytes_read += 256 * (4 + 4 + 2);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    cout << num_blocks << " blocks read" << endl;
 | 
			
		||||
    cout << bytes_read / (1024 * 1024) << " MB" << endl;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,168 @@
 | 
			
		||||
// produces a list of vein materials available on the map. can be run with '-a' modifier to show even unrevealed minerals deep underground
 | 
			
		||||
// with -b modifier, it will show base layer materials too
 | 
			
		||||
 | 
			
		||||
// TODO: use material colors to make the output prettier
 | 
			
		||||
// TODO: needs the tiletype filter!
 | 
			
		||||
// TODO: tile override materials
 | 
			
		||||
// TODO: material types, trees, ice, constructions
 | 
			
		||||
// TODO: GUI
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string.h> // for memset
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <map>
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
#include <DFTypes.h>
 | 
			
		||||
#include <DFTileTypes.h>
 | 
			
		||||
#include <DFHackAPI.h>
 | 
			
		||||
 | 
			
		||||
int main (int argc, const char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    
 | 
			
		||||
    bool showhidden = false;
 | 
			
		||||
    bool showbaselayers = false;
 | 
			
		||||
    for(int i = 0; i < argc; i++)
 | 
			
		||||
    {
 | 
			
		||||
        string test = argv[i];
 | 
			
		||||
        if(test == "-a")
 | 
			
		||||
        {
 | 
			
		||||
            showhidden = true;
 | 
			
		||||
        }
 | 
			
		||||
        else if(test == "-b")
 | 
			
		||||
        {
 | 
			
		||||
            showbaselayers = true;
 | 
			
		||||
        }
 | 
			
		||||
        else if(test == "-ab" || test == "-ba")
 | 
			
		||||
        {
 | 
			
		||||
            showhidden = true;
 | 
			
		||||
            showbaselayers = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    uint32_t x_max,y_max,z_max;
 | 
			
		||||
    uint16_t tiletypes[16][16];
 | 
			
		||||
    t_designation designations[16][16];
 | 
			
		||||
    uint8_t regionoffsets[16];
 | 
			
		||||
    map <int16_t, uint32_t> materials;
 | 
			
		||||
    materials.clear();
 | 
			
		||||
    vector<t_matgloss> stonetypes;
 | 
			
		||||
    vector< vector <uint16_t> > layerassign;
 | 
			
		||||
    
 | 
			
		||||
    // init the API
 | 
			
		||||
    DFHackAPI DF("Memory.xml");
 | 
			
		||||
    
 | 
			
		||||
    // attach
 | 
			
		||||
    if(!DF.Attach())
 | 
			
		||||
    {
 | 
			
		||||
        cerr << "DF not found" << endl;
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // init the map
 | 
			
		||||
    DF.InitMap();
 | 
			
		||||
    DF.getSize(x_max,y_max,z_max);
 | 
			
		||||
    
 | 
			
		||||
    // get stone matgloss mapping
 | 
			
		||||
    if(!DF.ReadStoneMatgloss(stonetypes))
 | 
			
		||||
    {
 | 
			
		||||
        //DF.DestroyMap();
 | 
			
		||||
        cerr << "Can't get the materials." << endl;
 | 
			
		||||
        return 1; 
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // get region geology
 | 
			
		||||
    if(!DF.ReadGeology( layerassign ))
 | 
			
		||||
    {
 | 
			
		||||
        cerr << "Can't get region geology." << endl;
 | 
			
		||||
        return 1; 
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    int16_t tempvein [16][16];
 | 
			
		||||
    vector <t_vein> veins;
 | 
			
		||||
    // walk the map!
 | 
			
		||||
    for(uint32_t x = 0; x< x_max;x++)
 | 
			
		||||
    {
 | 
			
		||||
        for(uint32_t y = 0; y< y_max;y++)
 | 
			
		||||
        {
 | 
			
		||||
            for(uint32_t z = 0; z< z_max;z++)
 | 
			
		||||
            {
 | 
			
		||||
                if(!DF.isValidBlock(x,y,z))
 | 
			
		||||
                    continue;
 | 
			
		||||
                
 | 
			
		||||
                // read data
 | 
			
		||||
                DF.ReadTileTypes(x,y,z, (uint16_t *) tiletypes);
 | 
			
		||||
                DF.ReadDesignations(x,y,z, (uint32_t *) designations);
 | 
			
		||||
                
 | 
			
		||||
                memset(tempvein, -1, sizeof(tempvein));
 | 
			
		||||
                veins.clear();
 | 
			
		||||
                DF.ReadVeins(x,y,z,veins);
 | 
			
		||||
                
 | 
			
		||||
                if(showbaselayers)
 | 
			
		||||
                {
 | 
			
		||||
                    DF.ReadRegionOffsets(x,y,z, regionoffsets);
 | 
			
		||||
                    // get the layer materials
 | 
			
		||||
                    for(uint32_t xx = 0;xx<16;xx++)
 | 
			
		||||
                    {
 | 
			
		||||
                        for (uint32_t yy = 0; yy< 16;yy++)
 | 
			
		||||
                        {
 | 
			
		||||
                            tempvein[xx][yy] =
 | 
			
		||||
                            layerassign
 | 
			
		||||
                            [regionoffsets[designations[xx][yy].bits.biome]]
 | 
			
		||||
                            [designations[xx][yy].bits.geolayer_index];
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                // for each vein
 | 
			
		||||
                for(int i = 0; i < veins.size();i++)
 | 
			
		||||
                {
 | 
			
		||||
                    //iterate through vein rows
 | 
			
		||||
                    for(uint32_t j = 0;j<16;j++)
 | 
			
		||||
                    {
 | 
			
		||||
                        //iterate through the bits
 | 
			
		||||
                        for (uint32_t k = 0; k< 16;k++)
 | 
			
		||||
                        {
 | 
			
		||||
                            // and the bit array with a one-bit mask, check if the bit is set
 | 
			
		||||
                            bool set = ((1 << k) & veins[i].assignment[j]) >> k;
 | 
			
		||||
                            if(set)
 | 
			
		||||
                            {
 | 
			
		||||
                                // store matgloss
 | 
			
		||||
                                tempvein[k][j] = veins[i].type;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                // count the material types
 | 
			
		||||
                for(uint32_t xi = 0 ; xi< 16 ; xi++)
 | 
			
		||||
                {
 | 
			
		||||
                    for(uint32_t yi = 0 ; yi< 16 ; yi++)
 | 
			
		||||
                    {
 | 
			
		||||
                        // hidden tiles are ignored unless '-a' is provided on the command line
 | 
			
		||||
                        // non-wall tiles are ignored
 | 
			
		||||
                        if(designations[xi][yi].bits.hidden && !showhidden || !isWallTerrain(tiletypes[xi][yi]))
 | 
			
		||||
                            continue;
 | 
			
		||||
                        if(tempvein[xi][yi] < 0)
 | 
			
		||||
                            continue;
 | 
			
		||||
                        
 | 
			
		||||
                        if(materials.count(tempvein[xi][yi]))
 | 
			
		||||
                        {
 | 
			
		||||
                            materials[tempvein[xi][yi]] += 1;
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            materials[tempvein[xi][yi]] = 1;
 | 
			
		||||
                        }
 | 
			
		||||
                    }    
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // print report
 | 
			
		||||
    map<int16_t, uint32_t>::iterator p;
 | 
			
		||||
    for(p = materials.begin(); p != materials.end(); p++)
 | 
			
		||||
    {
 | 
			
		||||
        cout << stonetypes[p->first].id << " : " << p->second << endl;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,50 @@
 | 
			
		||||
// This is a reveal program. It reveals the map.
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
#include <DFTypes.h>
 | 
			
		||||
#include <DFHackAPI.h>
 | 
			
		||||
 | 
			
		||||
int main (void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t x_max,y_max,z_max;
 | 
			
		||||
    uint32_t num_blocks = 0;
 | 
			
		||||
    uint32_t bytes_read = 0;
 | 
			
		||||
    t_designation designations[256];
 | 
			
		||||
    
 | 
			
		||||
    DFHackAPI DF("Memory.xml");
 | 
			
		||||
    if(!DF.Attach())
 | 
			
		||||
    {
 | 
			
		||||
        cerr << "DF not found" << endl;
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    DF.InitMap();
 | 
			
		||||
    DF.getSize(x_max,y_max,z_max);
 | 
			
		||||
    
 | 
			
		||||
    // walk the map
 | 
			
		||||
    for(uint32_t x = 0; x< x_max;x++)
 | 
			
		||||
    {
 | 
			
		||||
        for(uint32_t y = 0; y< y_max;y++)
 | 
			
		||||
        {
 | 
			
		||||
            for(uint32_t z = 0; z< z_max;z++)
 | 
			
		||||
            {
 | 
			
		||||
                if(DF.isValidBlock(x,y,z))
 | 
			
		||||
                {
 | 
			
		||||
                    // read block designations
 | 
			
		||||
                    DF.ReadDesignations(x,y,z, (uint32_t *) designations);
 | 
			
		||||
                    // change the hidden flag to 0
 | 
			
		||||
                    for (uint32_t i = 0; i < 256;i++)
 | 
			
		||||
                    {
 | 
			
		||||
                        designations[i].bits.hidden = 0;
 | 
			
		||||
                    }
 | 
			
		||||
                    // write the designations back
 | 
			
		||||
                    DF.WriteDesignations(x,y,z, (uint32_t *) designations);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue