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