First 'working' DFHack inside DF, for 'some' values of 'working'.

develop
Petr Mrázek 2011-06-12 23:17:40 +02:00
parent da2fb1cb1a
commit 81d648dfa7
99 changed files with 699 additions and 7930 deletions

@ -8,31 +8,25 @@ cmake_minimum_required(VERSION 2.8)
include_directories (include)
include_directories (depends/md5)
include_directories (depends/tinyxml)
include_directories (depends/argstream)
include_directories (private)
SET(PROJECT_HDRS_INTERNAL
private/ContextShared.h
private/Internal.h
private/SHMProcess.h
private/LinuxProcess.h
private/ProcessFactory.h
private/MicrosoftSTL.h
private/core.h
)
SET(PROJECT_HDRS
include/DFHack.h
include/dfhack/DFContext.h
include/dfhack/DFContextManager.h
include/dfhack/Context.h
include/dfhack/DFError.h
include/dfhack/DFExport.h
include/dfhack/DFIntegers.h
include/dfhack/DFMiscUtils.h
include/dfhack/DFModule.h
include/dfhack/DFPragma.h
include/dfhack/DFProcess.h
include/dfhack/DFProcessEnumerator.h
include/dfhack/DFTileTypes.h
include/dfhack/Process.h
include/dfhack/TileTypes.h
include/dfhack/DFTypes.h
include/dfhack/DFVector.h
include/dfhack/VersionInfoFactory.h
@ -50,39 +44,15 @@ include/dfhack/modules/Maps.h
include/dfhack/modules/Materials.h
include/dfhack/modules/Translation.h
include/dfhack/modules/Vegetation.h
include/dfhack/modules/WindowIO.h
include/dfhack/modules/World.h
)
SET(PROJECT_C_HDRS
include/DFHack_C.h
include/dfhack-c/DFProcess_C.h
include/dfhack-c/DFTypes_C.h
include/dfhack-c/DFTileTypes_C.h
include/dfhack-c/DFContext_C.h
include/dfhack-c/modules/Buildings_C.h
include/dfhack-c/modules/Constructions_C.h
include/dfhack-c/modules/Creatures_C.h
include/dfhack-c/modules/Gui_C.h
include/dfhack-c/modules/Items_C.h
include/dfhack-c/modules/Maps_C.h
include/dfhack-c/modules/Materials_C.h
include/dfhack-c/modules/Translation_C.h
include/dfhack-c/modules/Vegetation_C.h
include/dfhack-c/modules/WindowIO_C.h
include/dfhack-c/modules/World_C.h
)
SET(PROJECT_SRCS
VersionInfo.cpp
VersionInfoFactory.cpp
DFContextManager.cpp
DFContext.cpp
DFTileTypes.cpp
DFProcessEnumerator.cpp
Context.cpp
TileTypes.cpp
ContextShared.cpp
DFProcess-SHM.cpp
MicrosoftSTL.cpp
depends/md5/md5.cpp
depends/md5/md5wrapper.cpp
@ -105,25 +75,6 @@ modules/Vegetation.cpp
modules/World.cpp
)
SET(PROJECT_C_SRCS
DFContext_C.cpp
DFProcess_C.cpp
DFTypes_C.cpp
DFTileTypes_C.cpp
modules/Buildings_C.cpp
modules/Constructions_C.cpp
modules/Creatures_C.cpp
modules/Gui_C.cpp
modules/Items_C.cpp
modules/Maps_C.cpp
modules/Materials_C.cpp
modules/Translation_C.cpp
modules/Vegetation_C.cpp
modules/WindowIO_C.cpp
modules/World_C.cpp
)
SET(PROJECT_HDRS_LINUX
)
@ -132,17 +83,17 @@ include/dfhack/DFstdint_win.h
)
SET(PROJECT_SRCS_LINUX
DFProcess-linux.cpp
DFProcess-linux-base.cpp
DFProcess-linux-SHM.cpp
DFProcess-linux-wine.cpp
modules/WindowIO-linux.cpp
Core-linux.cpp
Process-linux.cpp
#DFProcess-linux-base.cpp
#DFProcess-linux-wine.cpp
#modules/WindowIO-linux.cpp
)
SET(PROJECT_SRCS_WINDOWS
DFProcess-windows.cpp
DFProcess-windows-SHM.cpp
modules/WindowIO-windows.cpp
Core-windows.cpp
Process-windows.cpp
#modules/WindowIO-windows.cpp
)
IF(UNIX)
@ -174,7 +125,8 @@ IF(UNIX)
add_definitions(-DLINUX_BUILD)
find_library(X11_LIBRARY X11)
SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall")
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden")
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -m32")
SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32")
SET(PROJECT_LIBS ${X11_LIBRARY} rt )
ELSE()

@ -29,11 +29,10 @@ distribution.
#include <cstring>
using namespace std;
#include "dfhack/DFProcess.h"
#include "dfhack/DFProcessEnumerator.h"
#include "dfhack/DFContext.h"
#include "dfhack/DFError.h"
#include "dfhack/DFModule.h"
#include "dfhack/Process.h"
#include "dfhack/Context.h"
#include "dfhack/Error.h"
#include "dfhack/Module.h"
#include "private/ContextShared.h"
#include "private/ModuleFactory.h"
@ -60,7 +59,7 @@ bool Context::isValid()
return true;
return false;
}
/*
bool Context::Attach()
{
if (!d->p->attach())
@ -96,14 +95,14 @@ bool Context::isAttached()
{
return d->p->isAttached();
}
*/
bool Context::Suspend()
{
return d->p->suspend();
// return d->p->suspend();
}
bool Context::AsyncSuspend()
{
return d->p->asyncSuspend();
// return d->p->asyncSuspend();
}
bool Context::Resume()
@ -112,8 +111,9 @@ bool Context::Resume()
{
d->allModules[i]->OnResume();
}
return d->p->resume();
//return d->p->resume();
}
/*
bool Context::ForceResume()
{
for(unsigned int i = 0 ; i < d->allModules.size(); i++)
@ -122,11 +122,12 @@ bool Context::ForceResume()
}
return d->p->forceresume();
}
*/
bool Context::isSuspended()
{
return d->p->isSuspended();
}
/*
void Context::ReadRaw (const uint32_t offset, const uint32_t size, uint8_t *target)
{
d->p->read (offset, size, target);
@ -136,7 +137,7 @@ void Context::WriteRaw (const uint32_t offset, const uint32_t size, uint8_t *sou
{
d->p->write (offset, size, source);
}
*/
VersionInfo *Context::getMemoryInfo()
{
return d->offset_descriptor;

@ -8,8 +8,8 @@ using namespace std;
#include "private/ContextShared.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFModule.h"
#include "dfhack/Process.h"
#include "dfhack/Module.h"
using namespace DFHack;
DFContextShared::DFContextShared()

@ -0,0 +1,257 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2011 Petr Mrázek (peterix)
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 <stdio.h>
#include <dlfcn.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <vector>
#include <string>
#include <map>
#include "core.h"
#include "DFHack.h"
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/Context.h"
#include <iostream>
#define DFhackCExport extern "C" __attribute__ ((visibility("default")))
int errorstate = 0;
bool inited = 0;
DFHack::VersionInfoFactory * vif = 0;
DFHack::Process * p = 0;
DFHack::Context * c = 0;
DFHack::Gui * gui = 0;
uint32_t OS_getPID()
{
return getpid();
}
void SHM_Init ( void )
{
// check that we do this only once per process
if(inited)
{
std::cerr << "SDL_Init was called twice or more!" << std::endl;
return;
}
vif = new DFHack::VersionInfoFactory("Memory.xml");
p = new DFHack::Process(vif);
if (!p->isIdentified())
{
std::cerr << "Couldn't identify this version of DF." << std::endl;
errorstate = 1;
}
c = new DFHack::Context(p);
gui = c->getGui();
gui->Start();
inited = true;
}
int32_t x = 0,y = 0,z = 0;
int32_t xo = 0,yo = 0,zo = 0;
void SHM_Act()
{
gui->getCursorCoords(x,y,z);
if(x != xo || y!= yo || z != zo)
{
xo = x;
yo = y;
zo = z;
std::cout << "Cursor: " << x << "/" << y << "/" << z << std::endl;
}
};
void SHM_Destroy ( void )
{
if(inited && !errorstate)
{
inited = false;
}
}
/*******************************************************************************
* SDL part starts here *
*******************************************************************************/
DFhackCExport int SDL_NumJoysticks(void)
{
if(errorstate)
return -1;
if(!inited)
{
SHM_Init();
return -2;
}
SHM_Act();
return -3;
}
// ptr to the real functions
//static void (*_SDL_GL_SwapBuffers)(void) = 0;
static void (*_SDL_Quit)(void) = 0;
static int (*_SDL_Init)(uint32_t flags) = 0;
//static int (*_SDL_Flip)(void * some_ptr) = 0;
/*
// hook - called every tick in OpenGL mode of DF
DFhackCExport void SDL_GL_SwapBuffers(void)
{
if(_SDL_GL_SwapBuffers)
{
if(!errorstate)
{
SHM_Act();
}
counter ++;
_SDL_GL_SwapBuffers();
}
}
*/
/*
// hook - called every tick in the 2D mode of DF
DFhackCExport int SDL_Flip(void * some_ptr)
{
if(_SDL_Flip)
{
if(!errorstate)
{
SHM_Act();
}
counter ++;
return _SDL_Flip(some_ptr);
}
return 0;
}
*/
// hook - called at program exit
DFhackCExport void SDL_Quit(void)
{
if(!errorstate)
{
SHM_Destroy();
errorstate = true;
}
if(_SDL_Quit)
{
_SDL_Quit();
}
}
// hook - called at program start, initialize some stuffs we'll use later
DFhackCExport int SDL_Init(uint32_t flags)
{
// find real functions
//_SDL_GL_SwapBuffers = (void (*)( void )) dlsym(RTLD_NEXT, "SDL_GL_SwapBuffers");
_SDL_Init = (int (*)( uint32_t )) dlsym(RTLD_NEXT, "SDL_Init");
//_SDL_Flip = (int (*)( void * )) dlsym(RTLD_NEXT, "SDL_Flip");
_SDL_Quit = (void (*)( void )) dlsym(RTLD_NEXT, "SDL_Quit");
// check if we got them
if(/*_SDL_GL_SwapBuffers &&*/ _SDL_Init && _SDL_Quit)
{
fprintf(stderr,"dfhack: hooking successful\n");
}
else
{
// bail, this would be a disaster otherwise
fprintf(stderr,"dfhack: something went horribly wrong\n");
errorstate = true;
exit(1);
}
//SHM_Init();
return _SDL_Init(flags);
}
//*/
/*******************************************************************************
* NCURSES part starts here *
*******************************************************************************/
static int (*_refresh)(void) = 0;
//extern NCURSES_EXPORT(int) refresh (void);
DFhackCExport int refresh (void)
{
if(_refresh)
{
/*
if(!errorstate)
{
SHM_Act();
}
counter ++;
*/
return _refresh();
}
return 0;
}
static int (*_endwin)(void) = 0;
//extern NCURSES_EXPORT(int) endwin (void);
DFhackCExport int endwin (void)
{
if(!errorstate)
{
SHM_Destroy();
errorstate = true;
}
if(_endwin)
{
return _endwin();
}
return 0;
}
typedef void WINDOW;
//extern NCURSES_EXPORT(WINDOW *) initscr (void);
static WINDOW * (*_initscr)(void) = 0;
DFhackCExport WINDOW * initscr (void)
{
// find real functions
//_refresh = (int (*)( void )) dlsym(RTLD_NEXT, "refresh");
_endwin = (int (*)( void )) dlsym(RTLD_NEXT, "endwin");
_initscr = (WINDOW * (*)( void )) dlsym(RTLD_NEXT, "initscr");
// check if we got them
if(_refresh && _endwin && _initscr)
{
fprintf(stderr,"dfhack: hooking successful\n");
}
else
{
// bail, this would be a disaster otherwise
fprintf(stderr,"dfhack: something went horribly wrong\n");
exit(1);
}
//SHM_Init();
return _initscr();
}

@ -1,246 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include <string>
#include <vector>
#include <map>
using namespace std;
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFProcessEnumerator.h"
#include "dfhack/DFError.h"
#include "dfhack/DFContext.h"
#include "dfhack/DFContextManager.h"
#include "private/ContextShared.h"
using namespace DFHack;
namespace DFHack
{
class ContextManager::Private
{
public:
Private(){};
~Private(){};
string xml; // path to xml
vector <Context *> contexts;
ProcessEnumerator * pEnum;
};
}
class DFHack::BadContexts::Private
{
public:
Private(){};
vector <Context *> bad;
};
BadContexts::BadContexts():d(new Private()){}
BadContexts::~BadContexts()
{
clear();
delete d;
}
bool BadContexts::Contains(Process* p)
{
for(unsigned int i = 0; i < d->bad.size(); i++)
{
if((d->bad[i])->getProcess() == p)
return true;
}
return false;
}
bool BadContexts::Contains(Context* c)
{
for(unsigned int i = 0; i < d->bad.size(); i++)
{
if(d->bad[i] == c)
return true;
}
return false;
}
uint32_t BadContexts::size()
{
return d->bad.size();
}
void BadContexts::clear()
{
for(unsigned int i = 0; i < d->bad.size(); i++)
{
// delete both Process and Context!
// process has to be deleted after context, because Context does some
// cleanup on delete (detach, etc.)
Process * to_kill = d->bad[i]->getProcess();
delete d->bad[i];
delete to_kill;
}
d->bad.clear();
}
void BadContexts::push_back(Context* c)
{
if(c)
d->bad.push_back(c);
}
Context * BadContexts::operator[](uint32_t index)
{
if(index < d->bad.size())
return d->bad[index];
return 0;
}
ContextManager::ContextManager (const string path_to_xml) : d (new Private())
{
d->xml = MEMXML_DATA_PATH;
d->xml += "/";
d->xml += path_to_xml;
d->pEnum = new ProcessEnumerator(d->xml);
}
ContextManager::~ContextManager()
{
purge();
// process enumerator has to be destroyed after we detach from processes
// because it tracks and destroys them
if(d->pEnum)
{
delete d->pEnum;
d->pEnum = 0;
}
delete d;
}
uint32_t ContextManager::Refresh( BadContexts* bad_contexts )
{
// handle expired processes, remove stale Contexts
{
BadProcesses expired;
// get new list od living and expired Process objects
d->pEnum->Refresh(&expired);
// scan expired, kill contexts if necessary
vector <Context*>::iterator it = d->contexts.begin();;
while(it != d->contexts.end())
{
Process * test = (*it)->getProcess();
if(expired.Contains(test))
{
// ok. we have an expired context here.
if(!bad_contexts)
{
// with nowhere to put the context, we have to destroy it
delete *it;
// stop tracking it and advance the iterator
it = d->contexts.erase(it);
continue;
}
else
{
// we stuff the context into bad_contexts
bad_contexts->push_back(*it);
// stop tracking it and advance the iterator
it = d->contexts.erase(it);
// remove process from the 'expired' container, it is tracked by bad_contexts now
// (which is responsible for freeing it).
expired.excise(test);
continue;
}
}
else it++; // not expired, just advance to next one
}
// no expired contexts are in the d->contexts vector now
// all processes remaining in 'expired' are now destroyed along with it
}
int numProcesses = d->pEnum->size();
int numContexts = d->contexts.size();
vector <Context *> newContexts;
// enumerate valid processes
for(int i = 0; i < numProcesses; i++)
{
Process * test = d->pEnum->operator[](i);
bool exists = false;
// scan context vector for this process
for(int j = 0; j < numContexts; j++)
{
if((d->contexts[j])->getProcess() == test)
{
// already have that one, skip
exists = true;
}
}
if(!exists)
{
// new process needs a new context
Context * c = new Context(d->pEnum->operator[](i));
newContexts.push_back(c);
}
}
d->contexts.insert(d->contexts.end(), newContexts.begin(), newContexts.end());
return d->contexts.size();
}
uint32_t ContextManager::size()
{
return d->contexts.size();
}
Context * ContextManager::operator[](uint32_t index)
{
if (index < d->contexts.size())
return d->contexts[index];
return 0;
}
Context * ContextManager::getSingleContext()
{
if(!d->contexts.size())
{
Refresh();
}
for(unsigned int i = 0; i < d->contexts.size();i++)
{
if(d->contexts[i]->isValid())
{
return d->contexts[i];
}
}
throw DFHack::Error::NoProcess();
}
void ContextManager::purge(void)
{
for(unsigned int i = 0; i < d->contexts.size();i++)
delete d->contexts[i];
d->contexts.clear();
d->pEnum->purge();
}

@ -1,366 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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 "dfhack/DFPragma.h"
#include "dfhack/DFExport.h"
#include <string>
#include <vector>
#include <map>
using namespace std;
#include "dfhack/DFIntegers.h"
#include "dfhack/DFContextManager.h"
#include "dfhack/DFContext.h"
using namespace DFHack;
#include "dfhack-c/DFContext_C.h"
#ifdef __cplusplus
extern "C" {
#endif
DFHackObject* ContextManager_Alloc(const char* path_to_xml)
{
DFHack::ContextManager* contextMgr = new DFHack::ContextManager(std::string(path_to_xml));
return (DFHackObject*)contextMgr;
}
//FIXME: X:\dfhack\DFHackContext_C.cpp:56: warning: deleting `DFHackObject* ' is undefined
//DC: Yeah, I forgot that trying to delete a void pointer might be a bad idea. This works now.
void ContextManager_Free(DFHackObject* contextMgr)
{
if(contextMgr != NULL)
{
DFHack::ContextManager* a = (DFHack::ContextManager*)contextMgr;
delete a;
contextMgr = NULL;
}
}
int ContextManager_Refresh(DFHackObject* contextMgr)
{
if(contextMgr != NULL)
{
return ((DFHack::ContextManager*)contextMgr)->Refresh();
}
return -1;
}
int ContextManager_size(DFHackObject* contextMgr, uint32_t* size)
{
if(contextMgr != NULL)
{
uint32_t result = ((DFHack::ContextManager*)contextMgr)->size();
*size = result;
return 1;
}
return -1;
}
int ContextManager_purge(DFHackObject* contextMgr)
{
if(contextMgr != NULL)
{
((DFHack::ContextManager*)contextMgr)->purge();
return 1;
}
return -1;
}
DFHackObject* ContextManager_getContext(DFHackObject* contextMgr, uint32_t index)
{
if(contextMgr != NULL)
{
DFHack::ContextManager* mgr = ((DFHack::ContextManager*)contextMgr);
if(index >= mgr->size())
return NULL;
return (DFHackObject*)((DFHack::Context*)((*mgr)[index]));
}
return NULL;
}
DFHackObject* ContextManager_getSingleContext(DFHackObject* contextMgr)
{
if(contextMgr != NULL)
{
return (DFHackObject*)((DFHack::ContextManager*)contextMgr)->getSingleContext();
}
return NULL;
}
void Context_Free(DFHackObject* context)
{
if(context != NULL)
{
DFHack::Context* c = (DFHack::Context*)context;
delete c;
context = NULL;
}
}
int Context_Attach(DFHackObject* context)
{
if(context != NULL)
{
return ((DFHack::Context*)context)->Attach();
}
return -1;
}
int Context_Detach(DFHackObject* context)
{
if(context != NULL)
{
return ((DFHack::Context*)context)->Detach();
}
return -1;
}
int Context_isAttached(DFHackObject* context)
{
if(context != NULL)
{
return ((DFHack::Context*)context)->isAttached();
}
return -1;
}
int Context_Suspend(DFHackObject* context)
{
if(context != NULL)
{
return ((DFHack::Context*)context)->Suspend();
}
return -1;
}
int Context_Resume(DFHackObject* context)
{
if(context != NULL)
{
return ((DFHack::Context*)context)->Resume();
}
return -1;
}
int Context_isSuspended(DFHackObject* context)
{
if(context != NULL)
{
return ((DFHack::Context*)context)->isSuspended();
}
return -1;
}
int Context_ForceResume(DFHackObject* context)
{
if(context != NULL)
{
return ((DFHack::Context*)context)->ForceResume();
}
return -1;
}
int Context_AsyncSuspend(DFHackObject* context)
{
if(context != NULL)
{
return ((DFHack::Context*)context)->AsyncSuspend();
}
return -1;
}
//module getters
DFHackObject* Context_getMemoryInfo(DFHackObject* context)
{
if(context != NULL)
{
return (DFHackObject*)((DFHack::Context*)context)->getMemoryInfo();
}
return NULL;
}
DFHackObject* Context_getProcess(DFHackObject* context)
{
if(context != NULL)
{
return (DFHackObject*)((DFHack::Context*)context)->getProcess();
}
return NULL;
}
DFHackObject* Context_getCreatures(DFHackObject* context)
{
if(context != NULL)
{
return (DFHackObject*)((DFHack::Context*)context)->getCreatures();
}
return NULL;
}
DFHackObject* Context_getMaps(DFHackObject* context)
{
if(context != NULL)
{
return (DFHackObject*)((DFHack::Context*)context)->getMaps();
}
return NULL;
}
DFHackObject* Context_getGui(DFHackObject* context)
{
if(context != NULL)
{
return (DFHackObject*)((DFHack::Context*)context)->getGui();
}
return NULL;
}
DFHackObject* Context_getMaterials(DFHackObject* context)
{
if(context != NULL)
{
return (DFHackObject*)((DFHack::Context*)context)->getMaterials();
}
return NULL;
}
DFHackObject* Context_getTranslation(DFHackObject* context)
{
if(context != NULL)
{
return (DFHackObject*)((DFHack::Context*)context)->getTranslation();
}
return NULL;
}
DFHackObject* Context_getVegetation(DFHackObject* context)
{
if(context != NULL)
{
return (DFHackObject*)((DFHack::Context*)context)->getVegetation();
}
return NULL;
}
DFHackObject* Context_getBuildings(DFHackObject* context)
{
if(context != NULL)
{
return (DFHackObject*)((DFHack::Context*)context)->getBuildings();
}
return NULL;
}
DFHackObject* Context_getConstructions(DFHackObject* context)
{
if(context != NULL)
{
return (DFHackObject*)((DFHack::Context*)context)->getConstructions();
}
return NULL;
}
DFHackObject* Context_getItems(DFHackObject* context)
{
if(context != NULL)
{
return (DFHackObject*)((DFHack::Context*)context)->getItems();
}
return NULL;
}
DFHackObject* Context_getWorld(DFHackObject* context)
{
if(context != NULL)
{
return (DFHackObject*)((DFHack::Context*)context)->getWorld();
}
return NULL;
}
DFHackObject* Context_getWindowIO(DFHackObject* context)
{
if(context != NULL)
{
return (DFHackObject*)((DFHack::Context*)context)->getWindowIO();
}
return NULL;
}
void Context_ReadRaw(DFHackObject* context, const uint32_t offset, const uint32_t size, uint8_t* target)
{
if(context != NULL)
{
((DFHack::Context*)context)->ReadRaw(offset, size, target);
}
}
void Context_WriteRaw(DFHackObject* context, const uint32_t offset, const uint32_t size, uint8_t* source)
{
if(context != NULL)
{
((DFHack::Context*)context)->WriteRaw(offset, size, source);
}
}
#ifdef __cplusplus
}
#endif

@ -1,488 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include "PlatformInternal.h"
#include <string>
#include <vector>
#include <map>
#include <cstring>
using namespace std;
#include "SHMProcess.h"
#include "ProcessFactory.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include "shms.h"
#include "mod-core.h"
using namespace DFHack;
Process* DFHack::createSHMProcess(uint32_t pid, VersionInfoFactory * factory)
{
return new SHMProcess(pid, factory);
}
SHMProcess::SHMProcess(uint32_t PID, VersionInfoFactory * factory)
: d(new Private(this))
{
d->process_ID = PID;
// attach the SHM
if(!attach())
{
return;
}
// Test bridge version, get PID, sync Yield
bool bridgeOK;
if(!d->Aux_Core_Attach(bridgeOK,d->process_ID))
{
detach();
throw Error::SHMAttachFailure();
}
else if(!bridgeOK)
{
detach();
throw Error::SHMVersionMismatch();
}
// try to identify the DF version (md5 the binary, compare with known versions)
d->validate(factory);
// at this point, DF is attached and suspended, make it run
detach();
}
SHMProcess::~SHMProcess()
{
if(d->attached)
{
detach();
}
// destroy data model. this is assigned by processmanager
if(d->memdescriptor)
delete d->memdescriptor;
delete d;
}
VersionInfo * SHMProcess::getDescriptor()
{
return d->memdescriptor;
}
int SHMProcess::getPID()
{
return d->process_ID;
}
bool SHMProcess::isSuspended()
{
return d->locked;
}
bool SHMProcess::isAttached()
{
return d->attached;
}
bool SHMProcess::isIdentified()
{
return d->identified;
}
bool SHMProcess::suspend()
{
if(!d->attached)
{
return false;
}
if(d->locked)
{
return true;
}
//cerr << "suspend" << endl;// FIXME: throw
// FIXME: this should be controlled on the server side
// FIXME: IF server got CORE_RUN in this frame, interpret CORE_SUSPEND as CORE_STEP
// did we just resume a moment ago?
if(D_SHMCMD == CORE_RUN)
{
//fprintf(stderr,"%d invokes step\n",attachmentIdx);
// wait for the next window
/*
if(!d->SetAndWait(CORE_STEP))
{
throw Error::SHMLockingError("if(!d->SetAndWait(CORE_STEP))");
}
*/
D_SHMCMD = CORE_STEP;
}
else
{
//fprintf(stderr,"%d invokes suspend\n",attachmentIdx);
// lock now
/*
if(!d->SetAndWait(CORE_SUSPEND))
{
throw Error::SHMLockingError("if(!d->SetAndWait(CORE_SUSPEND))");
}
*/
D_SHMCMD = CORE_SUSPEND;
}
//fprintf(stderr,"waiting for lock\n");
// we wait for the server to give up our suspend lock (held by default)
if(acquireSuspendLock())
{
d->locked = true;
return true;
}
return false;
}
// FIXME: needs a good think-through
bool SHMProcess::asyncSuspend()
{
if(!d->attached)
{
return false;
}
if(d->locked)
{
return true;
}
//cerr << "async suspend" << endl;// FIXME: throw
uint32_t cmd = D_SHMCMD;
if(cmd == CORE_SUSPENDED)
{
// we have to hold the lock to be really suspended
if(acquireSuspendLock())
{
d->locked = true;
return true;
}
return false;
}
else
{
// did we just resume a moment ago?
if(cmd == CORE_STEP)
{
return false;
}
else if(cmd == CORE_RUN)
{
D_SHMCMD = CORE_STEP;
}
else
{
D_SHMCMD = CORE_SUSPEND;
}
return false;
}
}
bool SHMProcess::forceresume()
{
return resume();
}
// FIXME: wait for the server to advance a step!
bool SHMProcess::resume()
{
if(!d->attached)
return false;
if(!d->locked)
return true;
//cerr << "resume" << endl;// FIXME: throw
// unlock the suspend lock
if(releaseSuspendLock())
{
d->locked = false;
if(d->SetAndWait(CORE_RUN)) // we have to make sure the server responds!
{
return true;
}
throw Error::SHMLockingError("if(d->SetAndWait(CORE_RUN))");
}
throw Error::SHMLockingError("if(releaseSuspendLock())");
return false;
}
// get module index by name and version. bool 0 = error
bool SHMProcess::getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT)
{
if(!d->locked) throw Error::MemoryAccessDenied(0xdeadbeef);
modulelookup * payload = D_SHMDATA(modulelookup);
payload->version = version;
strncpy(payload->name,name,255);
payload->name[255] = 0;
if(!SetAndWait(CORE_ACQUIRE_MODULE))
{
return false; // FIXME: throw a fatal exception instead
}
if(D_SHMHDR->error)
{
return false;
}
//fprintf(stderr,"%s v%d : %d\n", name, version, D_SHMHDR->value);
OUTPUT = D_SHMHDR->value;
return true;
}
bool SHMProcess::Private::Aux_Core_Attach(bool & versionOK, pid_t & PID)
{
if(!locked) throw Error::MemoryAccessDenied(0xdeadbeef);
SHMDATA(coreattach)->cl_affinity = OS_getAffinity();
if(!SetAndWait(CORE_ATTACH)) return false;
/*
cerr <<"CORE_VERSION" << CORE_VERSION << endl;
cerr <<"server CORE_VERSION" << SHMDATA(coreattach)->sv_version << endl;
*/
versionOK =( SHMDATA(coreattach)->sv_version == CORE_VERSION );
PID = SHMDATA(coreattach)->sv_PID;
useYield = SHMDATA(coreattach)->sv_useYield;
#ifdef DEBUG
if(useYield) cerr << "Using Yield!" << endl;
#endif
return true;
}
void SHMProcess::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
{
if(!d->locked) throw Error::MemoryAccessDenied(src_address);
// normal read under 1MB
if(size <= SHM_BODY)
{
D_SHMHDR->address = src_address;
D_SHMHDR->length = size;
full_barrier
d->SetAndWait(CORE_READ);
memcpy (target_buffer, D_SHMDATA(void),size);
}
// a big read, we pull data over the shm in iterations
else
{
// first read equals the size of the SHM window
uint32_t to_read = SHM_BODY;
while (size)
{
// read to_read bytes from src_cursor
D_SHMHDR->address = src_address;
D_SHMHDR->length = to_read;
full_barrier
d->SetAndWait(CORE_READ);
memcpy (target_buffer, D_SHMDATA(void) ,to_read);
// decrease size by bytes read
size -= to_read;
// move the cursors
src_address += to_read;
target_buffer += to_read;
// check how much to write in the next iteration
to_read = min(size, (uint32_t) SHM_BODY);
}
}
}
void SHMProcess::readByte (const uint32_t offset, uint8_t &val )
{
if(!d->locked) throw Error::MemoryAccessDenied(offset);
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_BYTE);
val = D_SHMHDR->value;
}
void SHMProcess::readWord (const uint32_t offset, uint16_t &val)
{
if(!d->locked) throw Error::MemoryAccessDenied(offset);
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_WORD);
val = D_SHMHDR->value;
}
void SHMProcess::readDWord (const uint32_t offset, uint32_t &val)
{
if(!d->locked) throw Error::MemoryAccessDenied(offset);
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_DWORD);
val = D_SHMHDR->value;
}
void SHMProcess::readQuad (const uint32_t offset, uint64_t &val)
{
if(!d->locked) throw Error::MemoryAccessDenied(offset);
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_QUAD);
val = D_SHMHDR->Qvalue;
}
void SHMProcess::readFloat (const uint32_t offset, float &val)
{
if(!d->locked) throw Error::MemoryAccessDenied(offset);
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_DWORD);
val = reinterpret_cast<float&> (D_SHMHDR->value);
}
/*
* WRITING
*/
void SHMProcess::writeQuad (uint32_t offset, uint64_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied(offset);
D_SHMHDR->address = offset;
D_SHMHDR->Qvalue = data;
full_barrier
d->SetAndWait(CORE_WRITE_QUAD);
}
void SHMProcess::writeDWord (uint32_t offset, uint32_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied(offset);
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
full_barrier
d->SetAndWait(CORE_WRITE_DWORD);
}
// using these is expensive.
void SHMProcess::writeWord (uint32_t offset, uint16_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied(offset);
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
full_barrier
d->SetAndWait(CORE_WRITE_WORD);
}
void SHMProcess::writeByte (uint32_t offset, uint8_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied(offset);
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
full_barrier
d->SetAndWait(CORE_WRITE_BYTE);
}
void SHMProcess::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer)
{
if(!d->locked) throw Error::MemoryAccessDenied(dst_address);
// normal write under 1MB
if(size <= SHM_BODY)
{
D_SHMHDR->address = dst_address;
D_SHMHDR->length = size;
memcpy(D_SHMDATA(void),source_buffer, size);
full_barrier
d->SetAndWait(CORE_WRITE);
}
// a big write, we push this over the shm in iterations
else
{
// first write equals the size of the SHM window
uint32_t to_write = SHM_BODY;
while (size)
{
// write to_write bytes to dst_cursor
D_SHMHDR->address = dst_address;
D_SHMHDR->length = to_write;
memcpy(D_SHMDATA(void),source_buffer, to_write);
full_barrier
d->SetAndWait(CORE_WRITE);
// decrease size by bytes written
size -= to_write;
// move the cursors
source_buffer += to_write;
dst_address += to_write;
// check how much to write in the next iteration
to_write = min(size, (uint32_t) SHM_BODY);
}
}
}
const std::string SHMProcess::readCString (uint32_t offset)
{
std::string temp;
int counter = 0;
char r;
while (1)
{
r = Process::readByte(offset+counter);
if(!r) break;
counter++;
temp.append(1,r);
}
return temp;
}
const std::string SHMProcess::readSTLString(uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied(offset);
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_STL_STRING);
return(string( D_SHMDATA(char) ));
}
size_t SHMProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
if(!d->locked) throw Error::MemoryAccessDenied(offset);
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_STL_STRING);
size_t length = D_SHMHDR->value;
size_t fit = min(bufcapacity - 1, length);
strncpy(buffer,D_SHMDATA(char),fit);
buffer[fit] = 0;
return fit;
}
size_t SHMProcess::writeSTLString(const uint32_t address, const std::string writeString)
{
if(!d->locked) throw Error::MemoryAccessDenied(address);
D_SHMHDR->address = address;
strncpy(D_SHMDATA(char),writeString.c_str(),writeString.length()+1); // length + 1 for the null terminator
full_barrier
d->SetAndWait(CORE_WRITE_STL_STRING);
return writeString.length();
}

@ -1,421 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include "PlatformInternal.h"
#include <string>
#include <vector>
#include <map>
#include <cstdio>
using namespace std;
#include "SHMProcess.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include <errno.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <time.h>
#include <shms.h>
#include <mod-core.h>
#include <sys/time.h>
#include <time.h>
#include <sched.h>
#include <md5wrapper.h>
using namespace DFHack;
SHMProcess::Private::Private(SHMProcess * self_)
{
memdescriptor = NULL;
process_ID = 0;
shm_ID = -1;
attached = false;
identified = false;
useYield = false;
server_lock = -1;
client_lock = -1;
suspend_lock = -1;
locked = false;
self = self_;
}
bool SHMProcess::Private::SetAndWait (uint32_t state)
{
uint32_t cnt = 0;
if(!attached) return false;
SHMCMD = state;
while (SHMCMD == state)
{
// yield the CPU, only on single-core CPUs
if(useYield)
{
SCHED_YIELD
}
if(cnt == 10000)
{
if(!AreLocksOk())// DF not there anymore?
{
//detach the shared memory
shmdt(shm_addr);
FreeLocks();
attached = locked = identified = false;
// we aren't the current process anymore
throw Error::SHMServerDisappeared();
}
else
{
cnt = 0;
}
}
cnt++;
}
// server returned a generic error
if(SHMCMD == CORE_ERROR)
{
return false;
}
return true;
}
/*
Yeah. with no way to synchronize things (locks are slow, the OS doesn't give us
enough control over scheduling)
we end up with this silly thing
*/
bool SHMProcess::SetAndWait (uint32_t state)
{
return d->SetAndWait(state);
}
uint32_t OS_getAffinity()
{
cpu_set_t mask;
sched_getaffinity(0,sizeof(cpu_set_t),&mask);
// FIXME: truncation
uint32_t affinity = *(uint32_t *) &mask;
return affinity;
}
void SHMProcess::Private::FreeLocks()
{
attachmentIdx = -1;
if(client_lock != -1)
{
lockf(client_lock,F_ULOCK,0);
close(client_lock);
client_lock = -1;
}
if(server_lock != -1)
{
close(server_lock);
server_lock = -1;
}
if(suspend_lock != -1)
{
close(suspend_lock);
locked = false;
suspend_lock = -1;
}
}
bool SHMProcess::Private::GetLocks()
{
char name[256];
// try to acquire locks
// look at the server lock, if it's locked, the server is present
sprintf(name, "/tmp/DFHack/%d/SVlock",process_ID);
server_lock = open(name,O_WRONLY);
if(server_lock == -1)
{
// cerr << "can't open sv lock" << endl;
return false;
}
if(lockf( server_lock, F_TEST, 0 ) != -1)
{
cerr << "sv lock not locked" << endl;
close(server_lock);
server_lock = -1;
return false;
}
for(int i = 0; i < SHM_MAX_CLIENTS; i++)
{
// open the client suspend locked
sprintf(name, "/tmp/DFHack/%d/CLSlock%d",process_ID,i);
suspend_lock = open(name,O_WRONLY);
if(suspend_lock == -1)
{
cerr << "can't open cl S-lock " << i << endl;
// couldn't open lock
continue;
}
// open the client lock, try to lock it
sprintf(name, "/tmp/DFHack/%d/CLlock%d",process_ID,i);
client_lock = open(name,O_WRONLY);
if(client_lock == -1)
{
cerr << "can't open cl lock " << i << endl;
close(suspend_lock);
locked = false;
suspend_lock = -1;
// couldn't open lock
continue;
}
if(lockf(client_lock,F_TLOCK, 0) == -1)
{
// couldn't acquire lock
cerr << "can't acquire cl lock " << i << endl;
close(suspend_lock);
locked = false;
suspend_lock = -1;
close(client_lock);
client_lock = -1;
continue;
}
// ok, we have all the locks we need!
attachmentIdx = i;
return true;
}
close(server_lock);
server_lock = -1;
cerr << "can't get any client locks" << endl;
return false;
}
// test if we have client and server locks and the server is present
bool SHMProcess::Private::AreLocksOk()
{
// both locks are inited (we hold our lock)
if(client_lock != -1 && server_lock != -1)
{
if(lockf(server_lock,F_TEST,0) == -1) // and server holds its lock
{
return true; // OK, locks are good
}
}
// locks are bad
return false;
}
bool SHMProcess::Private::validate(VersionInfoFactory * factory)
{
char exe_link_name [256];
char target_name[1024];
int target_result;
// find the binary
sprintf(exe_link_name,"/proc/%d/exe", process_ID);
target_result = readlink(exe_link_name, target_name, sizeof(target_name)-1);
if (target_result == -1)
{
perror("readlink");
return false;
}
// make sure we have a null terminated string...
// see http://www.opengroup.org/onlinepubs/000095399/functions/readlink.html
target_name[target_result] = 0;
// get hash of the running DF process
md5wrapper md5;
string hash = md5.getHashFromFile(target_name);
// create linux process, add it to the vector
VersionInfo * vinfo = factory->getVersionInfoByMD5(hash);
if(vinfo)
{
memdescriptor = vinfo;
// FIXME: BIG BAD BUG RIGHT HERE!!!!
memdescriptor->setParentProcess(self);
identified = true;
vector_start = memdescriptor->getGroup("vector")->getOffset("start");
return true;
}
return false;
}
// there is only one we care about.
bool SHMProcess::getThreadIDs(vector<uint32_t> & threads )
{
if(d->attached)
{
threads.clear();
threads.push_back(d->process_ID);
return true;
}
return false;
}
//FIXME: cross-reference with ELF segment entries?
void SHMProcess::getMemRanges( vector<t_memrange> & ranges )
{
char buffer[1024];
char permissions[5]; // r/-, w/-, x/-, p/s, 0
sprintf(buffer, "/proc/%lu/maps", (long unsigned)d->process_ID);
FILE *mapFile = ::fopen(buffer, "r");
uint64_t offset, device1, device2, node;
while (fgets(buffer, 1024, mapFile))
{
t_memrange temp;
temp.name[0] = 0;
sscanf(buffer, "%zx-%zx %s %zx %2zu:%2zu %zu %s",
&temp.start,
&temp.end,
(char*)&permissions,
&offset, &device1, &device2, &node,
(char*)&temp.name);
temp.read = permissions[0] == 'r';
temp.write = permissions[1] == 'w';
temp.execute = permissions[2] == 'x';
temp.valid = true;
ranges.push_back(temp);
}
}
bool SHMProcess::acquireSuspendLock()
{
return (lockf(d->suspend_lock,F_LOCK,0) == 0);
}
bool SHMProcess::releaseSuspendLock()
{
return (lockf(d->suspend_lock,F_ULOCK,0) == 0);
}
bool SHMProcess::attach()
{
if(d->attached)
{
if(!d->locked)
return suspend();
return true;
}
//cerr << "attach" << endl;// FIXME: throw
if(!d->GetLocks())
{
//cerr << "server is full or not really there!" << endl;
return false;
}
/*
* Locate the segment.
*/
if ((d->shm_ID = shmget(SHM_KEY + d->process_ID, SHM_SIZE, 0666)) < 0)
{
d->FreeLocks();
cerr << "can't find segment" << endl; // FIXME: throw
return false;
}
/*
* Attach the segment
*/
if ((d->shm_addr = (char *) shmat(d->shm_ID, NULL, 0)) == (char *) -1)
{
d->FreeLocks();
cerr << "can't attach segment" << endl; // FIXME: throw
return false;
}
d->attached = true;
if(!suspend())
{
shmdt(d->shm_addr);
d->FreeLocks();
cerr << "unable to suspend" << endl;
return false;
}
return true;
}
bool SHMProcess::detach()
{
if(!d->attached) return true;
if(d->locked)
{
resume();
}
// detach segment
if(shmdt(d->shm_addr) != -1)
{
d->FreeLocks();
d->locked = false;
d->attached = false;
d->shm_addr = 0;
return true;
}
// fail if we can't detach
// FIXME: throw exception here??
perror("failed to detach shared segment");
return false;
}
void SHMProcess::readSTLVector(const uint32_t address, t_vecTriplet & triplet)
{
read(address + d->vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
void SHMProcess::writeSTLVector(const uint32_t address, t_vecTriplet & triplet)
{
write(address + d->vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
string SHMProcess::doReadClassName (uint32_t vptr)
{
if(!d->locked) throw Error::MemoryAccessDenied(vptr);
int typeinfo = Process::readDWord(vptr - 0x4);
int typestring = Process::readDWord(typeinfo + 0x4);
string raw = readCString(typestring);
size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers
size_t end = raw.length();
return raw.substr(start,end-start);
}
string SHMProcess::getPath()
{
char cwd_name[256];
char target_name[1024];
int target_result;
sprintf(cwd_name,"/proc/%d/cwd", getPID());
// resolve /proc/PID/exe link
target_result = readlink(cwd_name, target_name, sizeof(target_name));
target_name[target_result] = '\0';
return(string(target_name));
}
char * SHMProcess::getSHMStart (void)
{
if(!d->locked) return 0; //THROW HERE!
return d->shm_addr;
}

@ -1,326 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include "PlatformInternal.h"
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <cstdio>
using namespace std;
#include "LinuxProcess.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include <errno.h>
#include <sys/ptrace.h>
using namespace DFHack;
LinuxProcessBase::LinuxProcessBase(uint32_t pid)
: my_pid(pid)
{
my_descriptor = NULL;
attached = false;
suspended = false;
memFileHandle = 0;
}
bool LinuxProcessBase::isSuspended()
{
return suspended;
}
bool LinuxProcessBase::isAttached()
{
return attached;
}
bool LinuxProcessBase::isIdentified()
{
return identified;
}
LinuxProcessBase::~LinuxProcessBase()
{
// destroy our copy of the memory descriptor
if(my_descriptor)
delete my_descriptor;
}
VersionInfo * LinuxProcessBase::getDescriptor()
{
return my_descriptor;
}
int LinuxProcessBase::getPID()
{
return my_pid;
}
int getdir (string dir, vector<string> &files)
{
DIR *dp;
struct dirent *dirp;
if((dp = opendir(dir.c_str())) == NULL) {
cout << "Error(" << errno << ") opening " << dir << endl;
return errno;
}
while ((dirp = readdir(dp)) != NULL) {
files.push_back(string(dirp->d_name));
}
closedir(dp);
return 0;
}
bool LinuxProcessBase::getThreadIDs(vector<uint32_t> & threads )
{
stringstream ss;
vector<string> subdirs;
ss << "/proc/" << my_pid << "/task/";
if(getdir(ss.str(),subdirs) != 0)
{
//FIXME: needs exceptions. this is a fatal error
cerr << "unable to enumerate threads. This is BAD!" << endl;
return false;
}
threads.clear();
for(size_t i = 0; i < subdirs.size();i++)
{
uint32_t tid;
if(sscanf(subdirs[i].c_str(),"%d", &tid))
{
threads.push_back(tid);
}
}
return true;
}
//FIXME: cross-reference with ELF segment entries?
void LinuxProcessBase::getMemRanges( vector<t_memrange> & ranges )
{
char buffer[1024];
char permissions[5]; // r/-, w/-, x/-, p/s, 0
sprintf(buffer, "/proc/%lu/maps", (long unsigned)my_pid);
FILE *mapFile = ::fopen(buffer, "r");
size_t start, end, offset, device1, device2, node;
while (fgets(buffer, 1024, mapFile))
{
t_memrange temp;
temp.name[0] = 0;
sscanf(buffer, "%zx-%zx %s %zx %2zu:%2zu %zu %[^\n]s",
&start,
&end,
(char*)&permissions,
&offset, &device1, &device2, &node,
(char*)&temp.name);
temp.start = start;
temp.end = end;
temp.read = permissions[0] == 'r';
temp.write = permissions[1] == 'w';
temp.execute = permissions[2] == 'x';
temp.shared = permissions[3] == 's';
temp.valid = true;
ranges.push_back(temp);
}
}
void LinuxProcessBase::read (const uint32_t offset, const uint32_t size, uint8_t *target)
{
if(size == 0) return;
ssize_t result;
ssize_t total = 0;
ssize_t remaining = size;
while (total != size)
{
result = pread(memFileHandle, target + total ,remaining,offset + total);
if(result == -1)
{
cerr << "pread failed: can't read " << size << " bytes at addres " << offset << endl;
cerr << "errno: " << errno << endl;
errno = 0;
throw Error::MemoryAccessDenied(offset);
}
else
{
total += result;
remaining -= result;
}
}
}
void LinuxProcessBase::readByte (const uint32_t offset, uint8_t &val )
{
read(offset, 1, &val);
}
void LinuxProcessBase::readWord (const uint32_t offset, uint16_t &val)
{
read(offset, 2, (uint8_t *) &val);
}
void LinuxProcessBase::readDWord (const uint32_t offset, uint32_t &val)
{
read(offset, 4, (uint8_t *) &val);
}
void LinuxProcessBase::readFloat (const uint32_t offset, float &val)
{
read(offset, 4, (uint8_t *) &val);
}
void LinuxProcessBase::readQuad (const uint32_t offset, uint64_t &val)
{
read(offset, 8, (uint8_t *) &val);
}
/*
* WRITING
*/
void LinuxProcessBase::writeQuad (uint32_t offset, const uint64_t data)
{
#ifdef HAVE_64_BIT
ptrace(PTRACE_POKEDATA,my_pid, offset, data);
#else
ptrace(PTRACE_POKEDATA,my_pid, offset, (uint32_t) data);
ptrace(PTRACE_POKEDATA,my_pid, offset+4, (uint32_t) (data >> 32));
#endif
}
void LinuxProcessBase::writeDWord (uint32_t offset, uint32_t data)
{
#ifdef HAVE_64_BIT
uint64_t orig = Process::readQuad(offset);
orig &= 0xFFFFFFFF00000000;
orig |= data;
ptrace(PTRACE_POKEDATA,my_pid, offset, orig);
#else
ptrace(PTRACE_POKEDATA,my_pid, offset, data);
#endif
}
// using these is expensive.
void LinuxProcessBase::writeWord (uint32_t offset, uint16_t data)
{
#ifdef HAVE_64_BIT
uint64_t orig = Process::readQuad(offset);
orig &= 0xFFFFFFFFFFFF0000;
orig |= data;
ptrace(PTRACE_POKEDATA,my_pid, offset, orig);
#else
uint32_t orig = Process::readDWord(offset);
orig &= 0xFFFF0000;
orig |= data;
ptrace(PTRACE_POKEDATA,my_pid, offset, orig);
#endif
}
void LinuxProcessBase::writeByte (uint32_t offset, uint8_t data)
{
#ifdef HAVE_64_BIT
uint64_t orig = Process::readQuad(offset);
orig &= 0xFFFFFFFFFFFFFF00;
orig |= data;
ptrace(PTRACE_POKEDATA,my_pid, offset, orig);
#else
uint32_t orig = Process::readDWord(offset);
orig &= 0xFFFFFF00;
orig |= data;
ptrace(PTRACE_POKEDATA,my_pid, offset, orig);
#endif
}
// blah. THIS IS RIDICULOUS
void LinuxProcessBase::write (uint32_t offset, uint32_t size, uint8_t *source)
{
uint32_t indexptr = 0;
while (size > 0)
{
#ifdef HAVE_64_BIT
// quad!
if(size >= 8)
{
writeQuad(offset, *(uint64_t *) (source + indexptr));
offset +=8;
indexptr +=8;
size -=8;
}
else
#endif
// default: we push 4 bytes
if(size >= 4)
{
writeDWord(offset, *(uint32_t *) (source + indexptr));
offset +=4;
indexptr +=4;
size -=4;
}
// last is either three or 2 bytes
else if(size >= 2)
{
writeWord(offset, *(uint16_t *) (source + indexptr));
offset +=2;
indexptr +=2;
size -=2;
}
// finishing move
else if(size == 1)
{
writeByte(offset, *(uint8_t *) (source + indexptr));
return;
}
}
}
const std::string LinuxProcessBase::readCString (uint32_t offset)
{
std::string temp;
int counter = 0;
char r;
while (1)
{
r = Process::readByte(offset+counter);
if(!r) break;
counter++;
temp.append(1,r);
}
return temp;
}
string LinuxProcessBase::getPath()
{
char cwd_name[256];
char target_name[1024];
int target_result;
sprintf(cwd_name,"/proc/%d/cwd", getPID());
// resolve /proc/PID/exe link
target_result = readlink(cwd_name, target_name, sizeof(target_name));
target_name[target_result] = '\0';
return(string(target_name));
}

@ -1,280 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include "PlatformInternal.h"
#include <string>
#include <vector>
#include <map>
#include <cstdio>
#include <cstring>
#include <fstream>
using namespace std;
#include "LinuxProcess.h"
#include "ProcessFactory.h"
#include "MicrosoftSTL.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
using namespace DFHack;
#include <errno.h>
#include <sys/ptrace.h>
#include <md5wrapper.h>
namespace {
class WineProcess : public LinuxProcessBase
{
private:
uint8_t vector_start;
MicrosoftSTL stl;
public:
WineProcess(uint32_t pid, VersionInfoFactory * factory);
~WineProcess()
{
if(attached)
{
detach();
}
}
bool attach();
bool detach();
bool suspend();
bool asyncSuspend();
bool resume();
bool forceresume();
void readSTLVector(const uint32_t address, t_vecTriplet & triplet);
void writeSTLVector(const uint32_t address, t_vecTriplet & triplet);
const std::string readSTLString (uint32_t offset);
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity);
size_t writeSTLString(const uint32_t address, const std::string writeString);
// get class name of an object with rtti/type info
std::string doReadClassName(uint32_t vptr);
};
}
Process* DFHack::createWineProcess(uint32_t pid, VersionInfoFactory * factory)
{
return new WineProcess(pid, factory);
}
WineProcess::WineProcess(uint32_t pid, VersionInfoFactory * factory) : LinuxProcessBase(pid)
{
char dir_name [256];
char exe_link_name [256];
char mem_name [256];
char cwd_name [256];
char cmdline_name [256];
char target_name[1024];
int target_result;
identified = false;
my_descriptor = 0;
sprintf(dir_name,"/proc/%d/", pid);
sprintf(exe_link_name,"/proc/%d/exe", pid);
sprintf(mem_name,"/proc/%d/mem", pid);
memFile = mem_name;
sprintf(cwd_name,"/proc/%d/cwd", pid);
sprintf(cmdline_name,"/proc/%d/cmdline", pid);
// resolve /proc/PID/exe link
target_result = readlink(exe_link_name, target_name, sizeof(target_name)-1);
if (target_result == -1)
{
return;
}
// make sure we have a null terminated string...
target_name[target_result] = 0;
// FIXME: this fails when the wine process isn't started from the 'current working directory'. strip path data from cmdline
// is this windows version of Df running in wine?
if(strstr(target_name, "wine-preloader")!= NULL)
{
// get working directory
target_result = readlink(cwd_name, target_name, sizeof(target_name)-1);
target_name[target_result] = 0;
// got path to executable, do the same for its name
ifstream ifs ( cmdline_name , ifstream::in );
string cmdline;
getline(ifs,cmdline);
if (cmdline.find("dwarfort-w.exe") != string::npos || cmdline.find("dwarfort.exe") != string::npos || cmdline.find("Dwarf Fortress.exe") != string::npos)
{
char exe_link[1024];
// put executable name and path together
sprintf(exe_link,"%s/%s",target_name,cmdline.c_str());
md5wrapper md5;
// get hash of the running DF process
string hash = md5.getHashFromFile(exe_link);
// create linux process, add it to the vector
VersionInfo * vinfo = factory->getVersionInfoByMD5(hash);
if(vinfo)
{
my_descriptor = new VersionInfo(*vinfo);
my_descriptor->setParentProcess(this);
vector_start = my_descriptor->getGroup("vector")->getOffset("start");
stl.init(this);
identified = true;
}
return;
}
}
}
void WineProcess::readSTLVector(const uint32_t address, t_vecTriplet & triplet)
{
read(address + vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
void WineProcess::writeSTLVector(const uint32_t address, t_vecTriplet & triplet)
{
write(address + vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
size_t WineProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
return stl.readSTLString(offset, buffer, bufcapacity);
}
size_t WineProcess::writeSTLString(const uint32_t address, const std::string writeString)
{
return stl.writeSTLString(address,writeString);
}
const string WineProcess::readSTLString (uint32_t offset)
{
return stl.readSTLString(offset);
}
string WineProcess::doReadClassName (uint32_t vptr)
{
return stl.readClassName(vptr);
}
bool WineProcess::asyncSuspend()
{
return suspend();
}
bool WineProcess::suspend()
{
int status;
if(suspended)
return true;
// can we attach?
if (ptrace(PTRACE_ATTACH , my_pid, NULL, NULL) == -1)
{
// no, we got an error
perror("ptrace attach error");
cerr << "attach failed on pid " << my_pid << endl;
return false;
}
while(true)
{
// we wait on the pid
pid_t w = waitpid(my_pid, &status, 0);
if (w == -1)
{
// child died
perror("wait inside attach()");
return false;
}
// stopped -> let's continue
if (WIFSTOPPED(status))
{
break;
}
}
int proc_pid_mem = open(memFile.c_str(),O_RDONLY);
if(proc_pid_mem == -1)
{
ptrace(PTRACE_DETACH, my_pid, NULL, NULL);
cerr << memFile << endl;
cerr << "couldn't open /proc/" << my_pid << "/mem" << endl;
perror("open(memFile.c_str(),O_RDONLY)");
return false;
}
else
{
attached = suspended = true;
memFileHandle = proc_pid_mem;
return true; // we are attached
}
}
bool WineProcess::forceresume()
{
return resume();
}
bool WineProcess::resume()
{
if(!suspended)
return true;
int result = 0;
// close /proc/PID/mem
result = close(memFileHandle);
if(result == -1)
{
cerr << "couldn't close /proc/"<< my_pid <<"/mem" << endl;
perror("mem file close");
return false;
}
else
{
// detach
result = ptrace(PTRACE_DETACH, my_pid, NULL, NULL);
if(result == -1)
{
cerr << "couldn't detach from process pid" << my_pid << endl;
perror("ptrace detach");
return false;
}
else
{
attached = suspended = false;
return true;
}
}
}
bool WineProcess::attach()
{
if(suspended) return true;
return suspend();
}
bool WineProcess::detach()
{
if(!suspended) return true;
return resume();
}

@ -1,410 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include "PlatformInternal.h"
#include <string>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
using namespace std;
#include "LinuxProcess.h"
#include "ProcessFactory.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include <errno.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <md5wrapper.h>
using namespace DFHack;
namespace {
class NormalProcess : public LinuxProcessBase
{
private:
uint8_t vector_start;
set <uint32_t> thread_ids;
void waitForSuspend(set<uint32_t> &threads);
public:
NormalProcess(uint32_t pid, VersionInfoFactory * known_versions);
~NormalProcess()
{
if(attached)
{
detach();
}
}
bool attach();
bool detach();
bool suspend();
bool asyncSuspend();
bool resume();
bool forceresume();
void readSTLVector(const uint32_t address, t_vecTriplet & triplet);
void writeSTLVector(const uint32_t address, t_vecTriplet & triplet);
const std::string readSTLString (uint32_t offset);
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity);
size_t writeSTLString(const uint32_t address, const std::string writeString);
size_t copySTLString(const uint32_t address, const uint32_t target);
// get class name of an object with rtti/type info
std::string doReadClassName(uint32_t vptr);
};
}
Process* DFHack::createNormalProcess(uint32_t pid, VersionInfoFactory * known_versions)
{
return new NormalProcess(pid, known_versions);
}
NormalProcess::NormalProcess(uint32_t pid, VersionInfoFactory * known_versions) : LinuxProcessBase(pid)
{
char dir_name [256];
char exe_link_name [256];
char mem_name [256];
char cwd_name [256];
char cmdline_name [256];
char target_name[1024];
int target_result;
identified = false;
my_descriptor = 0;
sprintf(dir_name,"/proc/%d/", pid);
sprintf(exe_link_name,"/proc/%d/exe", pid);
sprintf(mem_name,"/proc/%d/mem", pid);
memFile = mem_name;
sprintf(cwd_name,"/proc/%d/cwd", pid);
sprintf(cmdline_name,"/proc/%d/cmdline", pid);
// resolve /proc/PID/exe link
target_result = readlink(exe_link_name, target_name, sizeof(target_name)-1);
if (target_result == -1)
{
return;
}
// make sure we have a null terminated string...
target_name[target_result] = 0;
// is this the regular linux DF?
if (strstr(target_name, "dwarfort.exe") != 0 || strstr(target_name,"Dwarf_Fortress") != 0)
{
md5wrapper md5;
// get hash of the running DF process
string hash = md5.getHashFromFile(target_name);
// create linux process, add it to the vector
VersionInfo * vinfo = known_versions->getVersionInfoByMD5(hash);
if(vinfo)
{
my_descriptor = new VersionInfo(*vinfo);
my_descriptor->setParentProcess(this);
vector_start = my_descriptor->getGroup("vector")->getOffset("start");
identified = true;
}
}
}
struct _Rep_base
{
uint32_t _M_length; // length of text stored, not including zero termination
uint32_t _M_capacity; // capacity, not including zero termination
int32_t _M_refcount; // reference count (two STL strings can share a common buffer, copy on write rules apply)
};
size_t NormalProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
_Rep_base header;
offset = Process::readDWord(offset);
read(offset - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header);
size_t read_real = min((size_t)header._M_length, bufcapacity-1);// keep space for null termination
read(offset,read_real,(uint8_t * )buffer);
buffer[read_real] = 0;
return read_real;
}
size_t NormalProcess::writeSTLString(const uint32_t address, const std::string writeString)
{
_Rep_base header;
// get buffer location
uint32_t start = Process::readDWord(address);
// read the header
read(start - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header);
// the buffer has actual size = 1. no space for storing anything more than a zero byte
if(header._M_capacity == 0)
return 0;
if(header._M_refcount > 0 ) // one ref or one non-shareable (-1) ref
return 0;
// get writeable length (lesser of our string length and capacity of the target)
uint32_t lstr = writeString.length();
uint32_t allowed_copy = min(lstr, header._M_capacity);
// write header with new length.
header._M_length = allowed_copy;
write(start - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header);
// write string, add a zero terminator, return bytes written
write(start, allowed_copy, (uint8_t *) writeString.c_str());
writeByte(start + allowed_copy, 0);
return allowed_copy;
}
void NormalProcess::readSTLVector(const uint32_t address, t_vecTriplet & triplet)
{
read(address + vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
void NormalProcess::writeSTLVector(const uint32_t address, t_vecTriplet & triplet)
{
write(address + vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
const string NormalProcess::readSTLString (uint32_t offset)
{
_Rep_base header;
offset = Process::readDWord(offset);
read(offset - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header);
// FIXME: use char* everywhere, avoid string
char * temp = new char[header._M_length+1];
read(offset,header._M_length+1,(uint8_t * )temp);
string ret(temp);
delete temp;
return ret;
}
size_t NormalProcess::copySTLString (uint32_t offset, uint32_t target)
{
_Rep_base header;
offset = Process::readDWord(offset);
uint32_t old_target = Process::readDWord(target);
if (offset == old_target)
return 0;
read(offset - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header);
// destroying the leaked state
if (header._M_refcount == -1)
header._M_refcount = 1;
else
header._M_refcount++;
write(offset - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header);
writeDWord(target, offset);
return header._M_length;
}
string NormalProcess::doReadClassName (uint32_t vptr)
{
int typeinfo = Process::readDWord(vptr - 0x4);
int typestring = Process::readDWord(typeinfo + 0x4);
string raw = readCString(typestring);
size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers
size_t end = raw.length();
return raw.substr(start,end-start);
}
bool NormalProcess::asyncSuspend()
{
return suspend();
}
bool NormalProcess::suspend()
{
if(!attached)
return false;
if(suspended)
return true;
set<uint32_t> threads;
for (set<uint32_t>::iterator it = thread_ids.begin(); it != thread_ids.end(); ++it) {
if (syscall(SYS_tgkill, my_pid, *it, SIGSTOP) == -1) {
cerr << "couldn't stop thread " << *it << endl;
perror("kill SIGSTOP error");
} else {
threads.insert(*it);
}
}
if (threads.empty()) {
cerr << "couldn't suspend any of the threads";
return false;
}
waitForSuspend(threads);
if (!threads.empty())
cerr << "couldn't suspend some of the threads";
suspended = true;
return true;
}
bool NormalProcess::forceresume()
{
return resume();
}
bool NormalProcess::resume()
{
if(!attached)
return false;
if(!suspended)
return true;
bool ok = true;
for (set<uint32_t>::iterator it = thread_ids.begin(); it != thread_ids.end(); ++it) {
int result = ptrace(PTRACE_CONT, *it, NULL, NULL);
if(result == -1)
{
cerr << "couldn't resume thread " << *it << endl;
perror("ptrace resume error");
ok = false;
}
}
if (ok)
suspended = false;
return ok;
}
void NormalProcess::waitForSuspend(set<uint32_t> &threads)
{
int status;
while (!threads.empty()) {
pid_t w = waitpid(-1, &status, __WALL);
if (w == -1) {
perror("waitpid");
return;
}
if (threads.find(w) == threads.end()
&& thread_ids.find(w) == thread_ids.end())
continue;
if (WIFSTOPPED(status)) {
threads.erase(w);
thread_ids.insert(w);
} else if (WIFEXITED(status) || WIFSIGNALED(status)) {
threads.erase(w);
thread_ids.erase(w);
}
}
}
bool NormalProcess::attach()
{
if(attached)
{
if(!suspended)
return suspend();
return true;
}
set<uint32_t> threads;
vector<uint32_t> thread_vec;
if (!getThreadIDs(thread_vec))
return false;
for (vector<uint32_t>::iterator it = thread_vec.begin(); it != thread_vec.end(); ++it) {
if (ptrace(PTRACE_ATTACH, *it, NULL, NULL) == -1)
{
// no, we got an error
perror("ptrace attach error");
cerr << "attach failed on pid " << *it << endl;
continue;
}
threads.insert(*it);
}
thread_ids.clear();
waitForSuspend(threads);
if (thread_ids.empty()) {
cerr << "couldn't attach to any threads" << endl;
return false;
}
if (!threads.empty())
cerr << "couldn't attach to some threads" << endl;
suspended = true;
int proc_pid_mem = open(memFile.c_str(),O_RDONLY);
if(proc_pid_mem == -1)
{
ptrace(PTRACE_DETACH, my_pid, NULL, NULL);
cerr << memFile << endl;
cerr << "couldn't open /proc/" << my_pid << "/mem" << endl;
perror("open(memFile.c_str(),O_RDONLY)");
return false;
}
else
{
attached = true;
memFileHandle = proc_pid_mem;
return true; // we are attached
}
}
bool NormalProcess::detach()
{
if(!attached) return true;
if(!suspended) suspend();
int result = 0;
// close /proc/PID/mem
result = close(memFileHandle);
if(result == -1)
{
cerr << "couldn't close /proc/"<< my_pid <<"/mem" << endl;
perror("mem file close");
return false;
}
else
{
for (set<uint32_t>::iterator it = thread_ids.begin(); it != thread_ids.end();) {
// detach
result = ptrace(PTRACE_DETACH, *it, NULL, NULL);
if(result == -1)
{
cerr << "couldn't detach from process pid" << *it << endl;
perror("ptrace detach");
return false;;
}
thread_ids.erase(it++);
}
attached = false;
return true;
}
}

@ -1,428 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include "PlatformInternal.h"
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <string>
#include <map>
using namespace std;
#include "SHMProcess.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include "shms.h"
#include "mod-core.h"
using namespace DFHack;
SHMProcess::Private::Private(SHMProcess * self_)
{
memdescriptor = NULL;
process_ID = 0;
attached = false;
locked = false;
identified = false;
useYield = 0;
DFSVMutex = 0;
DFCLMutex = 0;
DFCLSuspendMutex = 0;
self = self_;
}
bool SHMProcess::Private::SetAndWait (uint32_t state)
{
uint32_t cnt = 0;
if(!attached) return false;
SHMCMD = state;
while (SHMCMD == state)
{
// yield the CPU, only on single-core CPUs
if(useYield)
{
SCHED_YIELD
}
if(cnt == 10000)
{
if(!AreLocksOk())// DF not there anymore?
{
UnmapViewOfFile(shm_addr);
FreeLocks();
attached = locked = identified = false;
// we aren't the current process anymore
throw Error::SHMServerDisappeared();
}
else
{
cnt = 0;
}
}
cnt++;
}
// server returned a generic error
if(SHMCMD == CORE_ERROR)
{
return false;
}
return true;
}
bool SHMProcess::SetAndWait (uint32_t state)
{
return d->SetAndWait(state);
}
uint32_t OS_getAffinity()
{
HANDLE hProcess = GetCurrentProcess();
DWORD dwProcessAffinityMask, dwSystemAffinityMask;
GetProcessAffinityMask( hProcess, &dwProcessAffinityMask, &dwSystemAffinityMask );
return dwProcessAffinityMask;
}
void SHMProcess::Private::FreeLocks()
{
attachmentIdx = -1;
if(DFCLMutex != 0)
{
ReleaseMutex(DFCLMutex);
CloseHandle(DFCLMutex);
DFCLMutex = 0;
}
if(DFSVMutex != 0)
{
CloseHandle(DFSVMutex);
DFSVMutex = 0;
}
if(DFCLSuspendMutex != 0)
{
ReleaseMutex(DFCLSuspendMutex);
CloseHandle(DFCLSuspendMutex);
// FIXME: maybe also needs ReleaseMutex!
DFCLSuspendMutex = 0;
locked = false;
}
}
bool SHMProcess::Private::GetLocks()
{
char name[256];
// try to acquire locks
// look at the server lock, if it's locked, the server is present
sprintf(name,"DFSVMutex-%d",process_ID);
DFSVMutex = OpenMutex(SYNCHRONIZE,0, name);
if(DFSVMutex == 0)
{
// cerr << "can't open sv lock" << endl;
return false;
}
// unlike the F_TEST of lockf, this one actually locks. we have to release
if(WaitForSingleObject(DFSVMutex,0) == 0)
{
ReleaseMutex(DFSVMutex);
// cerr << "sv lock not locked" << endl;
CloseHandle(DFSVMutex);
DFSVMutex = 0;
return false;
}
for(int i = 0; i < SHM_MAX_CLIENTS; i++)
{
// open the client suspend locked
sprintf(name, "DFCLSuspendMutex-%d-%d",process_ID,i);
DFCLSuspendMutex = OpenMutex(SYNCHRONIZE,0, name);
if(DFCLSuspendMutex == 0)
{
//cerr << "can't open cl S-lock " << i << endl;
// couldn't open lock
continue;
}
// open the client lock, try to lock it
sprintf(name,"DFCLMutex-%d-%d",process_ID,i);
DFCLMutex = OpenMutex(SYNCHRONIZE,0,name);
if(DFCLMutex == 0)
{
//cerr << "can't open cl lock " << i << endl;
CloseHandle(DFCLSuspendMutex);
locked = false;
DFCLSuspendMutex = 0;
continue;
}
uint32_t waitstate = WaitForSingleObject(DFCLMutex,0);
if(waitstate == WAIT_FAILED || waitstate == WAIT_TIMEOUT )
{
//cerr << "can't acquire cl lock " << i << endl;
CloseHandle(DFCLSuspendMutex);
locked = false;
DFCLSuspendMutex = 0;
CloseHandle(DFCLMutex);
DFCLMutex = 0;
continue;
}
// ok, we have all the locks we need!
attachmentIdx = i;
return true;
}
CloseHandle(DFSVMutex);
DFSVMutex = 0;
// cerr << "can't get any client locks" << endl;
return false;
}
// is the other side still there?
bool SHMProcess::Private::AreLocksOk()
{
// both locks are inited (we hold our lock)
if(DFCLMutex != 0 && DFSVMutex != 0)
{
// try if CL mutex is free
switch (WaitForSingleObject(DFSVMutex,0))
{
case WAIT_ABANDONED:
case WAIT_OBJECT_0:
{
ReleaseMutex(DFSVMutex);
return false;
}
case WAIT_TIMEOUT:
{
// mutex is held by DF
return true;
}
default:
case WAIT_FAILED:
{
// TODO: now how do I respond to this?
return false;
}
}
}
return false;
}
bool SHMProcess::Private::validate(VersionInfoFactory * factory)
{
// try to identify the DF version
IMAGE_NT_HEADERS pe_header;
IMAGE_SECTION_HEADER sections[16];
HMODULE hmod = NULL;
DWORD junk;
HANDLE hProcess;
bool found = false;
identified = false;
// open process, we only need the process open
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, process_ID );
if (NULL == hProcess)
return false;
// try getting the first module of the process
if(EnumProcessModules(hProcess, &hmod, 1 * sizeof(HMODULE), &junk) == 0)
{
CloseHandle(hProcess);
// cout << "EnumProcessModules fail'd" << endl;
return false;
}
// got base ;)
uint32_t base = (uint32_t)hmod;
// read from this process
uint32_t pe_offset = self->Process::readDWord(base+0x3C);
self->read(base + pe_offset , sizeof(pe_header), (uint8_t *)&pe_header);
self->read(base + pe_offset+ sizeof(pe_header), sizeof(sections) , (uint8_t *)&sections );
VersionInfo* vinfo = factory->getVersionInfoByPETimestamp(pe_header.FileHeader.TimeDateStamp);
if(vinfo)
{
VersionInfo *m = new VersionInfo(*vinfo);
m->RebaseAll(base);
memdescriptor = m;
m->setParentProcess(self);
identified = true;
vector_start = memdescriptor->getGroup("vector")->getOffset("start");
CloseHandle(hProcess);
return true;
}
return false;
}
bool SHMProcess::getThreadIDs(vector<uint32_t> & threads )
{
HANDLE AllThreads = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;
AllThreads = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( AllThreads == INVALID_HANDLE_VALUE )
{
return false;
}
te32.dwSize = sizeof(THREADENTRY32 );
if( !Thread32First( AllThreads, &te32 ) )
{
CloseHandle( AllThreads );
return false;
}
do
{
if( te32.th32OwnerProcessID == d->process_ID )
{
threads.push_back(te32.th32ThreadID);
}
} while( Thread32Next(AllThreads, &te32 ) );
CloseHandle( AllThreads );
return true;
}
//FIXME: use VirtualQuery to probe for memory ranges, cross-reference with base-corrected PE segment entries
void SHMProcess::getMemRanges( vector<t_memrange> & ranges )
{
// BLAH
ranges.clear();
}
bool SHMProcess::acquireSuspendLock()
{
return ( WaitForSingleObject(d->DFCLSuspendMutex,INFINITE) == 0 );
}
bool SHMProcess::releaseSuspendLock()
{
return ( ReleaseMutex(d->DFCLSuspendMutex) != 0);
}
bool SHMProcess::attach()
{
if(d->attached)
{
if(!d->locked)
return suspend();
return true;
}
//cerr << "attach" << endl;// FIXME: throw
if(!d->GetLocks())
{
//cerr << "server is full or not really there!" << endl;
return false;
}
/*
* Locate the segment.
*/
char shmname [256];
sprintf(shmname,"DFShm-%d",d->process_ID);
HANDLE shmHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS,false,shmname);
if(!shmHandle)
{
d->FreeLocks();
//ReleaseMutex(d->DFCLMutex);
return false; // we couldn't lock it
}
/*
* Attach the segment
*/
d->shm_addr = (char *) MapViewOfFile(shmHandle,FILE_MAP_ALL_ACCESS, 0,0, SHM_SIZE);
if(!d->shm_addr)
{
CloseHandle(shmHandle);
//ReleaseMutex(d->DFCLMutex);
d->FreeLocks();
return false; // we couldn't attach the mapping // FIXME: throw
}
// we close the handle right here - it's not needed anymore
CloseHandle(shmHandle);
d->attached = true;
if(!suspend())
{
UnmapViewOfFile(d->shm_addr);
d->FreeLocks();
//cerr << "unable to suspend" << endl;// FIXME: throw
return false;
}
return true;
}
bool SHMProcess::detach()
{
if(!d->attached) return true;
if(d->locked)
{
resume();
}
// detach segment
UnmapViewOfFile(d->shm_addr);
// release it for some other client
//ReleaseMutex(d->DFCLMutex); // we keep the mutex handles
d->FreeLocks();
d->attached = false;
d->locked = false;
d->shm_addr = false;
return true;
}
void SHMProcess::readSTLVector(const uint32_t address, t_vecTriplet & triplet)
{
read(address + d->vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
void SHMProcess::writeSTLVector(const uint32_t address, t_vecTriplet & triplet)
{
write(address + d->vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
string SHMProcess::doReadClassName (uint32_t vptr)
{
int rtti = Process::readDWord(vptr - 0x4);
int typeinfo = Process::readDWord(rtti + 0xC);
string raw = readCString(typeinfo + 0xC); // skips the .?AV
raw.resize(raw.length() - 2);// trim @@ from end
return raw;
}
string SHMProcess::getPath()
{
HMODULE hmod;
DWORD junk;
char String[255];
HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, d->process_ID ); //get the handle from the process ID
EnumProcessModules(hProcess, &hmod, 1 * sizeof(HMODULE), &junk); //get the module from the handle
GetModuleFileNameEx(hProcess,hmod,String,sizeof(String)); //get the filename from the module
string out(String);
return(out.substr(0,out.find_last_of("\\")));
}
char * SHMProcess::getSHMStart (void)
{
if(!d->locked) throw Error::MemoryAccessDenied(0xdeadbeef);
return d->shm_addr;
}

@ -1,391 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include "PlatformInternal.h"
#include <string>
#include <vector>
#include <cstdio>
#include <map>
#include <cstring>
#include <cassert>
#include <cstdlib>
using namespace std;
#include "ProcessFactory.h"
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/DFProcessEnumerator.h"
#include "dfhack/VersionInfo.h"
using namespace DFHack;
typedef std::vector<Process *> PROC_V;
typedef std::map<ProcessID, Process*> PID2PROC;
class DFHack::ProcessEnumerator::Private
{
public:
Private(){};
VersionInfoFactory *meminfo;
PROC_V Processes;
PID2PROC ProcMap;
Process *GetProcessObject(ProcessID ID);
void EnumPIDs (vector <ProcessID> &PIDs);
};
class DFHack::BadProcesses::Private
{
public:
Private(){};
PROC_V bad;
};
BadProcesses::BadProcesses():d(new Private()){}
BadProcesses::~BadProcesses()
{
clear();
delete d;
}
bool BadProcesses::Contains(Process* p)
{
for(unsigned int i = 0; i < d->bad.size(); i++)
{
if(d->bad[i] == p)
return true;
}
return false;
}
bool BadProcesses::excise(Process* p)
{
vector<Process*>::iterator it = d->bad.begin();
while(it != d->bad.end())
{
if((*it) == p)
{
d->bad.erase(it);
return true;
}
else
{
it++;
}
}
return false;
}
uint32_t BadProcesses::size()
{
return d->bad.size();
}
void BadProcesses::clear()
{
for(unsigned int i = 0; i < d->bad.size(); i++)
{
delete d->bad[i];
}
d->bad.clear();
}
void BadProcesses::push_back(Process* p)
{
if(p)
d->bad.push_back(p);
}
Process * BadProcesses::operator[](uint32_t index)
{
if(index < d->bad.size())
return d->bad[index];
return 0;
}
//FIXME: wasteful
Process *ProcessEnumerator::Private::GetProcessObject(ProcessID ID)
{
Process *p2 = createNormalProcess(ID.pid, meminfo);
if(p2->isIdentified())
{
return p2;
}
else
{
delete p2;
}
#ifdef LINUX_BUILD
Process *p3 = createWineProcess(ID.pid, meminfo);
if(p3->isIdentified())
return p3;
else
delete p3;
#endif
return 0;
}
#ifdef LINUX_BUILD
void ProcessEnumerator::Private::EnumPIDs (vector <ProcessID> &PIDs)
{
DIR *dir_p;
struct dirent *dir_entry_p;
struct stat st;
char fullname[512];
fullname[0] = 0;
PIDs.clear(); // make sure the vector is clear
// 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;
}
sprintf(fullname, "/proc/%s", dir_entry_p->d_name);
int ierr = stat (fullname, &st);
if (ierr != 0)
{
printf("Cannot stat %s: ierr= %d\n", fullname, ierr);
continue;
}
uint64_t Pnum = atoi(dir_entry_p->d_name);
uint64_t ctime = st.st_ctime;
PIDs.push_back(ProcessID(ctime,Pnum));
}
closedir(dir_p);
}
#endif
#ifndef LINUX_BUILD
// 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;
}
typedef union
{
struct
{
uint32_t LowDword;
uint32_t HighDword;
};
uint64_t Quad;
} TWO_DWORDS;
// Convert Windows FileTime structs to POSIX timestamp
// from http://frenk.wordpress.com/2009/12/14/convert-filetime-to-unix-timestamp/
uint64_t FileTime_to_POSIX(FILETIME ft)
{
// takes the last modified date
TWO_DWORDS date, adjust;
date.HighDword = ft.dwHighDateTime;
date.LowDword = ft.dwLowDateTime;
// 100-nanoseconds = milliseconds * 10000
adjust.Quad = 11644473600000LL * 10000LL;
// removes the diff between 1970 and 1601
date.Quad -= adjust.Quad;
// converts back from 100-nanoseconds to seconds
return date.Quad / 10000000LL;
}
void ProcessEnumerator::Private::EnumPIDs (vector <ProcessID> &PIDs)
{
FILETIME ftCreate, ftExit, ftKernel, ftUser;
PIDs.clear(); // make sure the vector is clear
// Get the list of process identifiers.
DWORD ProcArray[2048], memoryNeeded, numProccesses;
if(!EnableDebugPriv())
{
cerr << "Failed to acquire debug privileges." << endl;
}
if ( !EnumProcesses( ProcArray, sizeof(ProcArray), &memoryNeeded ) )
{
cerr << "EnumProcesses fail'd" << endl;
return;
}
// Calculate how many process identifiers were returned.
numProccesses = memoryNeeded / sizeof(DWORD);
//EnableDebugPriv();
// iterate through processes
for ( int i = 0; i < (int)numProccesses; i++ )
{
HANDLE proc = OpenProcess (PROCESS_QUERY_INFORMATION, false, ProcArray[i]);
if(!proc)
continue;
if(GetProcessTimes(proc, &ftCreate, &ftExit, &ftKernel, &ftUser))
{
uint64_t ctime = FileTime_to_POSIX(ftCreate);
uint64_t Pnum = ProcArray[i];
PIDs.push_back(ProcessID(ctime,Pnum));
}
CloseHandle(proc);
}
}
#endif
bool ProcessEnumerator::Refresh( BadProcesses* invalidated_processes )
{
// PIDs to process
vector <ProcessID> PIDs;
// this will be the new process map
PID2PROC temporary;
// clear the vector
d->Processes.clear();
if(invalidated_processes)
invalidated_processes->clear();
d->EnumPIDs(PIDs);
for(uint64_t i = 0; i < PIDs.size();i++)
{
ProcessID & PID = PIDs[i];
// check if we know about the OS process already
PID2PROC::iterator found= d->ProcMap.find(PID);
if( found != d->ProcMap.end())
{
// we do
// check if it does have a DFHack Process object associated with it
Process * p = (*found).second;
if(p)
{
// add it back to the vector we export
d->Processes.push_back(p);
}
// remove the OS Process from ProcMap
d->ProcMap.erase(found);
// add the OS Process to what will be the new ProcMap
temporary[PID] = p;
}
else
{
// an OS process we don't know yet!
// try to make a DFHack Process object for it
if(Process*p = d->GetProcessObject(PID))
{
// allright. this is something that can be used
d->Processes.push_back(p);
temporary[PID] = p;
}
else
{
// just a process. we track it anyway. Why not.
temporary[PID] = 0;
}
}
}
// now the vector we export is filled again and a temporary map with valid processes is created.
// we iterate over the old Process map and destroy all the processes that are dead.
for(PID2PROC::const_iterator idx = d->ProcMap.begin(); idx != d->ProcMap.end();++idx)
{
Process * p = (*idx).second;
if(p)
{
if(invalidated_processes)
{
invalidated_processes->push_back(p);
}
else
{
delete p;
}
}
}
d->ProcMap.swap(temporary);
// return value depends on if we found some DF processes
if(d->Processes.size())
{
return true;
}
return false;
}
uint32_t ProcessEnumerator::size()
{
return d->Processes.size();
}
Process * ProcessEnumerator::operator[](uint32_t index)
{
assert(index < d->Processes.size());
return d->Processes[index];
}
ProcessEnumerator::ProcessEnumerator( string path_to_xml )
: d(new Private())
{
d->meminfo = new VersionInfoFactory(path_to_xml);
}
void ProcessEnumerator::purge()
{
for(uint32_t i = 0;i < d->Processes.size();i++)
{
delete d->Processes[i];
}
d->ProcMap.clear();
d->Processes.clear();
}
ProcessEnumerator::~ProcessEnumerator()
{
// delete all processes
purge();
delete d->meminfo;
delete d;
}

@ -1,326 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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 <vector>
#include <algorithm>
#include <string>
#include <map>
#include <cstring>
using namespace std;
#include "dfhack/DFIntegers.h"
#include "dfhack-c/DFTypes_C.h"
#include "dfhack-c/DFProcess_C.h"
#ifdef __cplusplus
extern "C" {
#endif
#define PTR_CHECK if(p_Ptr == NULL) return -1;
int C_ProcessID_Compare(c_processID* left, c_processID* right)
{
if(left == NULL || right == NULL)
return PROCESSID_C_NULL;
else
{
if(left->time == right->time && left->pid == right->pid)
return PROCESSID_C_EQ;
else if(left->time < right->time || left->pid < right->pid)
return PROCESSID_C_LT;
else
return PROCESSID_C_GT;
}
}
#define FUNCTION_FORWARD(func_name) \
int Process_##func_name (DFHackObject* p_Ptr) \
{ \
if(p_Ptr == NULL) \
return -1; \
if(((DFHack::Process*)p_Ptr)->func_name()) \
return 1; \
else \
return 0; \
}
FUNCTION_FORWARD(attach)
FUNCTION_FORWARD(detach)
FUNCTION_FORWARD(suspend)
FUNCTION_FORWARD(asyncSuspend)
FUNCTION_FORWARD(resume)
FUNCTION_FORWARD(forceresume)
FUNCTION_FORWARD(isSuspended)
FUNCTION_FORWARD(isAttached)
FUNCTION_FORWARD(isIdentified)
FUNCTION_FORWARD(isSnapshot)
#define MEMREAD_FUNC_FORWARD(func_name, type) \
int Process_##func_name(DFHackObject* p_Ptr, uint32_t address, type* value) \
{ \
PTR_CHECK \
((DFHack::Process*)p_Ptr)->func_name(address, *value); \
return 1; \
}
#define MEMWRITE_FUNC_FORWARD(func_name, type) \
int Process_##func_name(DFHackObject* p_Ptr, uint32_t address, type value) \
{ \
PTR_CHECK \
((DFHack::Process*)p_Ptr)->func_name(address, value); \
return 1; \
}
MEMREAD_FUNC_FORWARD(readQuad, uint64_t)
MEMWRITE_FUNC_FORWARD(writeQuad, uint64_t)
MEMREAD_FUNC_FORWARD(readDWord, uint32_t)
MEMWRITE_FUNC_FORWARD(writeDWord, uint32_t)
MEMREAD_FUNC_FORWARD(readWord, uint16_t)
MEMWRITE_FUNC_FORWARD(writeWord, uint16_t)
MEMREAD_FUNC_FORWARD(readFloat, float)
MEMREAD_FUNC_FORWARD(readByte, uint8_t)
MEMWRITE_FUNC_FORWARD(writeByte, uint8_t)
MEMREAD_FUNC_FORWARD(readSTLVector, t_vecTriplet);
uint8_t* Process_read(DFHackObject* p_Ptr, uint32_t address, uint32_t length)
{
if(p_Ptr == NULL || alloc_ubyte_buffer_callback == NULL)
return NULL;
uint8_t* buf;
((*alloc_ubyte_buffer_callback)(&buf, length));
if(buf == NULL)
return NULL;
((DFHack::Process*)p_Ptr)->read(address, length, buf);
return buf;
}
void Process_write(DFHackObject* p_Ptr, uint32_t address, uint32_t length, uint8_t* buffer)
{
if(p_Ptr == NULL || buffer == NULL)
return;
((DFHack::Process*)p_Ptr)->write(address, length, buffer);
}
const char* Process_readString(DFHackObject* p_Ptr, uint32_t offset)
{
if(p_Ptr == NULL || alloc_char_buffer_callback == NULL)
return NULL;
std::string pString = ((DFHack::Process*)p_Ptr)->readSTLString(offset);
if(pString.length() > 0)
{
size_t length = pString.length();
char* buf;
//add 1 for the null terminator
((*alloc_char_buffer_callback)(&buf, length + 1));
if(buf == NULL)
return NULL;
memset(buf, '\n', length + 1);
pString.copy(buf, length);
return buf;
}
else
return "";
}
const char* Process_getPath(DFHackObject* p_Ptr)
{
if(p_Ptr == NULL || alloc_char_buffer_callback == NULL)
return NULL;
std::string pString = ((DFHack::Process*)p_Ptr)->getPath();
if(pString.length() > 0)
{
size_t length = pString.length();
char* buf;
//add 1 for the null terminator
((*alloc_char_buffer_callback)(&buf, length + 1));
if(buf == NULL)
return NULL;
memset(buf, '\0', length + 1);
pString.copy(buf, length);
return buf;
}
else
return "";
}
const char* Process_readClassName(DFHackObject* p_Ptr, uint32_t vptr)
{
if(p_Ptr == NULL || alloc_char_buffer_callback == NULL)
return NULL;
std::string cString = ((DFHack::Process*)p_Ptr)->readClassName(vptr);
if(cString.length() > 0)
{
size_t length = cString.length();
char* buf;
//add 1 for the null terminator
((*alloc_char_buffer_callback)(&buf, length + 1));
if(buf == NULL)
return NULL;
memset(buf, '\0', length + 1);
cString.copy(buf, length);
return buf;
}
else
return "";
}
uint32_t* Process_getThreadIDs(DFHackObject* p_Ptr)
{
if(p_Ptr == NULL || alloc_uint_buffer_callback == NULL)
return NULL;
std::vector<uint32_t> threads;
if(((DFHack::Process*)p_Ptr)->getThreadIDs(threads))
{
uint32_t* buf;
if(threads.size() > 0)
{
((*alloc_uint_buffer_callback)(&buf, threads.size()));
if(buf == NULL)
return NULL;
copy(threads.begin(), threads.end(), buf);
return buf;
}
}
return NULL;
}
t_memrange* Process_getMemRanges(DFHackObject* p_Ptr)
{
if(p_Ptr == NULL || alloc_memrange_buffer_callback == NULL)
return NULL;
std::vector<t_memrange> ranges;
((DFHack::Process*)p_Ptr)->getMemRanges(ranges);
if(ranges.size() > 0)
{
t_memrange* buf;
uint32_t* rangeDescriptorBuf = (uint32_t*)calloc(ranges.size(), sizeof(uint32_t));
for(uint32_t i = 0; i < ranges.size(); i++)
{
t_memrange* r = &ranges[i];
rangeDescriptorBuf[i] = (uint32_t)(r->end - r->start);
}
((*alloc_memrange_buffer_callback)(&buf, rangeDescriptorBuf, ranges.size()));
free(rangeDescriptorBuf);
if(buf == NULL)
return NULL;
for(uint32_t i = 0; i < ranges.size(); i++)
{
t_memrange* r = &ranges[i];
buf[i].start = r->start;
buf[i].end = r->end;
memset(buf[i].name, '\0', 1024);
strncpy(buf[i].name, r->name, 1024);
buf[i].read = r->read;
buf[i].write = r->write;
buf[i].execute = r->execute;
buf[i].shared = r->shared;
buf[i].valid = r->valid;
memcpy(buf[i].buffer, r->buffer, r->end - r->start);
}
return buf;
}
return NULL;
}
int Process_getPID(DFHackObject* p_Ptr, int32_t* pid)
{
if(p_Ptr == NULL)
{
*pid = -1;
return -1;
}
else
{
*pid = ((DFHack::Process*)p_Ptr)->getPID();
return 1;
}
}
int Process_getModuleIndex(DFHackObject* p_Ptr, char* name, uint32_t version, uint32_t* output)
{
PTR_CHECK
if(((DFHack::Process*)p_Ptr)->getModuleIndex(name, version, *output))
return 1;
else
return 0;
}
int Process_SetAndWait(DFHackObject* p_Ptr, uint32_t state)
{
PTR_CHECK
if(((DFHack::Process*)p_Ptr)->SetAndWait(state))
return 1;
else
return 0;
}
#ifdef __cplusplus
}
#endif

@ -1,66 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include "dfhack/DFTileTypes.h"
#include "dfhack-c/DFTileTypes_C.h"
int DFHack_isWallTerrain(int in)
{
return DFHack::isWallTerrain(in);
}
int DFHack_isFloorTerrain(int in)
{
return DFHack::isFloorTerrain(in);
}
int DFHack_isRampTerrain(int in)
{
return DFHack::isRampTerrain(in);
}
int DFHack_isStairTerrain(int in)
{
return DFHack::isStairTerrain(in);
}
int DFHack_isOpenTerrain(int in)
{
return DFHack::isOpenTerrain(in);
}
int DFHack_getVegetationType(int in)
{
return DFHack::tileShape(in);
}
int DFHack_getTileType(int index, TileRow* tPtr)
{
if(index >= TILE_TYPE_ARRAY_LENGTH)
return 0;
*tPtr = tileTypeTable[index];
return 1;
}

@ -1,173 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
#include "dfhack/DFTypes.h"
#include "dfhack-c/DFTypes_C.h"
#include "dfhack/modules/Materials.h"
using namespace DFHack;
/*
I believe this is what they call "the bad kind of clever", but writing out registration functions for each callback just feels *so* wrong...
The output of this macro is something like this...
void RegisterByteBufferCallback(int(*fptr)(int8_t*, uint32_t))
{
alloc_byte_buffer_callback = fptr;
}
*/
#define BUILD(a) a ## BufferCallback
#define REG_MACRO(type_name, type, callback) void BUILD(Register ## type_name) (int (*fptr)(type, uint32_t)) { callback = fptr; }
/*
The output of this macro is something like this...
void UnregisterByteBufferCallback()
{
alloc_byte_buffer_callback = NULL;
}
*/
#define UNREG_MACRO(type_name, callback) void BUILD(Unregister ## type_name) () { callback = NULL; }
#ifdef __cplusplus
extern "C" {
#endif
int (*alloc_byte_buffer_callback)(int8_t**, uint32_t) = NULL;
int (*alloc_short_buffer_callback)(int16_t**, uint32_t) = NULL;
int (*alloc_int_buffer_callback)(int32_t**, uint32_t) = NULL;
int (*alloc_ubyte_buffer_callback)(uint8_t**, uint32_t) = NULL;
int (*alloc_ushort_buffer_callback)(uint16_t**, uint32_t) = NULL;
int (*alloc_uint_buffer_callback)(uint32_t**, uint32_t) = NULL;
int (*alloc_char_buffer_callback)(char**, uint32_t) = NULL;
int (*alloc_matgloss_buffer_callback)(t_matgloss**, uint32_t) = NULL;
int (*alloc_descriptor_buffer_callback)(t_descriptor_color**, uint32_t) = NULL;
int (*alloc_matgloss_other_buffer_callback)(t_matglossOther**, uint32_t) = NULL;
int (*alloc_feature_buffer_callback)(t_feature**, uint32_t) = NULL;
int (*alloc_hotkey_buffer_callback)(t_hotkey**, uint32_t) = NULL;
int (*alloc_screen_buffer_callback)(t_screen**, uint32_t) = NULL;
int (*alloc_tree_buffer_callback)(dfh_plant**, uint32_t) = NULL;
int (*alloc_memrange_buffer_callback)(t_memrange**, uint32_t*, uint32_t) = NULL;
int (*alloc_customWorkshop_buffer_callback)(t_customWorkshop**, uint32_t) = NULL;
int (*alloc_material_buffer_callback)(t_material**, uint32_t) = NULL;
int (*alloc_creaturetype_buffer_callback)(c_creaturetype**, c_creaturetype_descriptor*, uint32_t) = NULL;
int (*alloc_vein_buffer_callback)(t_vein**, uint32_t) = NULL;
int (*alloc_frozenliquidvein_buffer_callback)(t_frozenliquidvein**, uint32_t) = NULL;
int (*alloc_spattervein_buffer_callback)(t_spattervein**, uint32_t) = NULL;
int (*alloc_grassvein_buffer_callback)(t_grassvein**, uint32_t) = NULL;
int (*alloc_worldconstruction_buffer_callback)(t_worldconstruction**, uint32_t) = NULL;
int (*alloc_featuremap_buffer_callback)(c_featuremap_node**, uint32_t*, uint32_t) = NULL;
//int (*alloc_bodypart_buffer_callback)(t_bodypart**, uint32_t) = NULL;
REG_MACRO(Byte, int8_t**, alloc_byte_buffer_callback)
REG_MACRO(Short, int16_t**, alloc_short_buffer_callback)
REG_MACRO(Int, int32_t**, alloc_int_buffer_callback)
REG_MACRO(UByte, uint8_t**, alloc_ubyte_buffer_callback)
REG_MACRO(UShort, uint16_t**, alloc_ushort_buffer_callback)
REG_MACRO(UInt, uint32_t**, alloc_uint_buffer_callback)
REG_MACRO(Char, char**, alloc_char_buffer_callback)
REG_MACRO(Matgloss, t_matgloss**, alloc_matgloss_buffer_callback)
REG_MACRO(DescriptorColor, t_descriptor_color**, alloc_descriptor_buffer_callback)
REG_MACRO(MatglossOther, t_matglossOther**, alloc_matgloss_other_buffer_callback)
REG_MACRO(Feature, t_feature**, alloc_feature_buffer_callback)
REG_MACRO(Hotkey, t_hotkey**, alloc_hotkey_buffer_callback)
REG_MACRO(Screen, t_screen**, alloc_screen_buffer_callback)
REG_MACRO(Tree, dfh_plant**, alloc_tree_buffer_callback)
REG_MACRO(CustomWorkshop, t_customWorkshop**, alloc_customWorkshop_buffer_callback)
REG_MACRO(Material, t_material**, alloc_material_buffer_callback)
void RegisterMemRangeBufferCallback(int (*funcptr)(t_memrange**, uint32_t*, uint32_t))
{
alloc_memrange_buffer_callback = funcptr;
}
UNREG_MACRO(Byte, alloc_byte_buffer_callback)
UNREG_MACRO(Short, alloc_short_buffer_callback)
UNREG_MACRO(Int, alloc_int_buffer_callback)
UNREG_MACRO(UByte, alloc_ubyte_buffer_callback)
UNREG_MACRO(UShort, alloc_ushort_buffer_callback)
UNREG_MACRO(UInt, alloc_uint_buffer_callback)
UNREG_MACRO(Char, alloc_char_buffer_callback)
UNREG_MACRO(Matgloss, alloc_matgloss_buffer_callback)
UNREG_MACRO(DescriptorColor, alloc_descriptor_buffer_callback)
UNREG_MACRO(MatglossOther, alloc_matgloss_other_buffer_callback)
UNREG_MACRO(Feature, alloc_feature_buffer_callback)
UNREG_MACRO(Hotkey, alloc_hotkey_buffer_callback)
UNREG_MACRO(Screen, alloc_screen_buffer_callback)
UNREG_MACRO(Tree, alloc_tree_buffer_callback)
UNREG_MACRO(MemRange, alloc_memrange_buffer_callback)
UNREG_MACRO(CustomWorkshop, alloc_customWorkshop_buffer_callback)
UNREG_MACRO(Material, alloc_material_buffer_callback)
void RegisterCreatureTypeBufferCallback(int (*funcptr)(c_creaturetype**, c_creaturetype_descriptor*, uint32_t))
{
alloc_creaturetype_buffer_callback = funcptr;
}
UNREG_MACRO(CreatureType, alloc_creaturetype_buffer_callback)
REG_MACRO(Vein, t_vein**, alloc_vein_buffer_callback)
REG_MACRO(FrozenLiquidVein, t_frozenliquidvein**, alloc_frozenliquidvein_buffer_callback)
REG_MACRO(SpatterVein, t_spattervein**, alloc_spattervein_buffer_callback)
REG_MACRO(GrassVein, t_grassvein**, alloc_grassvein_buffer_callback)
REG_MACRO(WorldConstruction, t_worldconstruction**, alloc_worldconstruction_buffer_callback)
UNREG_MACRO(Vein, alloc_vein_buffer_callback)
UNREG_MACRO(FrozenLiquidVein, alloc_frozenliquidvein_buffer_callback)
UNREG_MACRO(SpatterVein, alloc_spattervein_buffer_callback)
UNREG_MACRO(GrassVein, alloc_grassvein_buffer_callback)
UNREG_MACRO(WorldConstruction, alloc_worldconstruction_buffer_callback)
void RegisterFeatureMapBufferCallback(int (*funcptr)(c_featuremap_node**, uint32_t*, uint32_t))
{
alloc_featuremap_buffer_callback = funcptr;
}
UNREG_MACRO(FeatureMap, alloc_featuremap_buffer_callback)
#ifdef __cplusplus
}
#endif

@ -1,108 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include <string>
#include <vector>
#include <map>
using namespace std;
#include "MicrosoftSTL.h"
#include "dfhack/DFProcess.h"
#include "dfhack/VersionInfo.h"
using namespace DFHack;
void MicrosoftSTL::init(Process* self)
{
p = self;
OffsetGroup * strGrp = p->getDescriptor()->getGroup("string")->getGroup("MSVC");
STLSTR_buf_off = strGrp->getOffset("buffer");
STLSTR_size_off = strGrp->getOffset("size");
STLSTR_cap_off = strGrp->getOffset("capacity");
}
size_t MicrosoftSTL::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
uint32_t start_offset = offset + STLSTR_buf_off;
size_t length = p->readDWord(offset + STLSTR_size_off);
size_t capacity = p->readDWord(offset + STLSTR_cap_off);
size_t read_real = min(length, bufcapacity-1);// keep space for null termination
// read data from inside the string structure
if(capacity < 16)
{
p->read(start_offset, read_real , (uint8_t *)buffer);
}
else // read data from what the offset + 4 dword points to
{
start_offset = p->readDWord(start_offset);// dereference the start offset
p->read(start_offset, read_real, (uint8_t *)buffer);
}
buffer[read_real] = 0;
return read_real;
}
const string MicrosoftSTL::readSTLString (uint32_t offset)
{
uint32_t start_offset = offset + STLSTR_buf_off;
size_t length = p->readDWord(offset + STLSTR_size_off);
size_t capacity = p->readDWord(offset + STLSTR_cap_off);
char * temp = new char[capacity+1];
// read data from inside the string structure
if(capacity < 16)
{
p->read(start_offset, capacity, (uint8_t *)temp);
}
else // read data from what the offset + 4 dword points to
{
start_offset = p->readDWord(start_offset);// dereference the start offset
p->read(start_offset, capacity, (uint8_t *)temp);
}
temp[length] = 0;
string ret = temp;
delete temp;
return ret;
}
string MicrosoftSTL::readClassName (uint32_t vptr)
{
int rtti = p->readDWord(vptr - 0x4);
int typeinfo = p->readDWord(rtti + 0xC);
string raw = p->readCString(typeinfo + 0xC); // skips the .?AV
raw.resize(raw.length() - 2);// trim @@ from end
return raw;
}
// FIXME: really, fix this.
size_t MicrosoftSTL::writeSTLString(const uint32_t address, const std::string writeString)
{
return 0;
}

@ -0,0 +1,185 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2011 Petr Mrázek (peterix)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include "PlatformInternal.h"
#include <string>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
using namespace std;
#include "dfhack/Process.h"
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/Error.h"
#include <errno.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <md5wrapper.h>
using namespace DFHack;
Process::Process(VersionInfoFactory * known_versions)
{
const char * dir_name = "/proc/self/";
const char * exe_link_name = "/proc/self/exe";
const char * cwd_name = "/proc/self/cwd";
const char * cmdline_name = "/proc/self/cmdline";
char target_name[1024];
int target_result;
identified = false;
my_descriptor = 0;
// resolve /proc/self/exe link
target_result = readlink(exe_link_name, target_name, sizeof(target_name)-1);
if (target_result == -1)
{
return;
}
// make sure we have a null terminated string...
target_name[target_result] = 0;
// is this the regular linux DF?
if (strstr(target_name, "dwarfort.exe") != 0 || strstr(target_name,"Dwarf_Fortress") != 0)
{
md5wrapper md5;
// get hash of the running DF process
string hash = md5.getHashFromFile(target_name);
// create linux process, add it to the vector
VersionInfo * vinfo = known_versions->getVersionInfoByMD5(hash);
if(vinfo)
{
my_descriptor = new VersionInfo(*vinfo);
my_descriptor->setParentProcess(this);
identified = true;
}
}
}
void Process::readSTLVector(const uint32_t address, t_vecTriplet & triplet)
{
read(address, sizeof(triplet), (uint8_t *) &triplet);
}
void Process::writeSTLVector(const uint32_t address, t_vecTriplet & triplet)
{
write(address, sizeof(triplet), (uint8_t *) &triplet);
}
string Process::doReadClassName (uint32_t vptr)
{
int typeinfo = Process::readDWord(vptr - 0x4);
int typestring = Process::readDWord(typeinfo + 0x4);
string raw = readCString(typestring);
size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers
size_t end = raw.length();
return raw.substr(start,end-start);
}
//FIXME: cross-reference with ELF segment entries?
void Process::getMemRanges( vector<t_memrange> & ranges )
{
char buffer[1024];
char permissions[5]; // r/-, w/-, x/-, p/s, 0
FILE *mapFile = ::fopen("/proc/self/maps", "r");
size_t start, end, offset, device1, device2, node;
while (fgets(buffer, 1024, mapFile))
{
t_memrange temp;
temp.name[0] = 0;
sscanf(buffer, "%zx-%zx %s %zx %2zu:%2zu %zu %[^\n]s",
&start,
&end,
(char*)&permissions,
&offset, &device1, &device2, &node,
(char*)&temp.name);
temp.start = start;
temp.end = end;
temp.read = permissions[0] == 'r';
temp.write = permissions[1] == 'w';
temp.execute = permissions[2] == 'x';
temp.shared = permissions[3] == 's';
temp.valid = true;
ranges.push_back(temp);
}
}
int getdir (string dir, vector<string> &files)
{
DIR *dp;
struct dirent *dirp;
if((dp = opendir(dir.c_str())) == NULL)
{
cout << "Error(" << errno << ") opening " << dir << endl;
return errno;
}
while ((dirp = readdir(dp)) != NULL) {
files.push_back(string(dirp->d_name));
}
closedir(dp);
return 0;
}
bool Process::getThreadIDs(vector<uint32_t> & threads )
{
stringstream ss;
vector<string> subdirs;
if(getdir("/proc/self/task/",subdirs) != 0)
{
//FIXME: needs exceptions. this is a fatal error
cerr << "unable to enumerate threads. This is BAD!" << endl;
return false;
}
threads.clear();
for(size_t i = 0; i < subdirs.size();i++)
{
uint32_t tid;
if(sscanf(subdirs[i].c_str(),"%d", &tid))
{
threads.push_back(tid);
}
}
return true;
}
string Process::getPath()
{
const char * cwd_name = "/proc/self/cwd";
char target_name[1024];
int target_result;
target_result = readlink(cwd_name, target_name, sizeof(target_name));
target_name[target_result] = '\0';
return(string(target_name));
}
int Process::getPID()
{
return getpid();
}

@ -1,7 +1,7 @@
// vim: sts=4 sta et shiftwidth=4:
#include "dfhack/DFIntegers.h"
#include "dfhack/DFTileTypes.h"
#include "dfhack/DFExport.h"
#include "dfhack/Integers.h"
#include "dfhack/TileTypes.h"
#include "dfhack/Export.h"
namespace DFHack
{

@ -31,8 +31,8 @@ distribution.
using namespace std;
#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include "dfhack/DFProcess.h"
#include "dfhack/Error.h"
#include "dfhack/Process.h"
using namespace DFHack;
//Inital amount of space in levels vector (since we usually know the number, efficient!)

@ -32,7 +32,7 @@ using namespace std;
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFError.h"
#include "dfhack/Error.h"
using namespace DFHack;
#include <tinyxml.h>

@ -45,7 +45,7 @@
//----------------------------------------------------------------------
//STL includes
#include <string>
#include <dfhack/DFIntegers.h>
#include <dfhack/Integers.h>
//----------------------------------------------------------------------
//typedefs
typedef unsigned char *POINTER;

@ -20,13 +20,12 @@
#endif
// DFHack core classes and types
#include "dfhack/DFIntegers.h"
#include "dfhack/DFError.h"
#include "dfhack/DFContextManager.h"
#include "dfhack/DFContext.h"
#include "dfhack/Integers.h"
#include "dfhack/Error.h"
#include "dfhack/Context.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFTypes.h"
#include "dfhack/Process.h"
#include "dfhack/Types.h"
// DFHack modules
#include "dfhack/modules/Buildings.h"
@ -46,11 +45,11 @@
* Only for use of official DFHack tools!
*/
#ifdef DFHACK_WANT_MISCUTILS
#include "dfhack/DFMiscUtils.h"
#include "dfhack/MiscUtils.h"
#endif
// define this to get the static tiletype->properties mapping
#ifdef DFHACK_WANT_TILETYPES
#include "dfhack/DFTileTypes.h"
#include "dfhack/TileTypes.h"
#endif
#endif

@ -1,48 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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.
*/
#pragma once
#ifndef DFHACK_C_API
#define DFHACK_C_API
#include "dfhack/DFPragma.h"
#include "dfhack/DFExport.h"
#include "dfhack/DFIntegers.h"
typedef void DFHackObject;
#ifdef __cplusplus
namespace DFHack {};
using namespace DFHack;
extern "C" {
#endif
// some global stuff here
#ifdef __cplusplus
}
#endif
#endif

@ -1,51 +0,0 @@
/*
* www.sourceforge.net/projects/dfhack
* Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
*
* 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 DFHACK_C_API
#define DFHACK_C_API
#define HBUILD(a) a ## BufferCallback
#define HREG_MACRO(type_name, type) DFHACK_EXPORT void HBUILD(Register ## type_name) (int (*funcptr)(type, uint32_t));
#define HUNREG_MACRO(type_name) DFHACK_EXPORT void HBUILD(Unregister ## type_name) ();
#include "dfhack/DFPragma.h"
#include "dfhack/DFExport.h"
#include "dfhack/DFIntegers.h"
typedef void DFHackObject;
#ifdef __cplusplus
namespace DFHack {};
using namespace DFHack;
extern "C" {
#endif
// some global stuff here
#ifdef __cplusplus
}
#endif
#endif

@ -1,157 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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 DFHACK_C_CONTEXT
#define DFHACK_C_CONTEXT
#include "dfhack-c/Common.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
Allocates a new ContextManager.
@param path_to_xml A const string pointer containing the path to the Memory.xml file.
@return A DFHackObject pointer that points to the allocated ContextManager.
*/
DFHACK_EXPORT DFHackObject* ContextManager_Alloc(const char* path_to_xml);
/**
Frees a previously allocated ContextManager.
@param contextMgr A DFHackObject pointer that points to a previously allocated ContextManager.
@return None.
*/
DFHACK_EXPORT void ContextManager_Free(DFHackObject* contextMgr);
DFHACK_EXPORT int ContextManager_Refresh(DFHackObject* contextMgr);
/**
Gets the number of active DF processes.
@param contextMgr A pointer to an active ContextManager.
@param size A pointer to an unsigned 32-bit integer that will contain the count of active DF processes.
@return
- 0: Failure.
- 1: Success.
- -1: An invalid pointer was supplied.
*/
DFHACK_EXPORT int ContextManager_size(DFHackObject* contextMgr, uint32_t* size);
DFHACK_EXPORT int ContextManager_purge(DFHackObject* contextMgr);
DFHACK_EXPORT DFHackObject* ContextManager_getContext(DFHackObject* contextMgr, uint32_t index);
DFHACK_EXPORT DFHackObject* ContextManager_getSingleContext(DFHackObject* contextMgr);
/**
Frees a previously allocated Context.
@param context A DFHackObject pointer that points to a previously allocated Context.
@return None.
*/
DFHACK_EXPORT void Context_Free(DFHackObject* context);
/**
Attaches to a running DF process.
@param context A pointer to an unattached Context.
@return
- 0: Failure.
- 1: Success.
- -1: An invalid pointer was supplied.
*/
DFHACK_EXPORT int Context_Attach(DFHackObject* context);
/**
Detaches from a tracked DF process.
@param context A pointer to an attached Context.
@return
- 0: Failure.
- 1: Success.
- -1: An invalid pointer was supplied.
*/
DFHACK_EXPORT int Context_Detach(DFHackObject* context);
/**
Determines whether or not the given Context is attached to a running DF process.
@param context A pointer to an attached Context.
@return
- 0: The supplied Context is not attached.
- 1: The supplied Context is attached.
- -1: An invalid pointer was supplied.
*/
DFHACK_EXPORT int Context_isAttached(DFHackObject* context);
/**
Suspends a running DF process.
@param context A pointer to an attached Context.
@return
- 0: The tracked process was not suspended.
- 1: The tracked process was suspended.
- -1: An invalid pointer was supplied.
*/
DFHACK_EXPORT int Context_Suspend(DFHackObject* context);
/**
Resume a running DF process.
@param context A pointer to an attached Context.
@return
- 0: The tracked process was not resumed.
- 1: The tracked process was resumed.
- -1: An invalid pointer was supplied.
*/
DFHACK_EXPORT int Context_Resume(DFHackObject* context);
/**
Determines whether or not the given Context's tracked process is suspended.
@param context A pointer to an attached Context.
@return
- 0: The tracked process is not suspended.
- 1: The tracked process is suspended.
- -1: An invalid pointer was supplied.
*/
DFHACK_EXPORT int Context_isSuspended(DFHackObject* context);
DFHACK_EXPORT int Context_ForceResume(DFHackObject* context);
DFHACK_EXPORT int Context_AsyncSuspend(DFHackObject* context);
DFHACK_EXPORT DFHackObject* Context_getMemoryInfo(DFHackObject* context);
DFHACK_EXPORT DFHackObject* Context_getProcess(DFHackObject* context);
DFHACK_EXPORT DFHackObject* Context_getCreatures(DFHackObject* context);
DFHACK_EXPORT DFHackObject* Context_getMaps(DFHackObject* context);
DFHACK_EXPORT DFHackObject* Context_getGui(DFHackObject* context);
DFHACK_EXPORT DFHackObject* Context_getMaterials(DFHackObject* context);
DFHACK_EXPORT DFHackObject* Context_getTranslation(DFHackObject* context);
DFHACK_EXPORT DFHackObject* Context_getVegetation(DFHackObject* context);
DFHACK_EXPORT DFHackObject* Context_getBuildings(DFHackObject* context);
DFHACK_EXPORT DFHackObject* Context_getConstructions(DFHackObject* context);
DFHACK_EXPORT DFHackObject* Context_getItems(DFHackObject* context);
DFHACK_EXPORT DFHackObject* Context_getWorld(DFHackObject* context);
DFHACK_EXPORT DFHackObject* Context_getWindowIO(DFHackObject* context);
//these are DANGEROUS...can crash/segfault DF, turn the seas to blood, call up the Antichrist, etc
DFHACK_EXPORT void Context_ReadRaw(DFHackObject* context, const uint32_t offset, const uint32_t size, uint8_t* target);
DFHACK_EXPORT void Context_WriteRaw(DFHackObject* context, const uint32_t offset, const uint32_t size, uint8_t* source);
#ifdef __cplusplus
}
#endif
#endif

@ -1,96 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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 PROCESS_C_API
#define PROCESS_C_API
#include "dfhack-c/Common.h"
#include "dfhack/DFProcess.h"
#ifdef __cplusplus
extern "C" {
#endif
struct c_processID
{
uint64_t time;
uint64_t pid;
};
#define PROCESSID_C_NULL -2
#define PROCESSID_C_LT -1
#define PROCESSID_C_EQ 0
#define PROCESSID_C_GT 1
DFHACK_EXPORT extern int C_ProcessID_Compare(c_processID* left, c_processID* right);
DFHACK_EXPORT int Process_attach(DFHackObject* p_Ptr);
DFHACK_EXPORT int Process_detach(DFHackObject* p_Ptr);
DFHACK_EXPORT int Process_suspend(DFHackObject* p_Ptr);
DFHACK_EXPORT int Process_asyncSuspend(DFHackObject* p_Ptr);
DFHACK_EXPORT int Process_resume(DFHackObject* p_Ptr);
DFHACK_EXPORT int Process_forceresume(DFHackObject* p_Ptr);
DFHACK_EXPORT int Process_readQuad(DFHackObject* p_Ptr, uint32_t address, uint64_t* value);
DFHACK_EXPORT int Process_writeQuad(DFHackObject* p_Ptr, uint32_t address, uint64_t value);
DFHACK_EXPORT int Process_readDWord(DFHackObject* p_Ptr, uint32_t address, uint32_t* value);
DFHACK_EXPORT int Process_writeDWord(DFHackObject* p_Ptr, uint32_t address, uint32_t value);
DFHACK_EXPORT int Process_readWord(DFHackObject* p_Ptr, uint32_t address, uint16_t* value);
DFHACK_EXPORT int Process_writeWord(DFHackObject* p_Ptr, uint32_t address, uint16_t value);
DFHACK_EXPORT int Process_readFloat(DFHackObject* p_Ptr, uint32_t address, float* value);
DFHACK_EXPORT int Process_readByte(DFHackObject* p_Ptr, uint32_t address, uint8_t* value);
DFHACK_EXPORT int Process_writeByte(DFHackObject* p_Ptr, uint32_t address, uint8_t value);
DFHACK_EXPORT uint8_t* Process_read(DFHackObject* p_Ptr, uint32_t address, uint32_t length);
DFHACK_EXPORT void Process_write(DFHackObject* p_Ptr, uint32_t address, uint32_t length, uint8_t* buffer);
DFHACK_EXPORT int Process_readSTLVector(DFHackObject* p_Ptr, uint32_t address, t_vecTriplet* vector);
DFHACK_EXPORT const char* Process_readString(DFHackObject* p_Ptr, uint32_t offset);
DFHACK_EXPORT const char* Process_getPath(DFHackObject* p_Ptr);
DFHACK_EXPORT const char* Process_readClassName(DFHackObject* p_Ptr, uint32_t vptr);
DFHACK_EXPORT int Process_isSuspended(DFHackObject* p_Ptr);
DFHACK_EXPORT int Process_isAttached(DFHackObject* p_Ptr);
DFHACK_EXPORT int Process_isIdentified(DFHackObject* p_Ptr);
DFHACK_EXPORT int Process_isSnapshot(DFHackObject* p_Ptr);
DFHACK_EXPORT uint32_t* Process_getThreadIDs(DFHackObject* p_Ptr);
DFHACK_EXPORT t_memrange* Process_getMemRanges(DFHackObject* p_Ptr);
DFHACK_EXPORT int Process_getPID(DFHackObject* p_Ptr, int32_t* pid);
DFHACK_EXPORT int Process_getModuleIndex(DFHackObject* p_Ptr, char* name, uint32_t version, uint32_t* output);
DFHACK_EXPORT int Process_SetAndWait(DFHackObject* p_Ptr, uint32_t state);
#ifdef __cplusplus
}
#endif
#endif

@ -1,48 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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_C_API
#define TILETYPES_C_API
#include "dfhack-c/Common.h"
#include "dfhack/DFTileTypes.h"
#ifdef __cplusplus
extern "C" {
#endif
DFHACK_EXPORT int DFHack_isWallTerrain(int in);
DFHACK_EXPORT int DFHack_isFloorTerrain(int in);
DFHACK_EXPORT int DFHack_isRampTerrain(int in);
DFHACK_EXPORT int DFHack_isStairTerrain(int in);
DFHACK_EXPORT int DFHack_isOpenTerrain(int in);
DFHACK_EXPORT int DFHack_getVegetationType(int in);
DFHACK_EXPORT int DFHack_getTileType(int index, TileRow* tPtr);
#ifdef __cplusplus
}
#endif
#endif

@ -1,262 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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_C_API
#define TYPES_C_API
#include "dfhack-c/Common.h"
#include "DFProcess_C.h"
#include "dfhack/DFTypes.h"
#include "dfhack/modules/Maps.h"
#include "dfhack/modules/Materials.h"
#include "dfhack/modules/Gui.h"
#define HBUILD(a) a ## BufferCallback
#define HREG_MACRO(type_name, type) DFHACK_EXPORT void HBUILD(Register ## type_name) (int (*funcptr)(type, uint32_t));
#define HUNREG_MACRO(type_name) DFHACK_EXPORT void HBUILD(Unregister ## type_name) ();
#ifdef __cplusplus
extern "C" {
#endif
DFHACK_EXPORT extern int (*alloc_byte_buffer_callback)(int8_t**, uint32_t);
DFHACK_EXPORT extern int (*alloc_short_buffer_callback)(int16_t**, uint32_t);
DFHACK_EXPORT extern int (*alloc_int_buffer_callback)(int32_t**, uint32_t);
DFHACK_EXPORT extern int (*alloc_ubyte_buffer_callback)(uint8_t**, uint32_t);
DFHACK_EXPORT extern int (*alloc_ushort_buffer_callback)(uint16_t**, uint32_t);
DFHACK_EXPORT extern int (*alloc_uint_buffer_callback)(uint32_t**, uint32_t);
DFHACK_EXPORT extern int (*alloc_char_buffer_callback)(char**, uint32_t);
DFHACK_EXPORT extern int (*alloc_matgloss_buffer_callback)(t_matgloss**, uint32_t);
DFHACK_EXPORT extern int (*alloc_descriptor_buffer_callback)(t_descriptor_color**, uint32_t);
DFHACK_EXPORT extern int (*alloc_matgloss_other_buffer_callback)(t_matglossOther**, uint32_t);
DFHACK_EXPORT extern int (*alloc_feature_buffer_callback)(t_feature**, uint32_t);
DFHACK_EXPORT extern int (*alloc_hotkey_buffer_callback)(t_hotkey**, uint32_t);
DFHACK_EXPORT extern int (*alloc_screen_buffer_callback)(t_screen**, uint32_t);
DFHACK_EXPORT extern int (*alloc_tree_buffer_callback)(dfh_plant**, uint32_t);
DFHACK_EXPORT extern int (*alloc_memrange_buffer_callback)(t_memrange**, uint32_t*, uint32_t);
DFHACK_EXPORT void RegisterByteBufferCallback(int (*funcptr)(int8_t**, uint32_t));
DFHACK_EXPORT void RegisterShortBufferCallback(int (*funcptr)(int16_t**, uint32_t));
DFHACK_EXPORT void RegisterIntBufferCallback(int (*funcptr)(int32_t**, uint32_t));
DFHACK_EXPORT void RegisterUByteBufferCallback(int (*funcptr)(uint8_t**, uint32_t));
DFHACK_EXPORT void RegisterUShortBufferCallback(int (*funcptr)(uint16_t**, uint32_t));
DFHACK_EXPORT void RegisterUIntBufferCallback(int (*funcptr)(uint32_t**, uint32_t));
DFHACK_EXPORT void RegisterCharBufferCallback(int (*funcptr)(char**, uint32_t));
DFHACK_EXPORT void RegisterMatglossBufferCallback(int (*funcptr)(t_matgloss**, uint32_t));
DFHACK_EXPORT void RegisterDescriptorColorBufferCallback(int (*funcptr)(t_descriptor_color**, uint32_t));
DFHACK_EXPORT void RegisterMatglossOtherBufferCallback(int (*funcptr)(t_matglossOther**, uint32_t));
DFHACK_EXPORT void RegisterFeatureBufferCallback(int (*funcptr)(t_feature**, uint32_t));
DFHACK_EXPORT void RegisterHotkeyBufferCallback(int (*funcptr)(t_hotkey**, uint32_t));
DFHACK_EXPORT void RegisterScreenBufferCallback(int (*funcptr)(t_screen**, uint32_t));
DFHACK_EXPORT void RegisterTreeBufferCallback(int (*funcptr)(dfh_plant**, uint32_t));
DFHACK_EXPORT void RegisterMemRangeBufferCallback(int (*funcptr)(t_memrange**, uint32_t*, uint32_t));
HUNREG_MACRO(Byte)
HUNREG_MACRO(Short)
HUNREG_MACRO(Int)
HUNREG_MACRO(UByte)
HUNREG_MACRO(UShort)
HUNREG_MACRO(UInt)
HUNREG_MACRO(Char)
HUNREG_MACRO(Matgloss)
HUNREG_MACRO(DescriptorColor)
HUNREG_MACRO(MatglossOther)
HUNREG_MACRO(Feature)
HUNREG_MACRO(Hotkey)
HUNREG_MACRO(Screen)
HUNREG_MACRO(Tree)
HUNREG_MACRO(MemRange)
struct t_customWorkshop
{
uint32_t index;
char name[256];
};
DFHACK_EXPORT extern int (*alloc_customWorkshop_buffer_callback)(t_customWorkshop**, uint32_t);
DFHACK_EXPORT extern int (*alloc_material_buffer_callback)(t_material**, uint32_t);
DFHACK_EXPORT void RegisterCustomWorkshopBufferCallback(int (*funcptr)(t_customWorkshop**, uint32_t));
DFHACK_EXPORT void RegisterMaterialBufferCallback(int (*funcptr)(t_material**, uint32_t));
HUNREG_MACRO(CustomWorkshop)
HUNREG_MACRO(Material)
struct c_colormodifier
{
char part[128];
uint32_t* colorlist;
uint32_t colorlistLength;
uint32_t startdate;
uint32_t enddate;
};
struct c_colormodifier_descriptor
{
uint32_t colorlistLength;
};
struct c_creaturecaste
{
char rawname[128];
char singular[128];
char plural[128];
char adjective[128];
c_colormodifier* colorModifier;
uint32_t colorModifierLength;
t_bodypart* bodypart;
uint32_t bodypartLength;
t_attrib strength;
t_attrib agility;
t_attrib toughness;
t_attrib endurance;
t_attrib recuperation;
t_attrib disease_resistance;
t_attrib analytical_ability;
t_attrib focus;
t_attrib willpower;
t_attrib creativity;
t_attrib intuition;
t_attrib patience;
t_attrib memory;
t_attrib linguistic_ability;
t_attrib spatial_sense;
t_attrib musicality;
t_attrib kinesthetic_sense;
};
struct c_creaturecaste_descriptor
{
c_colormodifier_descriptor* color_descriptors;
uint32_t colorModifierLength;
uint32_t bodypartLength;
};
struct c_creaturetype
{
char rawname[128];
c_creaturecaste* castes;
uint32_t castesCount;
t_creatureextract* extract;
uint32_t extractCount;
uint8_t tile_character;
struct
{
uint16_t fore;
uint16_t back;
uint16_t bright;
} tilecolor;
};
struct c_creaturetype_descriptor
{
c_creaturecaste_descriptor* caste_descriptors;
uint32_t castesCount;
uint32_t extractCount;
};
DFHACK_EXPORT extern int (*alloc_creaturetype_buffer_callback)(c_creaturetype**, c_creaturetype_descriptor*, uint32_t);
DFHACK_EXPORT extern int (*alloc_vein_buffer_callback)(t_vein**, uint32_t);
DFHACK_EXPORT extern int (*alloc_frozenliquidvein_buffer_callback)(t_frozenliquidvein**, uint32_t);
DFHACK_EXPORT extern int (*alloc_spattervein_buffer_callback)(t_spattervein**, uint32_t);
DFHACK_EXPORT extern int (*alloc_grassvein_buffer_callback)(t_grassvein**, uint32_t);
DFHACK_EXPORT extern int (*alloc_worldconstruction_buffer_callback)(t_worldconstruction**, uint32_t);
DFHACK_EXPORT void RegisterCreatureTypeBufferCallback(int (*funcptr)(c_creaturetype**, c_creaturetype_descriptor*, uint32_t));
DFHACK_EXPORT void RegisterVeinBufferCallback(int (*funcptr)(t_vein**, uint32_t));
DFHACK_EXPORT void RegisterFrozenLiquidVeinBufferCallback(int (*funcptr)(t_frozenliquidvein**, uint32_t));
DFHACK_EXPORT void RegisterSpatterVeinBufferCallback(int (*funcptr)(t_spattervein**, uint32_t));
DFHACK_EXPORT void RegisterGrassVeinBufferCallback(int (*funcptr)(t_grassvein**, uint32_t));
DFHACK_EXPORT void RegisterWorldConstructionBufferCallback(int (*funcptr)(t_worldconstruction**, uint32_t));
HUNREG_MACRO(CreatureType)
HUNREG_MACRO(Vein)
HUNREG_MACRO(FrozenLiquidVein)
HUNREG_MACRO(SpatterVein)
HUNREG_MACRO(GrassVein)
HUNREG_MACRO(WorldConstruction)
struct c_mapcoord
{
union
{
struct
{
uint16_t x;
uint16_t y;
uint32_t z;
};
struct
{
uint16_t x;
uint16_t y;
} dim;
uint64_t comparate;
};
};
struct c_featuremap_node
{
c_mapcoord coordinate;
t_feature* features;
uint32_t feature_length;
};
DFHACK_EXPORT extern int (*alloc_featuremap_buffer_callback)(c_featuremap_node**, uint32_t*, uint32_t);
DFHACK_EXPORT void RegisterFeatureMapBufferCallback(int (*funcptr)(c_featuremap_node**, uint32_t*, uint32_t));
#ifdef __cplusplus
} // extern "C"
#endif
#endif

@ -1,133 +0,0 @@
=======================================
Introduction And Reasons For Existence
=======================================
C++ is not an easy language to access from other languages. There are several "features" that make interoperability considerably more painful when trying to write bindings for Python, Ruby, Lua, or whatever. To that end, dfhack has a C translation layer to ease the process of making bindings for other languages. A shadow API, if you will.
.. contents::
=================
Getting DFHack-C
=================
The C shim is a part of the standard dfhack package. If you've installed dfhack, you've already got it. The dfhack source and binaries are hosted on github_, at http://github.com/peterix/dfhack
.. _github: http://www.github.com/
Packages
=========
The library and tools are packaged for Archlinux and are available both
in AUR and the arch-games repository.
The package name is dfhack-git.
========
Layout
========
The structure of the C shim mimics, as far as possible, the normal dfhack structure. Of course, since C lacks things like classes, templates, and function overloading, there are a few places where deviations are unavoidable.
Return Values
=============
Unless otherwise specified, functions that return an int return one of the following values:
- 0: The operation failed.
- 1: The operation succeeded.
- -1: An invalid module pointer was supplied.
Types
=======
Module objects are passed around as void pointers with the typedef name 'DFHackObject'. Wherever possible, the structures and enumerations defined by dfhack are used without redefinition.
Allocator Callbacks
====================
Wherever possible, the C shim eschews the native allocation of memory, as this would require language bindings to remember to free the memory later, and would, in my opinion, make the shim less flexible. So a number of function pointers are exposed to allow memory to be allocated in the language being used to wrap dfhack. In general, the allocations relate to arrays of dfhack structures, but there are a couple of corner cases.
The buffer callback functions should take a pointer to an array of the particular type, and a 32-bit unsigned integer (uint32_t) defining the length of the array needed. If the buffer was successfully created, the callback function should return 1. In case of failure, set the buffer pointer to NULL (or 0) and return 0.
All of the allocators are defined in dfhack/library/include/dfhack-c/DFTypes_C.h.
Buffer Callback List
---------------------
- alloc_byte_buffer_callback(int8_t**, uint32_t)
- alloc_short_buffer_callback(int16_t**, uint32_t)
- alloc_int_buffer_callback(int32_t**, uint32_t)
- alloc_ubyte_buffer_callback(uint8_t**, uint32_t)
- alloc_ushort_buffer_callback(uint16_t**, uint32_t)
- alloc_uint_buffer_callback(uint32_t**, uint32_t)
- alloc_char_buffer_callback(char** uint32_t)
- alloc_matgloss_buffer_callback(t_matgloss**, uint32_t)
- alloc_descriptor_buffer_callback(t_descriptor_color**, uint32_t)
- alloc_matgloss_other_buffer_callback(t_matglossOther**, uint32_t)
- alloc_t_feature_buffer_callback(t_feature**, uint32_t)
- alloc_t_hotkey_buffer_callback(t_hotkey**, uint32_t)
- alloc_t_screen_buffer_callback(t_screen**, uint32_t)
- alloc_t_customWorkshop_buffer_callback(t_customWorkshop**, uint32_t)
- alloc_t_material_buffer_callback(t_material**, uint32_t)
- alloc_vein_buffer_callback(t_vein**, uint32_t)
- alloc_frozenliquidvein_buffer_callback(t_frozenliquidvein**, uint32_t)
- alloc_spattervein_buffer_callback(t_spattervein**, uint32_t)
- alloc_grassvein_buffer_callback(t_grassvein**, uint32_t)
- alloc_worldconstruction_buffer_callback(t_worldconstruction**, uint32_t)
Templates Make My Life Harder
-------------------------------
Several dfhack structures contain vectors, which (obviously) don't work in C. Therefore, these structures have C versions that replace the vector with a buffer and length, but are otherwise identical to their C++ counterparts. For each structure, there are three associated callbacks. One initializes an empty instance of the structure (*alloc_empty_colormodifier_callback*, for instance), one initializes an instance with values passed in (*alloc_colormodifier_callback*), and one allocates a buffer in the same manner as the other allocators (*alloc_colormodifier_buffer_callback*).
The replaced structures and their callbacks are as follows.
- c_colormodifier
* alloc_empty_colormodifier_callback(c_colormodifier*)
* alloc_colormodifier_callback(c_colormodifier*, const char*, uint32_t)
* alloc_colormodifier_buffer_callback(c_colormodifier*, uint32_t)
- c_creaturecaste
* alloc_empty_creaturecaste_callback(c_creaturecaste*)
* alloc_creaturecaste_callback(c_creaturecaste*, const char*, const char*, const char*, const char*, uint32_t, uint32_t)
* alloc_creaturecaste_buffer_callback(c_creaturecaste*, uint32_t)
- c_creaturetype
* alloc_empty_creaturetype_callback(c_creaturetype*)
* alloc_creaturetype_callback(c_creaturetype*, const char*, uint32_t, uint32_t, uint8_t, uint16_t, uint16_t, uint16_t)
* alloc_creaturetype_buffer_callback(c_creaturetype*, uint32_t)
A Small Callback Example In Python
-------------------------------------
The Python bindings for dfhack implement the unsigned integer allocator callback like this:
.. admonition:: util.py
| from ctypes import \*
|
| def _allocate_array(t_type, count):
| arr_type = t_type * count
| arr = arr_type()
|
| return arr
|
| def _alloc_uint_buffer(ptr, count):
| a = _allocate_array(c_uint, count)
|
| p = cast(a, POINTER(c_uint))
|
| ptr[0] = p
|
| return 1
|
| _uint_functype = CFUNCTYPE(c_int, POINTER(c_uint), c_uint)
| alloc_uint_buffer = _uint_functype(_alloc_uint_buffer)
.. admonition:: dftypes.py
| from ctypes import \*
| from util import \*
|
| libdfhack = cdll.libdfhack
|
| def _register_callback(name, func):
| ptr = c_void_p.in_dll(libdfhack, name)
| ptr.value = cast(func, c_void_p).value
|
| _register_callback("alloc_uint_buffer_callback", alloc_uint_buffer)
Modules
========
Every dfhack module has a corresponding set of C functions. The functions are named <MODULE>_<FUNCTION>, as in 'Maps_Start', 'Materials_ReadOthers', etc. The first argument to any module function is a void pointer that points to an instance of the module object in question.

@ -1,49 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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 BUILDINGS_C_API
#define BUILDINGS_C_API
#include "dfhack-c/Common.h"
#include "dfhack/DFTypes.h"
#include "dfhack/modules/Buildings.h"
#include "dfhack-c/DFTypes_C.h"
#ifdef __cplusplus
extern "C" {
#endif
DFHACK_EXPORT int Buildings_Start(DFHackObject* b_Ptr, uint32_t* numBuildings);
DFHACK_EXPORT int Buildings_Finish(DFHackObject* b_Ptr);
DFHACK_EXPORT int Buildings_Read(DFHackObject* b_Ptr, const uint32_t index, t_building* building);
DFHACK_EXPORT t_customWorkshop* Buildings_ReadCustomWorkshopTypes(DFHackObject* b_Ptr);
DFHACK_EXPORT int Buildings_GetCustomWorkshopType(DFHackObject* b_Ptr, t_building* building);
#ifdef __cplusplus
}
#endif
#endif

@ -1,45 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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 CONSTRUCTIONS_C_API
#define CONSTRUCTIONS_C_API
#include "dfhack-c/Common.h"
#include "dfhack/DFTypes.h"
#include "dfhack/modules/Constructions.h"
#ifdef __cplusplus
extern "C" {
#endif
DFHACK_EXPORT int Constructions_Start(DFHackObject* c_Ptr, uint32_t* numConstructions);
DFHACK_EXPORT int Constructions_Finish(DFHackObject* c_Ptr);
DFHACK_EXPORT int Constructions_Read(DFHackObject* c_Ptr, const uint32_t index, t_construction* construction);
#ifdef __cplusplus
}
#endif
#endif

@ -1,71 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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 CREATURES_C_API
#define CREATURES_C_API
#include "dfhack-c/Common.h"
#include "dfhack/DFTypes.h"
#include "dfhack-c/DFTypes_C.h"
#include "dfhack/modules/Materials.h"
#include "dfhack/modules/Creatures.h"
#ifdef __cplusplus
extern "C" {
#endif
DFHACK_EXPORT int Creatures_Start(DFHackObject* cPtr, uint32_t* numCreatures);
DFHACK_EXPORT int Creatures_Finish(DFHackObject* cPtr);
DFHACK_EXPORT int32_t Creatures_ReadCreatureInBox(DFHackObject* cPtr, const int32_t index, t_creature* furball,
const uint16_t x1, const uint16_t y1, const uint16_t z1,
const uint16_t x2, const uint16_t y2, const uint16_t z2);
DFHACK_EXPORT int Creatures_ReadCreature(DFHackObject* cPtr, const int32_t index, t_creature* furball);
DFHACK_EXPORT t_material* Creatures_ReadJob(DFHackObject* cPtr, const t_creature* furball);
DFHACK_EXPORT uint32_t* Creatures_ReadInventoryIdx(DFHackObject* cPtr, const uint32_t index);
DFHACK_EXPORT uint32_t* Creatures_ReadInventoryPtr(DFHackObject* cPtr, const uint32_t index);
DFHACK_EXPORT uint32_t Creatures_GetDwarfRaceIndex(DFHackObject* cPtr);
DFHACK_EXPORT int32_t Creatures_GetDwarfCivId(DFHackObject* cPtr);
DFHACK_EXPORT int Creatures_WriteLabors(DFHackObject* cPtr, const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]);
DFHACK_EXPORT int Creatures_WriteHappiness(DFHackObject* cPtr, const uint32_t index, const uint32_t happiness_value);
DFHACK_EXPORT int Creatures_WriteFlags(DFHackObject* cPtr, const uint32_t index, const uint32_t flags1, const uint32_t flags2);
DFHACK_EXPORT int Creatures_WriteSkills(DFHackObject* cPtr, const uint32_t index, const t_soul* soul);
DFHACK_EXPORT int Creatures_WriteAttributes(DFHackObject* cPtr, const uint32_t index, const t_creature* creature);
DFHACK_EXPORT int Creatures_WriteSex(DFHackObject* cPtr, const uint32_t index, const uint8_t sex);
DFHACK_EXPORT int Creatures_WriteTraits(DFHackObject* cPtr, const uint32_t index, const t_soul* soul);
DFHACK_EXPORT int Creatures_WriteMood(DFHackObject* cPtr, const uint32_t index, const uint16_t mood);
DFHACK_EXPORT int Creatures_WriteMoodSkill(DFHackObject* cPtr, const uint32_t index, const uint16_t moodSkill);
DFHACK_EXPORT int Creatures_WriteJob(DFHackObject* cPtr, const t_creature* furball, const t_material* mat, const uint32_t mat_count);
DFHACK_EXPORT int Creatures_WritePos(DFHackObject* cPtr, const uint32_t index, const t_creature* creature);
DFHACK_EXPORT int Creatures_WriteCiv(DFHackObject* cPtr, const uint32_t index, const int32_t civ);
#ifdef __cplusplus
}
#endif
#endif

@ -1,58 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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 GUI_C_API
#define GUI_C_API
#include "dfhack-c/Common.h"
#include "dfhack/DFTypes.h"
#include "dfhack/modules/Gui.h"
#ifdef __cplusplus
extern "C" {
#endif
DFHACK_EXPORT int Gui_Start(DFHackObject* gui);
DFHACK_EXPORT int Gui_Finish(DFHackObject* gui);
DFHACK_EXPORT int Gui_getViewCoords(DFHackObject* gui, int32_t* x, int32_t* y, int32_t* z);
DFHACK_EXPORT int Gui_setViewCoords(DFHackObject* gui, int32_t x, int32_t y, int32_t z);
DFHACK_EXPORT int Gui_getCursorCoords(DFHackObject* gui, int32_t* x, int32_t* y, int32_t* z);
DFHACK_EXPORT int Gui_setCursorCoords(DFHackObject* gui, int32_t x, int32_t y, int32_t z);
DFHACK_EXPORT t_hotkey* Gui_ReadHotkeys(DFHackObject* gui);
DFHACK_EXPORT int Gui_getWindowSize(DFHackObject* gui, int32_t* width, int32_t* height);
DFHACK_EXPORT t_screen* Gui_getScreenTiles(DFHackObject* gui, int32_t width, int32_t height);
DFHACK_EXPORT int Gui_ReadViewScreen(DFHackObject* gui, t_viewscreen* viewscreen);
DFHACK_EXPORT int Gui_ReadMenuState(DFHackObject* gui, uint32_t* menuState);
#ifdef __cplusplus
}
#endif
#endif

@ -1,48 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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 ITEMS_C_API
#define ITEMS_C_API
#include "dfhack-c/Common.h"
#include "dfhack/DFProcess.h"
#include "dfhack-c/DFTypes_C.h"
#include "dfhack/modules/Items.h"
#ifdef __cplusplus
extern "C" {
#endif
DFHACK_EXPORT int Items_Start(DFHackObject* items);
DFHACK_EXPORT int Items_Finish(DFHackObject* items);
DFHACK_EXPORT char* Items_getItemDescription(DFHackObject* items, dfh_item* item, DFHackObject* mats);
DFHACK_EXPORT char* Items_getItemClass(DFHackObject* items, int32_t index);
DFHACK_EXPORT int Items_getItemData(DFHackObject* items, uint32_t itemptr, dfh_item* item);
#ifdef __cplusplus
}
#endif
#endif

@ -1,102 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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 MAPS_C_API
#define MAPS_C_API
#include "dfhack-c/Common.h"
#include "dfhack/DFTypes.h"
#include "dfhack/modules/Maps.h"
#ifdef __cplusplus
extern "C" {
#endif
DFHACK_EXPORT int Maps_Start(DFHackObject* maps);
DFHACK_EXPORT int Maps_Finish(DFHackObject* maps);
DFHACK_EXPORT uint16_t* Maps_ReadGeology(DFHackObject* maps);
DFHACK_EXPORT t_feature* Maps_ReadGlobalFeatures(DFHackObject* maps);
DFHACK_EXPORT c_featuremap_node* Maps_ReadLocalFeatures(DFHackObject* maps);
DFHACK_EXPORT void Maps_getSize(DFHackObject* maps, uint32_t* x, uint32_t* y, uint32_t* z);
DFHACK_EXPORT void Maps_getPosition(DFHackObject* maps, int32_t* x, int32_t* y, int32_t* z);
DFHACK_EXPORT int Maps_isValidBlock(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z);
DFHACK_EXPORT uint32_t Maps_getBlockPtr(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z);
DFHACK_EXPORT int Maps_ReadBlock40d(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, mapblock40d* buffer);
DFHACK_EXPORT int Maps_ReadTileTypes(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, tiletypes40d* buffer);
DFHACK_EXPORT int Maps_WriteTileTypes(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, tiletypes40d* buffer);
DFHACK_EXPORT int Maps_ReadDesignations(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, designations40d* buffer);
DFHACK_EXPORT int Maps_WriteDesignations(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, designations40d* buffer);
DFHACK_EXPORT int Maps_ReadTemperatures(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, t_temperatures* temp1, t_temperatures* temp2);
DFHACK_EXPORT int Maps_WriteTemperatures(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, t_temperatures* temp1, t_temperatures* temp2);
DFHACK_EXPORT int Maps_ReadOccupancy(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, occupancies40d* buffer);
DFHACK_EXPORT int Maps_WriteOccupancy(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, occupancies40d* buffer);
DFHACK_EXPORT int Maps_ReadDirtyBit(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, int* dirtybit);
DFHACK_EXPORT int Maps_WriteDirtyBit(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, int dirtybit);
DFHACK_EXPORT int Maps_ReadFeatures(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, int16_t* local, int16_t* global);
DFHACK_EXPORT int Maps_WriteLocalFeature(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, int16_t local);
DFHACK_EXPORT int Maps_WriteEmptyLocalFeature(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z);
DFHACK_EXPORT int Maps_WriteGlobalFeature(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, int16_t local);
DFHACK_EXPORT int Maps_WriteEmptyGlobalFeature(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z);
DFHACK_EXPORT int Maps_ReadBlockFlags(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, t_blockflags* blockflags);
DFHACK_EXPORT int Maps_WriteBlockFlags(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, t_blockflags blockflags);
DFHACK_EXPORT int Maps_ReadRegionOffsets(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, biome_indices40d* buffer);
DFHACK_EXPORT t_vein* Maps_ReadStandardVeins(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z);
DFHACK_EXPORT t_frozenliquidvein* Maps_ReadFrozenVeins(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z);
DFHACK_EXPORT t_spattervein* Maps_ReadSpatterVeins(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z);
DFHACK_EXPORT t_grassvein* Maps_ReadGrassVeins(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z);
DFHACK_EXPORT t_worldconstruction* Maps_ReadWorldConstructions(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z);
typedef struct
{
t_vein* veins;
t_frozenliquidvein* frozen_veins;
t_spattervein* spatter_veins;
t_grassvein* grass_veins;
t_worldconstruction* world_constructions;
} c_allveins;
DFHACK_EXPORT int Maps_ReadAllVeins(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z, c_allveins* vein_struct);
DFHACK_EXPORT dfh_plant* Maps_ReadVegetation(DFHackObject* maps, uint32_t x, uint32_t y, uint32_t z);
#ifdef __cplusplus
}
#endif
#endif

@ -1,74 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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 MATERIALS_C_API
#define MATERIALS_C_API
#include "dfhack-c/Common.h"
#include "dfhack-c/DFTypes_C.h"
#include "dfhack/modules/Materials.h"
#ifdef __cplusplus
extern "C" {
#endif
DFHACK_EXPORT int Materials_ReadInorganicMaterials(DFHackObject* mat);
DFHACK_EXPORT int Materials_ReadOrganicMaterials(DFHackObject* mat);
DFHACK_EXPORT int Materials_ReadWoodMaterials(DFHackObject* mat);
DFHACK_EXPORT int Materials_ReadPlantMaterials(DFHackObject* mat);
DFHACK_EXPORT int Materials_ReadCreatureTypes(DFHackObject* mat);
DFHACK_EXPORT int Materials_ReadCreatureTypesEx(DFHackObject* mat);
DFHACK_EXPORT int Materials_ReadDescriptorColors(DFHackObject* mat);
DFHACK_EXPORT int Materials_ReadOthers(DFHackObject* mat);
DFHACK_EXPORT void Materials_ReadAllMaterials(DFHackObject* mat);
DFHACK_EXPORT const char* Materials_getType(DFHackObject* mat, t_material* material);
DFHACK_EXPORT const char* Materials_getDescription(DFHackObject* mat, t_material* material);
DFHACK_EXPORT int Materials_getInorganicSize(DFHackObject* mat);
DFHACK_EXPORT int Materials_getOrganicSize(DFHackObject* mat);
DFHACK_EXPORT int Materials_getTreeSize(DFHackObject* mat);
DFHACK_EXPORT int Materials_getPlantSize(DFHackObject* mat);
DFHACK_EXPORT int Materials_getRaceSize(DFHackObject* mat);
DFHACK_EXPORT int Materials_getRaceExSize(DFHackObject* mat);
DFHACK_EXPORT int Materials_getColorSize(DFHackObject* mat);
DFHACK_EXPORT int Materials_getOtherSize(DFHackObject* mat);
DFHACK_EXPORT t_matgloss* Materials_getInorganic(DFHackObject* mat);
DFHACK_EXPORT t_matgloss* Materials_getOrganic(DFHackObject* mat);
DFHACK_EXPORT t_matgloss* Materials_getTree(DFHackObject* mat);
DFHACK_EXPORT t_matgloss* Materials_getPlant(DFHackObject* mat);
DFHACK_EXPORT t_matgloss* Materials_getRace(DFHackObject* mat);
DFHACK_EXPORT c_creaturetype* Materials_getRaceEx(DFHackObject* mat);
DFHACK_EXPORT t_descriptor_color* Materials_getColor(DFHackObject* mat);
DFHACK_EXPORT t_matglossOther* Materials_getOther(DFHackObject* mat);
DFHACK_EXPORT t_matgloss* Materials_getAllDesc(DFHackObject* mat);
#ifdef __cplusplus
}
#endif
#endif

@ -1,47 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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 TRANSLATION_C_API
#define TRANSLATION_C_API
#include "dfhack-c/Common.h"
#include "dfhack/DFTypes.h"
#include "dfhack-c/DFTypes_C.h"
#include "dfhack/modules/Translation.h"
#ifdef __cplusplus
extern "C" {
#endif
DFHACK_EXPORT int Translation_Start(DFHackObject* trans);
DFHACK_EXPORT int Translation_Finish(DFHackObject* trans);
DFHACK_EXPORT char* Translation_TranslateNameEnglish(DFHackObject* trans, const DFHack::t_name* name);
DFHACK_EXPORT char* Translation_TranslateNameNonEnglish(DFHackObject* trans, const DFHack::t_name* name);
#ifdef __cplusplus
}
#endif
#endif

@ -1,45 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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 VEGETATION_C_API
#define VEGETATION_C_API
#include "dfhack-c/Common.h"
#include "dfhack/DFTypes.h"
#include "dfhack/modules/Vegetation.h"
#ifdef __cplusplus
extern "C" {
#endif
DFHACK_EXPORT int Vegetation_Start(DFHackObject* veg, uint32_t* numTrees);
DFHACK_EXPORT int Vegetation_Finish(DFHackObject* veg);
DFHACK_EXPORT int Vegetation_Read(DFHackObject* veg, const uint32_t index, dfh_plant* shrubbery);
#ifdef __cplusplus
}
#endif
#endif

@ -1,43 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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 WINDOWIO_C_API
#define WINDOWIO_C_API
#include "dfhack-c/Common.h"
#include "dfhack/modules/WindowIO.h"
#ifdef __cplusplus
extern "C" {
#endif
DFHACK_EXPORT int WindowIO_TypeStr(DFHackObject* window, const char* input, uint32_t delay, int8_t useShift);
DFHACK_EXPORT int WindowIO_TypeSpecial(DFHackObject* window, t_special command, uint32_t count, uint32_t delay);
#ifdef __cplusplus
}
#endif
#endif

@ -1,55 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf, doomchild
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 WORLD_C_API
#define WORLD_C_API
#include "dfhack-c/Common.h"
#include "dfhack/modules/World.h"
#ifdef __cplusplus
extern "C" {
#endif
DFHACK_EXPORT int World_Start(DFHackObject* world);
DFHACK_EXPORT int World_Finish(DFHackObject* world);
DFHACK_EXPORT int World_ReadCurrentTick(DFHackObject* world, uint32_t* tick);
DFHACK_EXPORT int World_ReadCurrentYear(DFHackObject* world, uint32_t* year);
DFHACK_EXPORT int World_ReadCurrentMonth(DFHackObject* world, uint32_t* month);
DFHACK_EXPORT int World_ReadCurrentDay(DFHackObject* world, uint32_t* day);
DFHACK_EXPORT int World_ReadCurrentWeather(DFHackObject* world, uint8_t* weather);
DFHACK_EXPORT int World_WriteCurrentWeather(DFHackObject* world, uint8_t weather);
DFHACK_EXPORT int World_ReadGameMode(DFHackObject* world, t_gamemodes*);
DFHACK_EXPORT int World_WriteGameMode(DFHackObject* world, t_gamemodes);
DFHACK_EXPORT int World_ReadPauseState(DFHackObject* gui);
DFHACK_EXPORT int World_SetPauseState(DFHackObject* gui, int8_t paused);
#ifdef __cplusplus
}
#endif
#endif

@ -27,7 +27,7 @@ distribution.
#ifndef CONTEXT_H_INCLUDED
#define CONTEXT_H_INCLUDED
#include "DFExport.h"
#include "dfhack/Export.h"
namespace DFHack
{
class Creatures;

@ -1,149 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
#ifndef CONTEXTMANAGER_H_INCLUDED
#define CONTEXTMANAGER_H_INCLUDED
#include "DFPragma.h"
#include "DFExport.h"
#include <string>
#include <vector>
#include <map>
namespace DFHack
{
class Context;
class BadContexts;
class Process;
/**
* Used to enumerate, create and destroy Contexts. The very base of DFHack.
* @see DFHack::Context
* \ingroup grp_context
*/
class DFHACK_EXPORT ContextManager
{
class Private;
Private * const d;
public:
/**
* Constructs the ContextManager.
* @param path_to_xml the path to the file that defines memory offsets. (Memory.xml)
*/
ContextManager(const std::string path_to_xml);
/**
* Destroys the ContextManager.
*/
~ContextManager();
/**
* Refresh the internal list of valid Context objects.
* @param bad_contexts pointer to a BadContexts object. Not required. All contexts are automatically destroyed if the object is not provided.
* @see DFHack::BadContexts
* @return Number of tracked contexts
*/
uint32_t Refresh(BadContexts* bad_contexts = 0);
/**
* Get the number of tracked contexts.
* @return Number of tracked contexts
*/
uint32_t size();
/**
* Get a context by index
* @param index index of the context to be returned
* @return pointer to a Context. 0 if the index is out of range.
*/
Context * operator[](uint32_t index);
/**
* Convenience method to return a single valid Context
* @return pointer to a Context. The Context isn't attached!
*/
Context * getSingleContext();
/**
* Destroy all tracked Context objects
* Normally called during object destruction. Calling this from outside ContextManager is nasty.
*/
void purge(void);
};
/**
* Class used for holding a set of invalidated Context AND Process objects temporarily and destroy them safely.
* @see DFHack::Context
* @see DFHack::Process
* \ingroup grp_context
*/
class DFHACK_EXPORT BadContexts
{
class Private;
Private * const d;
void push_back(Context * c);
friend class ContextManager;
void clear();
public:
BadContexts();
/**
* Destructor.
* All Processes and Contexts tracked by the BadContexts object will be destroyed also.
*/
~BadContexts();
/**
* Test if a Context is among the invalidated Contexts
* @param c pointer to a Context to be checked
* @return true if the Context is among the invalidated. false otherwise.
*/
bool Contains(Context* c);
/**
* Test if a Process is among the invalidated Processes/Contexts
* @param p pointer to a Process to be checked
* @see DFHack::Process
* @return true if the Process is among the invalidated. false otherwise.
*/
bool Contains(Process* p);
// TODO: Add excise(Context *) method
/**
* Get the number of tracked invalid contexts.
* @return Number of tracked invalid contexts
*/
uint32_t size();
/**
* Get an invalid Context by index
* @param index index of the invalid Context to be returned
* @return pointer to an invalid Context
*/
Context * operator[](uint32_t index);
};
} // namespace DFHack
#endif // CONTEXTMANAGER_H_INCLUDED

@ -1,136 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
#ifndef PROCESSMANAGER_H_INCLUDED
#define PROCESSMANAGER_H_INCLUDED
#include "DFPragma.h"
#include "DFExport.h"
namespace DFHack
{
class VersionInfo;
class Process;
class BadProcesses;
/**
* Process enumerator
* Used to enumerate, create and destroy Processes.
* @see DFHack::Process
* \ingroup grp_context
*/
class DFHACK_EXPORT ProcessEnumerator
{
class Private;
Private * const d;
public:
/**
* Constructs the ProcessEnumerator.
* @param path_to_xml the path to the file that defines memory offsets. (Memory.xml)
*/
ProcessEnumerator( string path_to_xml );
/**
* Destroys the ProcessEnumerator.
*/
~ProcessEnumerator();
/**
* Refresh the internal list of valid Process objects.
* @param invalidated_processes pointer to a BadProcesses object. Not required. All processes are automatically destroyed if the object is not provided.
* @see DFHack::BadProcesses
* @return true if there's at least one valit Process
*/
bool Refresh(BadProcesses * invalidated_processes = 0);
/**
* @return Number of tracked processes
*/
uint32_t size();
/**
* Get a Process by index
* @param index index of the Process to be returned
* @return pointer to a Process. 0 if the index is out of range.
*/
Process * operator[](uint32_t index);
/**
* Destroy all tracked Process objects
* Normally called during object destruction. Calling this from outside ProcessManager is nasty.
*/
void purge(void);
};
/**
* Class used for holding a set of invalidated Process objects temporarily and destroy them safely.
* @see DFHack::Process
* \ingroup grp_context
*/
class DFHACK_EXPORT BadProcesses
{
class Private;
Private * const d;
void push_back(Process * p);
friend class ProcessEnumerator;
void clear();
public:
BadProcesses();
/**
* Destructor.
* All Processes tracked by the BadProcesses object will be destroyed also.
*/
~BadProcesses();
/**
* Test if a Process is among the invalidated Processes
* @param p pointer to a Process to be checked
* @return true if the Process is among the invalidated. false otherwise.
*/
bool Contains(Process* p);
/**
* Remove a Process from the tracked invalidated Processes. Used by BadContexts.
* @param p pointer to a Process to be excised
* @see DFHack::BadContexts
* @return true if the Process was among the invalidated. false otherwise.
*/
bool excise (Process* p);
/**
* Get the number of tracked invalid contexts.
* @return Number of tracked invalid contexts
*/
uint32_t size();
/**
* Get an invalid Process by index
* @param index index of the invalid Process to be returned
* @return pointer to an invalid Process
*/
Process * operator[](uint32_t index);
};
}
#endif // PROCESSMANAGER_H_INCLUDED

@ -27,8 +27,8 @@ distribution.
#ifndef ERROR_H_INCLUDED
#define ERROR_H_INCLUDED
#include "DFExport.h"
#include "DFPragma.h"
#include "dfhack/Export.h"
#include "dfhack/Pragma.h"
#include <string>
#include <sstream>
#include <exception>

@ -14,6 +14,6 @@ You can turn off the include by defining SKIP_DFHACK_STDINT
#ifndef _MSC_VER
#include <stdint.h>
#else
#include "DFstdint_win.h"
#include "dfhack/stdint_win.h"
#endif
#endif

@ -5,7 +5,7 @@
#include <iostream>
#include <iomanip>
#include <climits>
#include <dfhack/DFIntegers.h>
#include <dfhack/Integers.h>
#include <vector>
#include <sstream>
#include <ctime>
@ -13,9 +13,9 @@
using namespace std;
#include <dfhack/DFProcess.h>
#include <dfhack/Process.h>
#include <dfhack/VersionInfo.h>
#include <dfhack/DFVector.h>
#include <dfhack/Vector.h>
void DumpObjStr0Vector (const char * name, DFHack::Process *p, uint32_t addr)
{

@ -27,7 +27,7 @@ distribution.
#ifndef MODULE_H_INCLUDED
#define MODULE_H_INCLUDED
#include "DFExport.h"
#include "dfhack/Export.h"
namespace DFHack
{
class Context;

@ -1,6 +1,6 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
https://github.com/peterix/dfhack
Copyright (c) 2011 Petr Mrázek (peterix)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@ -27,9 +27,10 @@ distribution.
#ifndef PROCESS_H_INCLUDED
#define PROCESS_H_INCLUDED
#include "DFPragma.h"
#include "DFExport.h"
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#include <iostream>
#include <cstring>
#include <map>
namespace DFHack
@ -38,6 +39,7 @@ namespace DFHack
class Process;
class Window;
class DFVector;
class VersionInfoFactory;
/**
* A type for storing an extended OS Process ID (combines PID and the time the process was started for unique identification)
@ -101,90 +103,137 @@ namespace DFHack
*/
class DFHACK_EXPORT Process
{
protected:
std::map<uint32_t, std::string> classNameCache;
public:
/// this is the single most important destructor ever. ~px
virtual ~Process(){};
/// Set up stuff so we can read memory, suspends synchronously
virtual bool attach() = 0;
/// detach from DF, resume its execution if it's suspended
virtual bool detach() = 0;
/**
* synchronous suspend
* waits for DF to be actually suspended,
* this might take a while depending on implementation
*/
virtual bool suspend() = 0;
/// asynchronous suspend to use together with polling and timers
virtual bool asyncSuspend() = 0;
/// resume DF execution
virtual bool resume() = 0;
/// force-resume DF execution
virtual bool forceresume() = 0;
Process(VersionInfoFactory * known_versions);
~Process();
/// read a 8-byte integer
uint64_t readQuad(const uint32_t address) { uint64_t result; readQuad(address, result); return result; }
uint64_t readQuad(const uint32_t address)
{
return *(uint64_t *)address;
}
/// read a 8-byte integer
virtual void readQuad(const uint32_t address, uint64_t & value) = 0;
void readQuad(const uint32_t address, uint64_t & value)
{
value = *(uint64_t *)address;
};
/// write a 8-byte integer
virtual void writeQuad(const uint32_t address, const uint64_t value) = 0;
void writeQuad(const uint32_t address, const uint64_t value)
{
(*(uint64_t *)address) = value;
};
/// read a 4-byte integer
uint32_t readDWord(const uint32_t address) { uint32_t result; readDWord(address, result); return result; }
uint32_t readDWord(const uint32_t address)
{
return *(uint32_t *)address;
}
/// read a 4-byte integer
virtual void readDWord(const uint32_t address, uint32_t & value) = 0;
void readDWord(const uint32_t address, uint32_t & value)
{
value = *(uint32_t *)address;
};
/// write a 4-byte integer
virtual void writeDWord(const uint32_t address, const uint32_t value) = 0;
void writeDWord(const uint32_t address, const uint32_t value)
{
(*(uint32_t *)address) = value;
};
/// read a float
float readFloat(const uint32_t address) { float result; readFloat(address, result); return result; }
float readFloat(const uint32_t address)
{
return *(float*)address;
}
/// write a float
virtual void readFloat(const uint32_t address, float & value) = 0;
void readFloat(const uint32_t address, float & value)
{
value = *(float*)address;
};
/// read a 2-byte integer
uint16_t readWord(const uint32_t address) { uint16_t result; readWord(address, result); return result; }
uint16_t readWord(const uint32_t address)
{
return *(uint16_t *)address;
}
/// read a 2-byte integer
virtual void readWord(const uint32_t address, uint16_t & value) = 0;
void readWord(const uint32_t address, uint16_t & value)
{
value = *(uint16_t *)address;
};
/// write a 2-byte integer
virtual void writeWord(const uint32_t address, const uint16_t value) = 0;
void writeWord(const uint32_t address, const uint16_t value)
{
(*(uint16_t *)address) = value;
};
/// read a byte
uint8_t readByte(const uint32_t address) { uint8_t result; readByte(address, result); return result; }
uint16_t readByte(const uint32_t address)
{
return *(uint8_t *)address;
}
/// read a byte
virtual void readByte(const uint32_t address, uint8_t & value) = 0;
void readByte(const uint32_t address, uint8_t & value)
{
value = *(uint8_t *)address;
};
/// write a byte
virtual void writeByte(const uint32_t address, const uint8_t value) = 0;
void writeByte(const uint32_t address, const uint8_t value)
{
(*(uint8_t *)address) = value;
};
/// read an arbitrary amount of bytes
virtual void read( uint32_t address, uint32_t length, uint8_t* buffer) = 0;
void read( uint32_t address, uint32_t length, uint8_t* buffer)
{
memcpy(buffer, (void *) address, length);
};
/// write an arbitrary amount of bytes
virtual void write(uint32_t address, uint32_t length, uint8_t* buffer) = 0;
void write(uint32_t address, uint32_t length, uint8_t* buffer)
{
memcpy((void *) address, buffer, length);
};
/// read an STL string
virtual const std::string readSTLString (uint32_t offset) = 0;
const std::string readSTLString (uint32_t offset)
{
std::string * str = (std::string *) offset;
return *str;
};
/// read an STL string
virtual size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity) = 0;
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
if(!bufcapacity || bufcapacity == 1)
return 0;
std::string * str = (std::string *) offset;
};
/**
* write an STL string
* @return length written
*/
virtual size_t writeSTLString(const uint32_t address, const std::string writeString) = 0;
size_t writeSTLString(const uint32_t address, const std::string writeString)
{
std::string * str = (std::string *) address;
str->assign(writeString);
return writeString.size();
};
/**
* attempt to copy a string from source address to target address. may truncate or leak, depending on platform
* @return length copied
*/
virtual size_t copySTLString(const uint32_t address, const uint32_t target)
size_t copySTLString(const uint32_t address, const uint32_t target)
{
return writeSTLString(target, readSTLString(address));
std::string * strsrc = (std::string *) address;
std::string * str = (std::string *) target;
str->assign(*strsrc);
return str->size();
}
/// read a STL vector
virtual void readSTLVector(const uint32_t address, t_vecTriplet & triplet) = 0;
virtual void writeSTLVector(const uint32_t address, t_vecTriplet & triplet) = 0;
void readSTLVector(const uint32_t address, t_vecTriplet & triplet);
void writeSTLVector(const uint32_t address, t_vecTriplet & triplet);
/// get class name of an object with rtti/type info
virtual std::string doReadClassName(uint32_t vptr) = 0;
std::string doReadClassName(uint32_t vptr);
std::string readClassName(uint32_t vptr)
{
@ -195,34 +244,39 @@ namespace DFHack
}
/// read a null-terminated C string
virtual const std::string readCString (uint32_t offset) = 0;
const std::string readCString (uint32_t offset)
{
return std::string((char *) offset);
};
/// @return true if the process is suspended
virtual bool isSuspended() = 0;
/// @return true if the process is attached
virtual bool isAttached() = 0;
bool isSuspended()
{
return true;
};
/// @return true if the process is identified -- has a Memory.xml entry
virtual bool isIdentified() = 0;
/// @return true if this is a Process snapshot
virtual bool isSnapshot() { return false; };
bool isIdentified()
{
return identified;
};
/// find the thread IDs of the process
virtual bool getThreadIDs(std::vector<uint32_t> & threads ) = 0;
bool getThreadIDs(std::vector<uint32_t> & threads );
/// get virtual memory ranges of the process (what is mapped where)
virtual void getMemRanges(std::vector<t_memrange> & ranges ) = 0;
void getMemRanges(std::vector<t_memrange> & ranges );
/// get the flattened Memory.xml entry of this process
virtual VersionInfo *getDescriptor() = 0;
VersionInfo *getDescriptor()
{
return my_descriptor;
};
/// get the DF Process ID
virtual int getPID() = 0;
int getPID();
/// get the DF Process FilePath
virtual std::string getPath() = 0;
/// get module index by name and version. bool 1 = error
virtual bool getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT) = 0;
/// get the SHM start if available
virtual char * getSHMStart (void) = 0;
/// set a SHM command and wait for a response, return 0 on error or throw exception
virtual bool SetAndWait (uint32_t state) = 0;
std::string getPath();
private:
VersionInfo * my_descriptor;
bool identified;
std::map<uint32_t, std::string> classNameCache;
};
class DFHACK_EXPORT ClassNameCheck

@ -27,8 +27,8 @@ distribution.
#ifndef TILETYPES_H_INCLUDED
#define TILETYPES_H_INCLUDED
#include "DFPragma.h"
#include "DFExport.h"
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
namespace DFHack
{

@ -27,8 +27,8 @@ distribution.
#ifndef TYPES_H_INCLUDED
#define TYPES_H_INCLUDED
#include "DFPragma.h"
#include "DFExport.h"
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#ifdef __cplusplus
namespace DFHack

@ -27,10 +27,10 @@ distribution.
#ifndef DFVECTOR_H_INCLUDED
#define DFVECTOR_H_INCLUDED
#include "DFPragma.h"
#include "DFExport.h"
#include "VersionInfo.h"
#include "DFProcess.h"
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/Process.h"
#include <string.h>

@ -27,9 +27,9 @@ distribution.
#ifndef MEMINFO_H_INCLUDED
#define MEMINFO_H_INCLUDED
#include "DFPragma.h"
#include "DFExport.h"
#include "dfhack/DFTypes.h"
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#include "dfhack/Types.h"
#include <sys/types.h>
namespace DFHack

@ -27,8 +27,8 @@ distribution.
#ifndef MEMINFO_MANAGER_H_INCLUDED
#define MEMINFO_MANAGER_H_INCLUDED
#include "dfhack/DFPragma.h"
#include "dfhack/DFExport.h"
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
class TiXmlElement;
namespace DFHack

@ -2,9 +2,9 @@
#ifndef MAPEXTRAS_H
#define MAPEXTRAS_H
#include "../modules/Maps.h"
#include "../DFTileTypes.h"
#include "../DFIntegers.h"
#include "dfhack/modules/Maps.h"
#include "dfhack/TileTypes.h"
#include "dfhack/Integers.h"
#include <cstring>
namespace MapExtras
{

@ -5,8 +5,8 @@
* \defgroup grp_buildings Building module parts - also includes zones and stockpiles
* @ingroup grp_modules
*/
#include "dfhack/DFExport.h"
#include "dfhack/DFModule.h"
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#ifdef __cplusplus
namespace DFHack

@ -4,8 +4,8 @@
/*
* DF constructions
*/
#include "dfhack/DFExport.h"
#include "dfhack/DFModule.h"
#include "dfhack/Export.h"
#include "dfhack/Module.h"
/**
* \defgroup grp_constructions Construction module parts

@ -4,8 +4,8 @@
/*
* Creatures
*/
#include "dfhack/DFExport.h"
#include "dfhack/DFModule.h"
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "dfhack/modules/Items.h"
/**
* \defgroup grp_creatures Creatures module parts

@ -4,8 +4,8 @@
/*
* DF engravings
*/
#include "dfhack/DFExport.h"
#include "dfhack/DFModule.h"
#include "dfhack/Export.h"
#include "dfhack/Module.h"
/**
* \defgroup grp_engraving Engraving module parts

@ -2,8 +2,8 @@
#ifndef CL_MOD_GUI
#define CL_MOD_GUI
#include "dfhack/DFExport.h"
#include "dfhack/DFModule.h"
#include "dfhack/Export.h"
#include "dfhack/Module.h"
/**
* \defgroup grp_gui query DF's GUI state

@ -5,9 +5,9 @@
/*
* Items!
*/
#include "dfhack/DFExport.h"
#include "dfhack/DFModule.h"
#include "dfhack/DFTypes.h"
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "dfhack/Types.h"
/**
* \defgroup grp_items Items module and its types

@ -6,9 +6,9 @@
#ifndef CL_MOD_MAPS
#define CL_MOD_MAPS
#include "dfhack/DFExport.h"
#include "dfhack/DFModule.h"
#include "Vegetation.h"
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "dfhack/modules/Vegetation.h"
/**
* \defgroup grp_maps Maps module and its types

@ -5,8 +5,8 @@
* \defgroup grp_materials Materials module - used for reading raws mostly
* @ingroup grp_modules
*/
#include "dfhack/DFExport.h"
#include "dfhack/DFModule.h"
#include "dfhack/Export.h"
#include "dfhack/Module.h"
namespace DFHack
{
class DFContextShared;

@ -6,8 +6,8 @@
* @ingroup grp_modules
*/
#include "dfhack/DFExport.h"
#include "dfhack/DFModule.h"
#include "dfhack/Export.h"
#include "dfhack/Module.h"
namespace DFHack
{
class DFContextShared;

@ -6,9 +6,9 @@
* @ingroup grp_modules
*/
#include "dfhack/DFExport.h"
#include "dfhack/DFModule.h"
#include "dfhack/DFTypes.h"
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "dfhack/Types.h"
namespace DFHack
{
/**

@ -31,9 +31,9 @@ distribution.
*/
#include "../DFPragma.h"
#include "../DFExport.h"
#include "../DFModule.h"
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#include "dfhack/Module.h"
namespace DFHack
{

@ -7,8 +7,8 @@
* @ingroup grp_modules
*/
#include "dfhack/DFExport.h"
#include "dfhack/DFModule.h"
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include <ostream>
namespace DFHack

@ -32,10 +32,10 @@ using namespace std;
#include "ContextShared.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFTypes.h"
#include "dfhack/DFError.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "dfhack/Types.h"
#include "dfhack/Error.h"
#include "dfhack/modules/Buildings.h"
#include "ModuleFactory.h"
using namespace DFHack;

@ -32,9 +32,9 @@ using namespace std;
#include "ContextShared.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFTypes.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "dfhack/Types.h"
#include "dfhack/modules/Constructions.h"
#include "ModuleFactory.h"

@ -34,10 +34,10 @@ using namespace std;
#include "ContextShared.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFError.h"
#include "dfhack/DFTypes.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "dfhack/Error.h"
#include "dfhack/Types.h"
// we connect to those
#include "dfhack/modules/Materials.h"

@ -32,9 +32,9 @@ using namespace std;
#include "ContextShared.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFTypes.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "dfhack/Types.h"
#include "dfhack/modules/Engravings.h"
#include "ModuleFactory.h"

@ -31,10 +31,10 @@ using namespace std;
#include "ContextShared.h"
#include "dfhack/modules/Gui.h"
#include "dfhack/DFProcess.h"
#include "dfhack/Process.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFTypes.h"
#include "dfhack/DFError.h"
#include "dfhack/Types.h"
#include "dfhack/Error.h"
#include "ModuleFactory.h"
using namespace DFHack;

@ -32,10 +32,10 @@ distribution.
using namespace std;
#include "ContextShared.h"
#include "dfhack/DFTypes.h"
#include "dfhack/Types.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "dfhack/modules/Materials.h"
#include "dfhack/modules/Items.h"
#include "dfhack/modules/Creatures.h"

@ -33,10 +33,10 @@ using namespace std;
#include "ContextShared.h"
#include "dfhack/modules/Maps.h"
#include "dfhack/DFError.h"
#include "dfhack/Error.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "ModuleFactory.h"
#define MAPS_GUARD if(!d->Started) throw DFHack::Error::ModuleNotInitialized();

@ -31,12 +31,12 @@ distribution.
using namespace std;
#include "ContextShared.h"
#include "dfhack/DFTypes.h"
#include "dfhack/Types.h"
#include "dfhack/modules/Materials.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include <dfhack/DFError.h>
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include <dfhack/Error.h>
#include "ModuleFactory.h"
using namespace DFHack;

@ -33,9 +33,9 @@ using namespace std;
#include "ContextShared.h"
#include "dfhack/modules/Translation.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFTypes.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "dfhack/Types.h"
#include "ModuleFactory.h"
using namespace DFHack;

@ -32,9 +32,9 @@ using namespace std;
#include "ContextShared.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFProcess.h"
#include "dfhack/DFVector.h"
#include "dfhack/DFTypes.h"
#include "dfhack/Process.h"
#include "dfhack/Vector.h"
#include "dfhack/Types.h"
#include "dfhack/modules/Vegetation.h"
#include "dfhack/modules/Translation.h"
#include "ModuleFactory.h"

@ -31,10 +31,10 @@ using namespace std;
#include "ContextShared.h"
#include "dfhack/modules/World.h"
#include "dfhack/DFProcess.h"
#include "dfhack/Process.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/DFTypes.h"
#include "dfhack/DFError.h"
#include "dfhack/Types.h"
#include "dfhack/Error.h"
#include "ModuleFactory.h"
using namespace DFHack;

@ -42,10 +42,10 @@ distribution.
#endif
// one file for telling the MSVC compiler where it can shove its pointless warnings
#include "dfhack/DFPragma.h"
#include "dfhack/Pragma.h"
// C99 integer types
#include "dfhack/DFIntegers.h"
#include "dfhack/Integers.h"
#endif // DFCOMMONINTERNAL_H_INCLUDED

@ -1,85 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
#ifndef LINUX_PROCESS_H_INCLUDED
#define LINUX_PROCESS_H_INCLUDED
#include "dfhack/DFProcess.h"
namespace DFHack
{
class LinuxProcessBase : public Process
{
protected:
VersionInfo * my_descriptor;
pid_t my_pid;
string memFile;
int memFileHandle;
bool attached:1;
bool suspended:1;
bool identified:1;
public:
LinuxProcessBase(uint32_t pid);
~LinuxProcessBase();
void readQuad(const uint32_t address, uint64_t & value);
void writeQuad(const uint32_t address, const uint64_t value);
void readDWord(const uint32_t address, uint32_t & value);
void writeDWord(const uint32_t address, const uint32_t value);
void readFloat(const uint32_t address, float & value);
void readWord(const uint32_t address, uint16_t & value);
void writeWord(const uint32_t address, const uint16_t value);
void readByte(const uint32_t address, uint8_t & value);
void writeByte(const uint32_t address, const uint8_t value);
void read( uint32_t address, uint32_t length, uint8_t* buffer);
void write(uint32_t address, uint32_t length, uint8_t* buffer);
const std::string readCString (uint32_t offset);
bool isSuspended();
bool isAttached();
bool isIdentified();
VersionInfo *getDescriptor();
int getPID();
std::string getPath();
bool getThreadIDs(std::vector<uint32_t> & threads );
void getMemRanges(std::vector<t_memrange> & ranges );
// get module index by name and version. bool 1 = error
bool getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT) { OUTPUT=0; return false;};
// get the SHM start if available
char * getSHMStart (void){return 0;};
// set a SHM command and wait for a response
bool SetAndWait (uint32_t state){return false;};
};
}
#endif

@ -1,46 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
namespace DFHack {
class Process;
class MicrosoftSTL
{
private:
uint32_t STLSTR_buf_off;
uint32_t STLSTR_size_off;
uint32_t STLSTR_cap_off;
Process* p;
public:
void init(Process* p);
const std::string readSTLString (uint32_t offset);
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity);
size_t writeSTLString(const uint32_t address, const std::string writeString);
// get class name of an object with rtti/type info
std::string readClassName(uint32_t vptr);
};
}

@ -1,39 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef PROCESS_FACTORY_H_INCLUDED
#define PROCESS_FACTORY_H_INCLUDED
#include "dfhack/DFProcess.h"
#include "dfhack/VersionInfoFactory.h"
namespace DFHack
{
Process* createNormalProcess(uint32_t pid, VersionInfoFactory * factory);
Process* createSHMProcess(uint32_t pid, VersionInfoFactory * factory);
#ifdef LINUX_BUILD
Process* createWineProcess(uint32_t pid, VersionInfoFactory * factory);
#endif
}
#endif

@ -1,152 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
#ifndef SHM_PROCESS_H_INCLUDED
#define SHM_PROCESS_H_INCLUDED
#include "dfhack/DFProcess.h"
#include "dfhack/DFIntegers.h"
#include "dfhack/VersionInfoFactory.h"
namespace DFHack
{
class DFHACK_EXPORT SHMProcess : public Process
{
private:
class Private;
Private * const d;
public:
SHMProcess(uint32_t PID, VersionInfoFactory * factory);
~SHMProcess();
// Set up stuff so we can read memory
bool attach();
bool detach();
bool suspend();
bool asyncSuspend();
bool resume();
bool forceresume();
void readQuad(const uint32_t address, uint64_t & value);
void writeQuad(const uint32_t address, const uint64_t value);
void readDWord(const uint32_t address, uint32_t & value);
void writeDWord(const uint32_t address, const uint32_t value);
void readFloat(const uint32_t address, float & value);
void readWord(const uint32_t address, uint16_t & value);
void writeWord(const uint32_t address, const uint16_t value);
void readByte(const uint32_t address, uint8_t & value);
void writeByte(const uint32_t address, const uint8_t value);
void read( uint32_t address, uint32_t length, uint8_t* buffer);
void write(uint32_t address, uint32_t length, uint8_t* buffer);
const std::string readSTLString (uint32_t offset);
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity);
size_t writeSTLString(const uint32_t address, const std::string writeString);
void readSTLVector(const uint32_t address, t_vecTriplet & triplet);
void writeSTLVector(const uint32_t address, t_vecTriplet & triplet);
// get class name of an object with rtti/type info
std::string doReadClassName(uint32_t vptr);
const std::string readCString (uint32_t offset);
bool isSuspended();
bool isAttached();
bool isIdentified();
bool getThreadIDs(std::vector<uint32_t> & threads );
void getMemRanges(std::vector<t_memrange> & ranges );
VersionInfo *getDescriptor();
int getPID();
std::string getPath();
// get module index by name and version. bool 1 = error
bool getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT);
// get the SHM start if available
char * getSHMStart (void);
bool SetAndWait (uint32_t state);
private:
bool acquireSuspendLock();
bool releaseSuspendLock();
};
class SHMProcess::Private
{
public:
Private(SHMProcess * self_);
~Private(){}
VersionInfo * memdescriptor;
SHMProcess * self;
char *shm_addr;
int attachmentIdx;
bool attached;
bool locked;
bool identified;
bool useYield;
uint8_t vector_start;
#ifdef LINUX_BUILD
pid_t process_ID;
int shm_ID;
int server_lock;
int client_lock;
int suspend_lock;
#else
typedef uint32_t pid_t;
uint32_t process_ID;
HANDLE DFSVMutex;
HANDLE DFCLMutex;
HANDLE DFCLSuspendMutex;
#endif
bool validate(VersionInfoFactory * factory);
bool Aux_Core_Attach(bool & versionOK, pid_t& PID);
bool SetAndWait (uint32_t state);
bool GetLocks();
bool AreLocksOk();
void FreeLocks();
};
}
// some helpful macros to keep the code bloat in check
#define SHMCMD ( (uint32_t *) shm_addr)[attachmentIdx]
#define D_SHMCMD ( (uint32_t *) (d->shm_addr))[d->attachmentIdx]
#define SHMHDR ((shm_core_hdr *)shm_addr)
#define D_SHMHDR ((shm_core_hdr *)(d->shm_addr))
#define SHMDATA(type) ((type *)(shm_addr + SHM_HEADER))
#define D_SHMDATA(type) ((type *)(d->shm_addr + SHM_HEADER))
#endif

@ -1,56 +0,0 @@
################################################################################
# DFCONNECT
###
SET(DFCONNECT_HDRS
shms.h
mod-core.h
mod-maps.h
)
SET(PROJECT_SRCS
mod-core.cpp
mod-maps.cpp
#mod-creature40d.cpp
)
SET(PROJECT_HDRS_LINUX
)
SET(PROJECT_HDRS_WINDOWS
)
SET(PROJECT_SRCS_LINUX
shms-linux.cpp
)
SET(PROJECT_SRCS_WINDOWS
shms-windows.cpp
)
IF(UNIX)
LIST(APPEND PROJECT_HDRS ${PROJECT_HDRS_LINUX})
LIST(APPEND PROJECT_SRCS ${PROJECT_SRCS_LINUX})
ELSE(UNIX)
LIST(APPEND PROJECT_HDRS ${PROJECT_HDRS_WINDOWS})
LIST(APPEND PROJECT_SRCS ${PROJECT_SRCS_WINDOWS})
ENDIF(UNIX)
SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE )
LIST(APPEND PROJECT_SRCS ${PROJECT_HDRS})
#IF(CMAKE_SIZEOF_VOID_P EQUAL 4)
add_definitions(-DBUILD_SHM)
IF(UNIX)
add_definitions(-DLINUX_BUILD)
SET(PROJECT_LIBS rt)
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden")
ADD_LIBRARY(dfconnect SHARED ${PROJECT_SRCS})
TARGET_LINK_LIBRARIES(dfconnect ${PROJECT_LIBS})
ELSE(UNIX)
# SET(PROJECT_LIBS psapi)
ADD_LIBRARY(SDL SHARED ${PROJECT_SRCS})
TARGET_LINK_LIBRARIES(SDL ${PROJECT_LIBS})
ENDIF(UNIX)
#ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 4)

@ -1,364 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix)
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 is the source for the DF <-> dfhack shm bridge's core module.
*/
#include <stdio.h>
#include "dfhack/DFIntegers.h"
#include <stdlib.h>
#include <string.h>
#include <string>
#include <vector>
#define SHM_INTERNAL // for things only visible to the SHM
#include "shms.h"
#include "mod-core.h"
#include "mod-maps.h"
#include "mod-creature40d.h"
std::vector <DFPP_module> module_registry;
// shared by shms_OS
extern int errorstate;
extern char *shm;
extern int shmid;
// file-globals
bool useYield = 0;
int currentClient = -1;
#define SHMHDR ((shm_core_hdr *)shm)
#define SHMCMD ((uint32_t *)shm )[currentClient]
#define SHMDATA(type) ((type *)(shm + SHM_HEADER))
void ReadRaw (void * data)
{
memcpy(SHMDATA(void), (void *) SHMHDR->address,SHMHDR->length);
}
void ReadQuad (void * data)
{
SHMHDR->Qvalue = *((uint64_t*) SHMHDR->address);
}
void ReadDWord (void * data)
{
SHMHDR->value = *((uint32_t*) SHMHDR->address);
}
void ReadWord (void * data)
{
SHMHDR->value = *((uint16_t*) SHMHDR->address);
}
void ReadByte (void * data)
{
SHMHDR->value = *((uint8_t*) SHMHDR->address);
}
void WriteRaw (void * data)
{
memcpy((void *)SHMHDR->address, SHMDATA(void),SHMHDR->length);
}
void WriteQuad (void * data)
{
(*(uint64_t*)SHMHDR->address) = SHMHDR->Qvalue;
}
void WriteDWord (void * data)
{
(*(uint32_t*)SHMHDR->address) = SHMHDR->value;
}
void WriteWord (void * data)
{
(*(uint16_t*)SHMHDR->address) = SHMHDR->value;
}
void WriteByte (void * data)
{
(*(uint8_t*)SHMHDR->address) = SHMHDR->value;
}
void ReadSTLString (void * data)
{
std::string * myStringPtr = (std::string *) SHMHDR->address;
unsigned int l = myStringPtr->length();
SHMHDR->value = l;
// FIXME: there doesn't have to be a null terminator!
strncpy( SHMDATA(char),myStringPtr->c_str(),l+1);
}
void WriteSTLString (void * data)
{
std::string * myStringPtr = (std::string *) SHMHDR->address;
// here we DO expect a 0 terminator
myStringPtr->assign( SHMDATA(const char) );
}
// MIT HAKMEM bitcount
int bitcount(uint32_t n)
{
register uint32_t tmp;
tmp = n - ((n >> 1) & 033333333333) - ((n >> 2) & 011111111111);
return ((tmp + (tmp >> 3)) & 030707070707) % 63;
}
// get local and remote affinity, set up yield if required (single core available)
void CoreAttach (void * data)
{
// sync affinity
uint32_t local = OS_getAffinity();
uint32_t remote = SHMDATA(coreattach)->cl_affinity;
uint32_t pool = local | remote;
SHMDATA(coreattach)->sv_useYield = useYield = (bitcount(pool) == 1);
// return our PID
SHMDATA(coreattach)->sv_PID = OS_getPID();
// return core version
SHMDATA(coreattach)->sv_version = module_registry[0].version;
}
void FindModule (void * data)
{
bool found = false;
modulelookup * payload = SHMDATA(modulelookup);
std::string test = payload->name;
uint32_t version = payload->version;
for(unsigned int i = 0; i < module_registry.size();i++)
{
if(module_registry[i].name == test && module_registry[i].version == version)
{
// gotcha
SHMHDR->value = i;
found = true;
break;
}
}
SHMHDR->error = !found;
}
void FindCommand (void * data)
{
bool found = false;
commandlookup * payload = SHMDATA(commandlookup);
std::string modname = payload->module;
std::string cmdname = payload->name;
uint32_t version = payload->version;
for(unsigned int i = 0; i < module_registry.size();i++)
{
if(module_registry[i].name == modname && module_registry[i].version == version)
{
for(unsigned int j = 0 ; j < module_registry[i].commands.size();j++)
{
if(module_registry[i].commands[j].name == cmdname)
{
// gotcha
SHMHDR->value = j + (i << 16);
SHMHDR->error = false;
return;
}
}
}
}
SHMHDR->error = true;
}
void ReleaseSuspendLock( void * data )
{
OS_releaseSuspendLock(currentClient);
}
void AcquireSuspendLock( void * data )
{
OS_lockSuspendLock(currentClient);
}
DFPP_module InitCore(void)
{
DFPP_module core;
core.name = "Core";
core.version = CORE_VERSION;
core.modulestate = 0; // this one is dumb and has no real state
core.reserve(NUM_CORE_CMDS);
// basic states
core.set_command(CORE_RUNNING, CANCELLATION, "Running");
//core.set_command(CORE_RUN, FUNCTION, "Run!",AcquireSuspendLock,CORE_RUNNING);
core.set_command(CORE_RUN, CANCELLATION, "Run!",0,CORE_RUNNING);
core.set_command(CORE_STEP, CANCELLATION, "Suspend on next step",0,CORE_SUSPEND);// set command to CORE_SUSPEND, check next client
core.set_command(CORE_SUSPEND, FUNCTION, "Suspend", ReleaseSuspendLock , CORE_SUSPENDED, LOCKING_LOCKS);
core.set_command(CORE_SUSPENDED, CLIENT_WAIT, "Suspended");
core.set_command(CORE_ERROR, CANCELLATION, "Error");
// utility commands
core.set_command(CORE_ATTACH, FUNCTION,"Core attach",CoreAttach, CORE_SUSPENDED);
core.set_command(CORE_ACQUIRE_MODULE, FUNCTION, "Module lookup", FindModule, CORE_SUSPENDED);
core.set_command(CORE_ACQUIRE_COMMAND, FUNCTION, "Command lookup", FindCommand, CORE_SUSPENDED);
// raw reads
core.set_command(CORE_READ, FUNCTION,"Raw read",ReadRaw, CORE_SUSPENDED);
core.set_command(CORE_READ_QUAD, FUNCTION,"Read QUAD",ReadQuad, CORE_SUSPENDED);
core.set_command(CORE_READ_DWORD, FUNCTION,"Read DWORD",ReadDWord, CORE_SUSPENDED);
core.set_command(CORE_READ_WORD, FUNCTION,"Read WORD",ReadWord, CORE_SUSPENDED);
core.set_command(CORE_READ_BYTE, FUNCTION,"Read BYTE",ReadByte, CORE_SUSPENDED);
// raw writes
core.set_command(CORE_WRITE, FUNCTION, "Raw write", WriteRaw, CORE_SUSPENDED);
core.set_command(CORE_WRITE_QUAD, FUNCTION, "Write QUAD", WriteQuad, CORE_SUSPENDED);
core.set_command(CORE_WRITE_DWORD, FUNCTION, "Write DWORD", WriteDWord, CORE_SUSPENDED);
core.set_command(CORE_WRITE_WORD, FUNCTION, "Write WORD", WriteWord, CORE_SUSPENDED);
core.set_command(CORE_WRITE_BYTE, FUNCTION, "Write BYTE", WriteByte, CORE_SUSPENDED);
// stl string commands
core.set_command(CORE_READ_STL_STRING, FUNCTION, "Read STL string", ReadSTLString, CORE_SUSPENDED);
core.set_command(CORE_READ_C_STRING, CLIENT_WAIT, "RESERVED");
core.set_command(CORE_WRITE_STL_STRING, FUNCTION, "Write STL string", WriteSTLString, CORE_SUSPENDED);
return core;
}
void InitModules (void)
{
// create the core module
module_registry.push_back(InitCore());
module_registry.push_back(DFHack::Server::Maps::Init());
//module_registry.push_back(DFHack::Server::Creatures::Init());
for(int i = 0; i < module_registry.size();i++)
{
fprintf(stderr,"Initialized module %s, version %d\n",module_registry[i].name.c_str(),module_registry[i].version);
}
// TODO: dynamic module init
}
void KillModules (void)
{
for(unsigned int i = 0; i < module_registry.size();i++)
{
if(module_registry[i].modulestate)
free(module_registry[i].modulestate);
}
module_registry.clear();
}
void SHM_Act (void)
{
volatile uint32_t atomic = 0;
if(errorstate)
{
return;
}
//static uint oldcl = 88;
for(currentClient = 0; currentClient < SHM_MAX_CLIENTS;currentClient++)
{
// set the offset for the shared memory used for the client
uint32_t numwaits = 0;
check_again: // goto target!!!
if(numwaits == 10000)
{
// this tests if there's a process on the other side
if(isValidSHM(currentClient))
{
numwaits = 0;
}
else
{
full_barrier
SHMCMD = CORE_RUNNING;
fprintf(stderr,"dfhack: Broke out of loop, other process disappeared.\n");
}
}
full_barrier // I don't want the compiler to reorder my code.
//fprintf(stderr,"%d: %x %x\n",currentClient, (uint) SHMHDR, (uint) &(SHMHDR->cmd[currentClient]));
// this is very important! copying two words separately from the command variable leads to inconsistency.
// Always copy the thing in one go.
// Also, this whole SHM thing probably only works on intel processors
atomic = SHMCMD;
full_barrier
DFPP_module & mod = module_registry[ ((shm_cmd)atomic).parts.module ];
DFPP_command & cmd = mod.commands[ ((shm_cmd)atomic).parts.command ];
/*
if(atomic == CORE_RUNNING)
{
// we are running again for this process
// reaquire the suspend lock
OS_lockSuspendLock(currentClient);
continue;
}
full_barrier
*/
// set next state BEFORE we act on the command - good for locks
if(cmd.locking == LOCKING_LOCKS)
{
if(cmd.nextState != -1) SHMCMD = cmd.nextState;
}
if(cmd._function)
{
cmd._function(mod.modulestate);
}
full_barrier
// set next state AFTER we act on the command - good for busy waits
if(cmd.locking == LOCKING_BUSY)
{
/*
char text [512];
char text2 [512];
sprintf (text,"Client %d invoked %d:%d = %x = %s\n",currentClient,((shm_cmd)atomic).parts.module,((shm_cmd)atomic).parts.command, cmd._function,cmd.name.c_str());
sprintf(text2, "Server set %d\n",cmd.nextState);
*/
// FIXME: WHAT HAPPENS WHEN A 'NEXTSTATE' IS FROM A DIFFERENT MODULE THAN 'CORE'? Yeah. It doesn't work.
if(cmd.nextState != -1) SHMCMD = cmd.nextState;
//MessageBox(0,text,text2, MB_OK);
//fflush(stderr); // make sure this finds its way to the terminal!
}
full_barrier
if(cmd.type != CANCELLATION)
{
if(useYield)
{
SCHED_YIELD
}
numwaits ++; // watchdog timeout
goto check_again;
}
full_barrier
// we are running again for this process
// reaquire the suspend lock
OS_lockSuspendLock(currentClient);
}
}

@ -1,100 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix)
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 SHMS_CORE_H
#define SHMS_CORE_H
// increment on every core change
#define CORE_VERSION 10
typedef struct
{
shm_cmd cmd[SHM_MAX_CLIENTS]; // MANDATORY!
uint32_t address;
uint32_t value;
uint32_t length;
uint32_t error;
uint64_t Qvalue;
} shm_core_hdr;
typedef struct
{
uint32_t version;
char name[256];
} modulelookup;
typedef struct
{
uint32_t version;
char module[256];
char name[256];
} commandlookup;
typedef struct
{
uint32_t sv_version; // output
uint32_t cl_affinity; // input
uint32_t sv_PID; // output
uint32_t sv_useYield; // output
} coreattach;
enum CORE_COMMAND
{
// basic states
CORE_RUNNING = 0, // no command, normal server execution
CORE_RUN, // sent by the client to restart the server execution
CORE_STEP, // client suspend sets step
CORE_SUSPEND, // client notifies server to wait for commands (server is stalled in busy wait)
CORE_SUSPENDED, // response to WAIT, server is stalled in busy wait
CORE_ERROR, // there was a server error
// utility commands
CORE_ATTACH, // compare affinity, get core version and process ID
CORE_ACQUIRE_MODULE, // get index of a loaded module by name and version
CORE_ACQUIRE_COMMAND, // get module::command callsign by module name, command name and module version
// raw reads
CORE_READ, // cl -> sv, read some data
CORE_READ_QUAD, // cl -> sv, read a quad
CORE_READ_DWORD, // cl -> sv, read a dword
CORE_READ_WORD, // cl -> sv, read a word
CORE_READ_BYTE, // cl -> sv, read a byte
// raw writes
CORE_WRITE,// client writes to server
CORE_WRITE_QUAD,// client writes a QUAD to server
CORE_WRITE_DWORD,// client writes a DWORD to server
CORE_WRITE_WORD,// client writes a WORD to server
CORE_WRITE_BYTE,// client writes a BYTE to server
// string functions
CORE_READ_STL_STRING,// client requests contents of STL string at address
CORE_READ_C_STRING,// client requests contents of a C string at address, max length (0 means zero terminated)
CORE_WRITE_STL_STRING,// client wants to set STL string at address to something
// total commands
NUM_CORE_CMDS
};
#endif

@ -1,105 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix)
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 MOD_CREATURES2010_H
#define MOD_CREATURES2010_H
namespace DFHack
{
namespace Creatures2010
{
#define CREATURES2010_VERSION 1
typedef struct
{
// creature offsets
uint32_t vector;
uint32_t pos_offset;
uint32_t profession_offset;
uint32_t custom_profession_offset;
uint32_t race_offset;
int32_t civ_offset;
uint32_t flags1_offset;
uint32_t flags2_offset;
uint32_t name_offset;
uint32_t sex_offset;
uint32_t caste_offset;
uint32_t id_offset;
uint32_t labors_offset;
uint32_t happiness_offset;
uint32_t artifact_name_offset;
uint32_t physical_offset;
uint32_t mood_offset;
uint32_t mood_skill_offset;
uint32_t pickup_equipment_bit;
uint32_t soul_vector_offset;
uint32_t default_soul_offset;
uint32_t current_job_offset;
// soul offsets
uint32_t soul_skills_vector_offset;
// name offsets (needed for reading creature names)
uint32_t name_firstname_offset;
uint32_t name_nickname_offset;
uint32_t name_words_offset;
uint32_t soul_mental_offset;
uint32_t soul_traits_offset;
uint32_t appearance_vector_offset;
uint32_t birth_year_offset;
uint32_t birth_time_offset;
uint32_t inventory_offset;
} creature_offsets;
typedef struct
{
bool inited;
creature_offsets offsets;
} creature_modulestate;
typedef struct
{
shm_cmd cmd[SHM_MAX_CLIENTS]; // MANDATORY!
// box
uint32_t x;
uint32_t y;
uint32_t z;
uint32_t x2;
uint32_t y2;
uint32_t z2;
// starting index
int32_t index;
} shm_creature_hdr;
enum CREATURE_COMMAND
{
CREATURE_INIT = 0, // initialization
CREATURE_FIND_IN_BOX,
CREATURE_AT_INDEX,
NUM_CREATURE_CMDS
};
DFPP_module Init(void);
}
}
#endif

@ -1,197 +0,0 @@
#include <string>
#include <vector>
#include <DFIntegers.h>
#include "shms.h"
#include "mod-core.h"
#include "mod-creature40d.h"
#include <DFTypes.h>
#include <modules/Creatures.h>
#include <string.h>
#include <malloc.h>
#include <vector>
#include <stdio.h>
extern char *shm;
namespace DFHack{
namespace Server{
namespace Creatures{ // start of namespace
#define SHMHDR ((shm_creature_hdr *)shm)
#define SHMDATA(type) ((type *)(shm + SHM_HEADER))
void readName(t_name & name, char * address, creature_offsets & offsets)
{
// custom profession
std::string * fname = (std::string *) (address + offsets.name_firstname_offset);
strncpy(name.first_name,fname->c_str(),127);
name.first_name[127] = 0;
std::string * nname = (std::string *) (address + offsets.name_nickname_offset);
strncpy(name.nickname,nname->c_str(),127);
name.nickname[127] = 0;
memcpy(name.words, (void *)(address + offsets.name_words_offset), 48);
}
void InitOffsets (void* data)
{
creature_modulestate * state = (creature_modulestate *) data;
memcpy((void *) &(state->offsets), SHMDATA(void), sizeof(creature_offsets));
((creature_modulestate *) data)->inited = true;
}
void ReadCreatureAtIndex(void *data)
{
creature_modulestate * state = (creature_modulestate *) data;
creature_offsets & offsets = state->offsets;
std::vector<char *> * creaturev = (std::vector<char *> *) (offsets.creature_vector + offsets.vector_correct);
uint32_t length = creaturev->size();
int32_t index = SHMHDR->index;
// read pointer from vector at position
char * temp = (char *) creaturev->at (index);
t_creature *furball = SHMDATA(t_creature);
furball->origin = (uint32_t) temp;
//read creature from memory
memcpy(&(furball->x),temp + offsets.creature_pos_offset,3* sizeof(uint16_t));
furball->type = *(uint32_t *) (temp + offsets.creature_type_offset);
furball->flags1.whole = *(uint32_t *) (temp + offsets.creature_flags1_offset);
furball->flags2.whole = *(uint32_t *) (temp + offsets.creature_flags2_offset);
// names
readName(furball->name,temp + offsets.creature_name_offset, offsets);
readName(furball->squad_name, temp + offsets.creature_squad_name_offset, offsets);
readName(furball->artifact_name, temp + offsets.creature_artifact_name_offset, offsets);
// custom profession
std::string * custprof = (std::string *) (temp + offsets.creature_custom_profession_offset);
strncpy(furball->custom_profession,custprof->c_str(),127);
furball->custom_profession[127] = 0;
// labors
memcpy(furball->labors, temp + offsets.creature_labors_offset, NUM_CREATURE_LABORS);
// traits
memcpy(furball->traits, temp + offsets.creature_traits_offset, sizeof (uint16_t) * NUM_CREATURE_TRAITS);
typedef struct
{
uint8_t id;
junk_fill <3> fill1;
uint8_t rating;
junk_fill <3> fill2;
uint16_t experience;
} raw_skill;
// learned skills
std::vector <void *> * skillv = (std::vector <void *> *) (temp + offsets.creature_skills_offset + offsets.vector_correct);
furball->numSkills = skillv->size();
for (uint32_t i = 0; i < furball->numSkills;i++)
{
//skills.read(i, (uint8_t *) &temp2);
// a byte: this gives us 256 skills maximum.
furball->skills[i].id = ( (raw_skill*) skillv->at(i))->id;
furball->skills[i].rating = ( (raw_skill*) skillv->at(i))->rating;
furball->skills[i].experience = ( (raw_skill*) skillv->at(i))->experience;
}
// profession
furball->profession = *(uint8_t *) (temp + offsets.creature_profession_offset);
// current job HACK: the job object isn't cleanly represented here
uint32_t jobIdAddr = *(uint32_t *) (temp + offsets.creature_current_job_offset);
if (jobIdAddr)
{
furball->current_job.active = true;
furball->current_job.jobId = *(uint8_t *) (jobIdAddr + offsets.creature_current_job_id_offset);
}
else
{
furball->current_job.active = false;
}
//likes
std::vector <t_like *> * likev = (std::vector <t_like *> *) (temp + offsets.creature_likes_offset + offsets.vector_correct);
furball->numLikes = likev->size();
for(uint32_t i = 0;i<furball->numLikes;i++)
{
memcpy(&furball->likes[i], likev->at(i), sizeof(t_skill));
}
furball->mood = *(int16_t *) (temp + offsets.creature_mood_offset);
furball->happiness = *(uint32_t *) (temp + offsets.creature_happiness_offset);
furball->id = *(uint32_t *) (temp + offsets.creature_id_offset);
furball->agility = *(uint32_t *) (temp + offsets.creature_agility_offset);
furball->strength = *(uint32_t *) (temp + offsets.creature_strength_offset);
furball->toughness = *(uint32_t *) (temp + offsets.creature_toughness_offset);
furball->money = *(uint32_t *) (temp + offsets.creature_money_offset);
furball->squad_leader_id = *(int32_t*) (temp + offsets.creature_squad_leader_id_offset);
furball->sex = *(uint8_t*) (temp + offsets.creature_sex_offset);
furball->pregnancy_timer = *(uint32_t *)(temp+offsets.creature_pregnancy_offset);
furball->blood_max = *(int32_t*) (temp+offsets.creature_blood_max_offset);
furball->blood_current = *(int32_t*) (temp+offsets.creature_blood_current_offset);
furball->bleed_rate = *(uint32_t*) (temp+offsets.creature_bleed_offset);
}
void FindNextCreatureInBox (void * data)
{
int32_t index = SHMHDR->index;
// sanity
if(index == -1) return;
creature_modulestate * state = (creature_modulestate *) data;
creature_offsets & offsets = state->offsets;
uint32_t x,y,z,x2,y2,z2;
x = SHMHDR->x; x2 = SHMHDR->x2;
y = SHMHDR->y; y2 = SHMHDR->y2;
z = SHMHDR->z; z2 = SHMHDR->x2;
std::vector<char *> * creaturev = (std::vector<char *> *) (offsets.creature_vector + offsets.vector_correct);
uint32_t length = creaturev->size();
typedef uint16_t coords[3];
// look at all creatures, starting at index
// if you find one in the specified 'box', return the creature in the data
// section and the index in the header
for(;index < length;index++)
{
coords& coo = *(coords*) (creaturev->at(index) + offsets.creature_pos_offset);
if(coo[0] >=x && coo[0] < x2
&& coo[1] >=y && coo[1] < y2
&& coo[2] >=z && coo[2] < z2)
{
// we found a creature!
SHMHDR->index = index;
ReadCreatureAtIndex(data);
return; // we're done here
}
}
// nothing found
SHMHDR->index = -1;
}
DFPP_module Init( void )
{
DFPP_module creatures;
creatures.name = "Creatures40d";
creatures.version = CREATURES40D_VERSION;
// freed by the core
creatures.modulestate = malloc(sizeof(creature_modulestate)); // we store a flag
memset(creatures.modulestate,0,sizeof(creature_modulestate));
creatures.reserve(NUM_CREATURE_CMDS);
creatures.set_command(CREATURE_INIT, FUNCTION, "Supply the Creature40d module with offsets",InitOffsets,CORE_SUSPENDED);
creatures.set_command(CREATURE_FIND_IN_BOX, FUNCTION, "Get next creature in a box, return new index or -1", FindNextCreatureInBox, CORE_SUSPENDED);
creatures.set_command(CREATURE_AT_INDEX, FUNCTION, "Get creature at index", ReadCreatureAtIndex, CORE_SUSPENDED);
return creatures;
}
}}} // end of namespace

@ -1,109 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix)
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 MOD_CREATURES40D_H
#define MOD_CREATURES40D_H
namespace DFHack
{
namespace Server
{
namespace Creatures
{
#define CREATURES40D_VERSION 1
typedef struct
{
// creature offsets
uint32_t creature_vector;
uint32_t creature_pos_offset;
uint32_t creature_type_offset;
uint32_t creature_flags1_offset;
uint32_t creature_flags2_offset;
uint32_t creature_name_offset;
uint32_t creature_custom_profession_offset;
uint32_t creature_profession_offset;
uint32_t creature_sex_offset;
uint32_t creature_id_offset;
uint32_t creature_squad_name_offset;
uint32_t creature_squad_leader_id_offset;
uint32_t creature_money_offset;
uint32_t creature_current_job_offset;
uint32_t creature_current_job_id_offset;
uint32_t creature_strength_offset;
uint32_t creature_agility_offset;
uint32_t creature_toughness_offset;
uint32_t creature_skills_offset;
uint32_t creature_labors_offset;
uint32_t creature_happiness_offset;
uint32_t creature_traits_offset;
uint32_t creature_likes_offset;
uint32_t creature_artifact_name_offset;
uint32_t creature_mood_offset;
uint32_t creature_pregnancy_offset;
uint32_t creature_blood_max_offset;
uint32_t creature_blood_current_offset;
uint32_t creature_bleed_offset;
// name offsets (needed for reading creature names)
uint32_t name_firstname_offset;
uint32_t name_nickname_offset;
uint32_t name_words_offset;
// HACK: vector address correction for SHM server
int32_t vector_correct;
} creature_offsets;
typedef struct
{
bool inited;
creature_offsets offsets;
} creature_modulestate;
typedef struct
{
shm_cmd cmd[SHM_MAX_CLIENTS]; // MANDATORY!
// box
uint32_t x;
uint32_t y;
uint32_t z;
uint32_t x2;
uint32_t y2;
uint32_t z2;
// starting index
int32_t index;
} shm_creature_hdr;
enum CREATURE_COMMAND
{
CREATURE_INIT = 0, // initialization
CREATURE_FIND_IN_BOX,
CREATURE_AT_INDEX,
NUM_CREATURE_CMDS
};
DFPP_module Init(void);
}
}
}
#endif

@ -1,130 +0,0 @@
#include <string>
#include <vector>
#include <map>
#include <dfhack/DFIntegers.h>
#include "shms.h"
#include "mod-core.h"
#include "mod-maps.h"
#include <dfhack/DFTypes.h>
#include <dfhack/modules/Maps.h>
using namespace DFHack;
using namespace DFHack::Server::Maps;
#include <string.h>
#include <malloc.h>
extern char *shm;
//TODO: circular buffer streaming primitives required
//TODO: commands can fail without the proper offsets. Hot to handle that?
namespace DFHack{
namespace Server{ // start of namespace
namespace Maps{ // start of namespace
#define SHMHDR ((shm_maps_hdr *)shm)
#define SHMCMD ((shm_cmd *)shm)->pingpong
#define SHMDATA(type) ((type *)(shm + SHM_HEADER))
void NullCommand (void* data)
{
};
void InitOffsets (void* data)
{
maps_modulestate * state = (maps_modulestate *) data;
memcpy((void *) &(state->offsets), SHMDATA(void), sizeof(maps_offsets));
((maps_modulestate *) data)->inited = true;
}
void GetMapSize (void *data)
{
maps_modulestate * state = (maps_modulestate *) data;
if(state->inited)
{
SHMHDR->x = *(uint32_t *) (state->offsets.x_count_offset);
SHMHDR->y = *(uint32_t *) (state->offsets.y_count_offset);
SHMHDR->z = *(uint32_t *) (state->offsets.z_count_offset);
SHMHDR->error = false;
}
else
{
SHMHDR->error = true;
}
}
struct mblock
{
uint32_t * ptr_to_dirty;
};
inline void ReadBlockByAddress (void * data)
{
maps_modulestate * state = (maps_modulestate *) data;
maps_offsets & offsets = state->offsets;
mblock * block = (mblock *) SHMHDR->address;
if(block)
{
memcpy(&(SHMDATA(mapblock40d)->tiletypes), ((char *) block) + offsets.tile_type_offset, sizeof(SHMDATA(mapblock40d)->tiletypes));
memcpy(&(SHMDATA(mapblock40d)->designation), ((char *) block) + offsets.designation_offset, sizeof(SHMDATA(mapblock40d)->designation));
memcpy(&(SHMDATA(mapblock40d)->occupancy), ((char *) block) + offsets.occupancy_offset, sizeof(SHMDATA(mapblock40d)->occupancy));
memcpy(&(SHMDATA(mapblock40d)->biome_indices), ((char *) block) + offsets.biome_stuffs, sizeof(SHMDATA(mapblock40d)->biome_indices));
SHMDATA(mapblock40d)->blockflags.whole = *block->ptr_to_dirty;
SHMDATA(mapblock40d)->local_feature = *(int16_t *)((char*) block + offsets.local_feature_offset);
SHMDATA(mapblock40d)->global_feature = *(int16_t *)((char*) block + offsets.global_feature_offset);
SHMDATA(mapblock40d)->origin = (uint32_t)(uint64_t)block; // this is STUPID
SHMHDR->error = false;
}
else
{
SHMHDR->error = true;
}
}
void ReadBlockByCoords (void * data)
{
maps_modulestate * state = (maps_modulestate *) data;
maps_offsets & offsets = state->offsets;
/* map_offset is a pointer to
a pointer to
an X block of pointers to
an Y blocks of pointers to
a Z blocks of pointers to
map blocks
only Z blocks can have NULL pointers? TODO: verify
*/
mblock * *** mapArray = *(mblock * ****)offsets.map_offset;
SHMHDR->address = (uint32_t) (uint64_t) mapArray[SHMHDR->x][SHMHDR->y][SHMHDR->z];// this is STUPID
ReadBlockByAddress(data); // I wonder... will this inline properly?
}
DFPP_module Init( void )
{
DFPP_module maps;
maps.name = "Maps";
maps.version = MAPS_VERSION;
// freed by the core
maps.modulestate = malloc(sizeof(maps_modulestate)); // we store a flag
memset(maps.modulestate,0,sizeof(maps_modulestate));
maps.reserve(NUM_MAPS_CMDS);
// client sends a maps_offsets struct -> inited = true;
maps.set_command(MAP_INIT, FUNCTION, "Supply the module with offsets",InitOffsets,CORE_SUSPENDED);
maps.set_command(MAP_GET_SIZE, FUNCTION, "Get map size in 16x16x1 tile blocks", GetMapSize, CORE_SUSPENDED);
maps.set_command(MAP_READ_BLOCK_BY_COORDS, FUNCTION, "Read the whole block with specified coords", ReadBlockByCoords, CORE_SUSPENDED);
maps.set_command(MAP_READ_BLOCK_BY_ADDRESS, FUNCTION, "Read the whole block from an address", ReadBlockByAddress, CORE_SUSPENDED);
// will it fit into 1MB? We shouldn't assume this is the case
maps.set_command(MAP_READ_BLOCKTREE, FUNCTION,"Get the tree of block pointers as a single structure", NullCommand, CORE_SUSPENDED);
// really doesn't fit into 1MB, there should be a streaming variant to better utilize context switches
maps.set_command(MAP_READ_BLOCKS_3D, FUNCTION, "Read a range of blocks between two sets of coords", NullCommand, CORE_SUSPENDED);
return maps;
}
}}} // end of namespace

@ -1,134 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix)
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 MOD_MAPS_H
#define MOD_MAPS_H
#include "dfhack/DFTypes.h"
namespace DFHack
{
namespace Server
{
namespace Maps
{
// increment on every change
#define MAPS_VERSION 5
typedef struct
{
uint32_t map_offset;// = d->offset_descriptor->getAddress ("map_data");
uint32_t x_count_offset;// = d->offset_descriptor->getAddress ("x_count");
uint32_t y_count_offset;// = d->offset_descriptor->getAddress ("y_count");
uint32_t z_count_offset;// = d->offset_descriptor->getAddress ("z_count");
/*
Block
*/
uint32_t tile_type_offset;// = d->offset_descriptor->getOffset ("type");
uint32_t designation_offset;// = d->offset_descriptor->getOffset ("designation");
uint32_t occupancy_offset;// = d->offset_descriptor->getOffset ("occupancy");
uint32_t biome_stuffs;// = d->offset_descriptor->getOffset ("biome_stuffs");
uint32_t veinvector;// = d->offset_descriptor->getOffset ("v_vein");
uint32_t vegvector;
uint32_t temperature1_offset;
uint32_t temperature2_offset;
uint32_t global_feature_offset;
uint32_t local_feature_offset;
uint32_t vein_mineral_vptr;
uint32_t vein_ice_vptr;
uint32_t vein_spatter_vptr;
uint32_t vein_grass_vptr;
uint32_t vein_worldconstruction_vptr;
/*
GEOLOGY
*/
uint32_t region_x_offset;// = minfo->getAddress ("region_x");
uint32_t region_y_offset;// = minfo->getAddress ("region_y");
uint32_t region_z_offset;// = minfo->getAddress ("region_z");
uint32_t world_regions;// mem->getAddress ("ptr2_region_array");
uint32_t region_size;// = minfo->getHexValue ("region_size");
uint32_t region_geo_index_offset;// = minfo->getOffset ("region_geo_index_off");
uint32_t world_geoblocks_vector;// = minfo->getOffset ("geoblock_vector");
uint32_t world_size_x;// = minfo->getOffset ("world_size_x");
uint32_t world_size_y;// = minfo->getOffset ("world_size_y");
uint32_t geolayer_geoblock_offset;// = minfo->getOffset ("geolayer_geoblock_offset");
uint32_t type_inside_geolayer;// = mem->getOffset ("type_inside_geolayer");
/*
FEATURES
*/
uint32_t world_data;
uint32_t local_f_start; // offset from world_data or absolute address.
uint32_t local_material;
uint32_t local_submaterial;
uint32_t global_vector; // offset from world_data or absolute address.
uint32_t global_funcptr;
uint32_t global_material;
uint32_t global_submaterial;
/*
* Vegetation
*/
uint32_t tree_desc_offset;
} maps_offsets;
typedef struct
{
bool inited;
maps_offsets offsets;
} maps_modulestate;
typedef struct
{
shm_cmd cmd[SHM_MAX_CLIENTS]; // MANDATORY!
uint32_t x;
uint32_t y;
uint32_t z;
uint32_t x2;
uint32_t y2;
uint32_t z2;
uint32_t address;
uint32_t error;
} shm_maps_hdr;
enum MAPS_COMMAND
{
MAP_INIT = 0, // initialization
MAP_PROBE, // check if the map is still there
MAP_GET_SIZE, // get the map size in 16x16x1 blocks
MAP_READ_BLOCKTREE, // read the structure of pointers to blocks
MAP_READ_BLOCK_BY_COORDS, // read block by cords
MAP_READ_BLOCK_BY_ADDRESS, // read block by address
MAP_WRITE_BLOCK,
MAP_READ_BLOCKS_3D, // read blocks between two coords (volumetric)
MAP_READ_ALL_BLOCKS, // read the entire map
MAP_REVEAL, // reveal the whole map
NUM_MAPS_CMDS
};
DFPP_module Init(void);
}
}
}
#endif

@ -1,14 +0,0 @@
Using the shm server:
copy files to DF/libs folder
g++ -fPIC -c dfconnect.c -o dfconnect.o
g++ -shared -o dfconnect.so dfconnect.o -ldl
edit DF/df script and add this line just before DF is called:
export LD_PRELOAD="./libs/dfconnect.so" # Hack DF!
save and run the script!
Has to be compiled for 32bit arch, otherwise the library isn't recognised. Client can be any arch.
Precompiled dfconnect library is made available. dfconnect.so goes in DF/libs, df-hacked script goes in DF/
Run ./df-hacked to use the shared memory API

@ -1,402 +0,0 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix)
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 is the source for the DF <-> dfhack shm bridge
*/
#include <stdio.h>
#include <dlfcn.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <vector>
#include <string>
#include "shms.h"
#include "mod-core.h"
#include <sched.h>
#define DFhackCExport extern "C" __attribute__ ((visibility("default")))
// various crud
int counter = 0;
int errorstate = 0;
char *shm = 0;
int shmid = 0;
bool inited = 0;
int fd_svlock = -1;
int fd_cllock[SHM_MAX_CLIENTS];
int fd_clSlock[SHM_MAX_CLIENTS];
int held_clSlock[SHM_MAX_CLIENTS];
int numheld = SHM_MAX_CLIENTS;
/*******************************************************************************
* SHM part starts here *
*******************************************************************************/
// is the other side still there?
bool isValidSHM(int which)
{
// if we get the client lock here, the client process failed and we need to reclaim our suspend lock
if(lockf(fd_cllock[which],F_TLOCK,0) == 0)
{
// we get back our suspend lock from the cold, dead hands of the former client :P
OS_lockSuspendLock(which);
// free the client lock again
lockf(fd_cllock[which],F_ULOCK,0);
return false;
}
return true;
}
uint32_t OS_getPID()
{
return getpid();
}
uint32_t OS_getAffinity()
{
cpu_set_t mask;
sched_getaffinity(0,sizeof(cpu_set_t),&mask);
// FIXME: truncation
uint32_t affinity = *(uint32_t *) &mask;
return affinity;
}
void OS_lockSuspendLock(int which)
{
if(numheld == SHM_MAX_CLIENTS)
return;
// lock not held by server and can be picked up. OK.
if(held_clSlock[which] == 0 && lockf(fd_clSlock[which],F_LOCK,0) == 0)
{
held_clSlock[which] = 1;
numheld++;
}
// lock couldn't be picked up!
else if (held_clSlock[which] == 0)
{
fprintf(stderr,"lock %d failed to lock\n", which);
}
}
void OS_releaseSuspendLock(int which)
{
/*
if(which >=0 && which < SHM_MAX_CLIENTS)
return;
*/
if(numheld != SHM_MAX_CLIENTS)
{
fprintf(stderr,"TOTAL FAILURE OF LOCKING SYSTEM\n");
return;
}
// lock hel by server and can be released -> OK
if(held_clSlock[which] == 1 && lockf(fd_clSlock[which],F_ULOCK,0) == 0)
{
numheld--;
held_clSlock[which] = 0;
}
// locked and not can't be released? FAIL!
else if (held_clSlock[which] == 1)
fprintf(stderr,"lock %d failed to unlock\n", which);
}
void SHM_Init ( void )
{
// check that we do this only once per process
if(inited)
{
fprintf(stderr, "SDL_Init was called twice or more!\n");
return;
}
inited = true;
char name[256];
char name2[256];
// make folder structure for our lock files
sprintf(name, "/tmp/DFHack/%d",OS_getPID());
mode_t createmode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
mkdir("/tmp/DFHack", createmode);
mkdir(name, createmode);
// create and lock the server lock file
sprintf(name2, "%s/SVlock",name);
fd_svlock = open(name2,O_WRONLY | O_CREAT, createmode);
lockf( fd_svlock, F_LOCK, 0 );
for(int i = 0; i < SHM_MAX_CLIENTS; i++)
{
// create the client lock file
sprintf(name2, "%s/CLlock%d",name,i);
fd_cllock[i] = open(name2,O_WRONLY | O_CREAT, createmode);
// get and lock the suspend locks
sprintf(name2, "%s/CLSlock%d",name,i);
fd_clSlock[i] = open(name2,O_WRONLY | O_CREAT, createmode);
lockf(fd_clSlock[i],F_LOCK,0);
held_clSlock[i] = 1;
}
// name for the segment, an accident waiting to happen
key_t key = SHM_KEY + OS_getPID();
// find previous segment, check if it's used by some processes.
// if it isn't, kill it with fire
if ((shmid = shmget(key, SHM_SIZE, 0600)) != -1)
{
shmid_ds descriptor;
shmctl(shmid, IPC_STAT, &descriptor);
if(descriptor.shm_nattch == 0)
{
shmctl(shmid,IPC_RMID,NULL);
fprintf(stderr,"dfhack: killed dangling resources from crashed DF.\n");
}
}
// create the segment, make sure only ww are really creating it
if ((shmid = shmget(key, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0600)) < 0)
{
perror("shmget");
errorstate = 1;
return;
}
// attach the segment
if ((shm = (char *) shmat(shmid, 0, 0)) == (char *) -1)
{
perror("shmat");
errorstate = 1;
return;
}
full_barrier
// make sure we don't stall or do crazy stuff
for(int i = 0; i < SHM_MAX_CLIENTS;i++)
{
((uint32_t *)shm)[i] = CORE_RUNNING;
}
InitModules();
}
void SHM_Destroy ( void )
{
if(inited && !errorstate)
{
KillModules();
shmid_ds descriptor;
shmctl(shmid, IPC_STAT, &descriptor);
shmdt(shm);
while(descriptor.shm_nattch != 0)
{
shmctl(shmid, IPC_STAT, &descriptor);
}
shmctl(shmid,IPC_RMID,NULL);
char name[256];
char name2[256];
sprintf(name, "/tmp/DFHack/%d",OS_getPID());
// unlock and close server lock, close client lock, destroy files
lockf(fd_svlock,F_ULOCK,0);
for(int i = 0; i < SHM_MAX_CLIENTS; i++)
{
close(fd_cllock[i]);
fd_cllock[i] = 0;
close(fd_clSlock[i]);
fd_clSlock[i] = 0;
held_clSlock[i] = 0;
sprintf(name2, "%s/CLlock%d",name,i);
unlink(name2);
sprintf(name2, "%s/CLSlock%d",name,i);
unlink(name2);
}
close(fd_svlock);
fd_svlock = 0;
sprintf(name2, "%s/SVlock",name);
unlink(name2);
// remove the PID folder
rmdir(name);
fprintf(stderr,"dfhack: destroyed shared segment.\n");
inited = false;
}
}
/*******************************************************************************
* SDL part starts here *
*******************************************************************************/
// this is supported from 0.31.04 forward
DFhackCExport int SDL_NumJoysticks(void)
{
if(errorstate)
return -1;
if(!inited)
{
SHM_Init();
return -2;
}
SHM_Act();
return -3;
}
// ptr to the real functions
//static void (*_SDL_GL_SwapBuffers)(void) = 0;
static void (*_SDL_Quit)(void) = 0;
static int (*_SDL_Init)(uint32_t flags) = 0;
//static int (*_SDL_Flip)(void * some_ptr) = 0;
/*
// hook - called every tick in OpenGL mode of DF
DFhackCExport void SDL_GL_SwapBuffers(void)
{
if(_SDL_GL_SwapBuffers)
{
if(!errorstate)
{
SHM_Act();
}
counter ++;
_SDL_GL_SwapBuffers();
}
}
*/
/*
// hook - called every tick in the 2D mode of DF
DFhackCExport int SDL_Flip(void * some_ptr)
{
if(_SDL_Flip)
{
if(!errorstate)
{
SHM_Act();
}
counter ++;
return _SDL_Flip(some_ptr);
}
return 0;
}
*/
// hook - called at program exit
DFhackCExport void SDL_Quit(void)
{
if(!errorstate)
{
SHM_Destroy();
errorstate = true;
}
if(_SDL_Quit)
{
_SDL_Quit();
}
}
// hook - called at program start, initialize some stuffs we'll use later
DFhackCExport int SDL_Init(uint32_t flags)
{
// find real functions
//_SDL_GL_SwapBuffers = (void (*)( void )) dlsym(RTLD_NEXT, "SDL_GL_SwapBuffers");
_SDL_Init = (int (*)( uint32_t )) dlsym(RTLD_NEXT, "SDL_Init");
//_SDL_Flip = (int (*)( void * )) dlsym(RTLD_NEXT, "SDL_Flip");
_SDL_Quit = (void (*)( void )) dlsym(RTLD_NEXT, "SDL_Quit");
// check if we got them
if(/*_SDL_GL_SwapBuffers &&*/ _SDL_Init && _SDL_Quit)
{
fprintf(stderr,"dfhack: hooking successful\n");
}
else
{
// bail, this would be a disaster otherwise
fprintf(stderr,"dfhack: something went horribly wrong\n");
errorstate = true;
exit(1);
}
//SHM_Init();
return _SDL_Init(flags);
}
//*/
/*******************************************************************************
* NCURSES part starts here *
*******************************************************************************/
static int (*_refresh)(void) = 0;
//extern NCURSES_EXPORT(int) refresh (void);
DFhackCExport int refresh (void)
{
if(_refresh)
{
/*
if(!errorstate)
{
SHM_Act();
}
counter ++;
*/
return _refresh();
}
return 0;
}
static int (*_endwin)(void) = 0;
//extern NCURSES_EXPORT(int) endwin (void);
DFhackCExport int endwin (void)
{
if(!errorstate)
{
SHM_Destroy();
errorstate = true;
}
if(_endwin)
{
return _endwin();
}
return 0;
}
typedef void WINDOW;
//extern NCURSES_EXPORT(WINDOW *) initscr (void);
static WINDOW * (*_initscr)(void) = 0;
DFhackCExport WINDOW * initscr (void)
{
// find real functions
//_refresh = (int (*)( void )) dlsym(RTLD_NEXT, "refresh");
_endwin = (int (*)( void )) dlsym(RTLD_NEXT, "endwin");
_initscr = (WINDOW * (*)( void )) dlsym(RTLD_NEXT, "initscr");
// check if we got them
if(_refresh && _endwin && _initscr)
{
fprintf(stderr,"dfhack: hooking successful\n");
}
else
{
// bail, this would be a disaster otherwise
fprintf(stderr,"dfhack: something went horribly wrong\n");
exit(1);
}
//SHM_Init();
return _initscr();
}