Merge remote branch 'upstream/master'

develop
doomchild 2010-04-20 15:04:18 -05:00
commit 20b752f68f
57 changed files with 2141 additions and 880 deletions

@ -0,0 +1,4 @@
mkdir build-real
cd build-real
cmake ..\.. -G"Visual Studio 10"
pause

@ -56,7 +56,7 @@ bool APIPrivate::InitReadNames()
void APIPrivate::readName(t_name & name, uint32_t address)
{
g_pProcess->readSTLString(address + name_firstname_offset , name.first_name, 128);
g_pProcess->readSTLString(address + name_nickname_offset , name.nickname, 128);
g_pProcess->read(address + name_words_offset ,48, (uint8_t *) name.words);
p->readSTLString(address + name_firstname_offset , name.first_name, 128);
p->readSTLString(address + name_nickname_offset , name.nickname, 128);
p->read(address + name_words_offset ,48, (uint8_t *) name.words);
}

@ -113,6 +113,62 @@ bool API::Detach()
d->p = NULL;
d->shm_start = 0;
d->offset_descriptor = NULL;
// invalidate all modules
if(d->creatures)
{
delete d->creatures;
d->creatures = 0;
}
if(d->creatures)
{
delete d->creatures;
d->creatures = 0;
}
if(d->maps)
{
delete d->maps;
d->maps = 0;
}
if(d->gui)
{
delete d->gui;
d->gui = 0;
}
if(d->position)
{
delete d->position;
d->position = 0;
}
if(d->materials)
{
delete d->materials;
d->materials = 0;
}
if(d->gui)
{
delete d->gui;
d->gui = 0;
}
if(d->translation)
{
delete d->translation;
d->translation = 0;
}
if(d->vegetation)
{
delete d->vegetation;
d->vegetation = 0;
}
if(d->constructions)
{
delete d->constructions;
d->constructions = 0;
}
if(d->translation)
{
delete d->translation;
d->translation = 0;
}
return true;
}
@ -145,12 +201,12 @@ bool API::isSuspended()
void API::ReadRaw (const uint32_t offset, const uint32_t size, uint8_t *target)
{
g_pProcess->read (offset, size, target);
d->p->read (offset, size, target);
}
void API::WriteRaw (const uint32_t offset, const uint32_t size, uint8_t *source)
{
g_pProcess->write (offset, size, source);
d->p->write (offset, size, source);
}
memory_info *API::getMemoryInfo()
@ -250,7 +306,7 @@ bool API::InitReadEffects ( uint32_t & numeffects )
return false;
}
d->effectsInited = true;
d->p_effect = new DfVector (d->p, effects, 4);
d->p_effect = new DfVector (d->p, effects);
numeffects = d->p_effect->getSize();
return true;
}
@ -263,9 +319,9 @@ bool API::ReadEffect(const uint32_t index, t_effect_df40d & effect)
return false;
// read pointer from vector at position
uint32_t temp = * (uint32_t *) d->p_effect->at (index);
uint32_t temp = d->p_effect->at (index);
//read effect from memory
g_pProcess->read (temp, sizeof (t_effect_df40d), (uint8_t *) &effect);
d->p->read (temp, sizeof (t_effect_df40d), (uint8_t *) &effect);
return true;
}
@ -277,9 +333,9 @@ bool API::WriteEffect(const uint32_t index, const t_effect_df40d & effect)
if(index >= d->p_effect->getSize())
return false;
// read pointer from vector at position
uint32_t temp = * (uint32_t *) d->p_effect->at (index);
uint32_t temp = d->p_effect->at (index);
// write effect to memory
g_pProcess->write(temp,sizeof(t_effect_df40d), (uint8_t *) &effect);
d->p->write(temp,sizeof(t_effect_df40d), (uint8_t *) &effect);
return true;
}
@ -306,7 +362,7 @@ bool API::InitReadNotes( uint32_t &numnotes )
d->note_name_offset = minfo->getOffset ("note_name");
d->note_xyz_offset = minfo->getOffset ("note_xyz");
d->p_notes = new DfVector (d->p, notes, 4);
d->p_notes = new DfVector (d->p, notes);
d->notesInited = true;
numnotes = d->p_notes->getSize();
return true;
@ -322,12 +378,12 @@ bool API::ReadNote (const int32_t index, t_note & note)
{
if(!d->notesInited) return false;
// read pointer from vector at position
uint32_t temp = * (uint32_t *) d->p_notes->at (index);
note.symbol = g_pProcess->readByte(temp);
note.foreground = g_pProcess->readWord(temp + d->note_foreground_offset);
note.background = g_pProcess->readWord(temp + d->note_background_offset);
uint32_t temp = d->p_notes->at (index);
note.symbol = d->p->readByte(temp);
note.foreground = d->p->readWord(temp + d->note_foreground_offset);
note.background = d->p->readWord(temp + d->note_background_offset);
d->p->readSTLString (temp + d->note_name_offset, note.name, 128);
g_pProcess->read (temp + d->note_xyz_offset, 3*sizeof (uint16_t), (uint8_t *) &note.x);
d->p->read (temp + d->note_xyz_offset, 3*sizeof (uint16_t), (uint8_t *) &note.x);
return true;
}
bool API::InitReadSettlements( uint32_t & numsettlements )
@ -343,8 +399,8 @@ bool API::InitReadSettlements( uint32_t & numsettlements )
d->settlement_world_xy_offset = minfo->getOffset ("settlement_world_xy");
d->settlement_local_xy_offset = minfo->getOffset ("settlement_local_xy");
d->p_settlements = new DfVector (d->p, allSettlements, 4);
d->p_current_settlement = new DfVector(d->p, currentSettlement,4);
d->p_settlements = new DfVector (d->p, allSettlements);
d->p_current_settlement = new DfVector(d->p, currentSettlement);
d->settlementsInited = true;
numsettlements = d->p_settlements->getSize();
return true;
@ -362,11 +418,11 @@ bool API::ReadSettlement(const int32_t index, t_settlement & settlement)
if(!d->p_settlements->getSize()) return false;
// read pointer from vector at position
uint32_t temp = * (uint32_t *) d->p_settlements->at (index);
uint32_t temp = d->p_settlements->at (index);
settlement.origin = temp;
d->readName(settlement.name, temp + d->settlement_name_offset);
g_pProcess->read(temp + d->settlement_world_xy_offset, 2 * sizeof(int16_t), (uint8_t *) &settlement.world_x);
g_pProcess->read(temp + d->settlement_local_xy_offset, 4 * sizeof(int16_t), (uint8_t *) &settlement.local_x1);
d->p->read(temp + d->settlement_world_xy_offset, 2 * sizeof(int16_t), (uint8_t *) &settlement.world_x);
d->p->read(temp + d->settlement_local_xy_offset, 4 * sizeof(int16_t), (uint8_t *) &settlement.local_x1);
return true;
}
@ -375,11 +431,11 @@ bool API::ReadCurrentSettlement(t_settlement & settlement)
if(!d->settlementsInited) return false;
if(!d->p_current_settlement->getSize()) return false;
uint32_t temp = * (uint32_t *) d->p_current_settlement->at(0);
uint32_t temp = d->p_current_settlement->at(0);
settlement.origin = temp;
d->readName(settlement.name, temp + d->settlement_name_offset);
g_pProcess->read(temp + d->settlement_world_xy_offset, 2 * sizeof(int16_t), (uint8_t *) &settlement.world_x);
g_pProcess->read(temp + d->settlement_local_xy_offset, 4 * sizeof(int16_t), (uint8_t *) &settlement.local_x1);
d->p->read(temp + d->settlement_world_xy_offset, 2 * sizeof(int16_t), (uint8_t *) &settlement.world_x);
d->p->read(temp + d->settlement_local_xy_offset, 4 * sizeof(int16_t), (uint8_t *) &settlement.local_x1);
return true;
}
@ -411,8 +467,8 @@ bool API::getItemIndexesInBox(vector<uint32_t> &indexes,
};
temp2 temp2;
for(uint32_t i =0;i<size;i++){
uint32_t temp = *(uint32_t *) d->p_itm->at(i);
g_pProcess->read(temp+sizeof(uint32_t),5 * sizeof(uint16_t), (uint8_t *) &temp2);
uint32_t temp = d->p_itm->at(i);
d->p->read(temp+sizeof(uint32_t),5 * sizeof(uint16_t), (uint8_t *) &temp2);
if(temp2.flags & (1 << 0)){
if (temp2.coords[0] >= x1 && temp2.coords[0] < x2)
{
@ -449,7 +505,7 @@ bool API::InitReadItems(uint32_t & numitems)
int items = d->offset_descriptor->getAddress ("items");
d->item_material_offset = d->offset_descriptor->getOffset ("item_materials");
d->p_itm = new DfVector (d->p, items, 4);
d->p_itm = new DfVector (d->p, items);
d->itemsInited = true;
numitems = d->p_itm->getSize();
return true;
@ -468,10 +524,10 @@ bool API::ReadItem (const uint32_t index, t_item & item)
t_item_df40d item_40d;
// read pointer from vector at position
uint32_t temp = * (uint32_t *) d->p_itm->at (index);
uint32_t temp = d->p_itm->at (index);
//read building from memory
g_pProcess->read (temp, sizeof (t_item_df40d), (uint8_t *) &item_40d);
d->p->read (temp, sizeof (t_item_df40d), (uint8_t *) &item_40d);
// transform
int32_t type = -1;
@ -486,7 +542,7 @@ bool API::ReadItem (const uint32_t index, t_item & item)
item.flags.whole = item_40d.flags;
//TODO certain item types (creature based, threads, seeds, bags do not have the first matType byte, instead they have the material index only located at 0x68
g_pProcess->read (temp + d->item_material_offset, sizeof (t_matglossPair), (uint8_t *) &item.material);
d->p->read (temp + d->item_material_offset, sizeof (t_matglossPair), (uint8_t *) &item.material);
//for(int i = 0; i < 0xCC; i++){ // used for item research
// uint8_t byte = MreadByte(temp+i);
// item.bytes.push_back(byte);
@ -512,7 +568,7 @@ bool API::ReadItemTypes(vector< vector< t_itemType > > & itemTypes)
int item_type_name_offset = minfo->getOffset("item_type_name");
for(int i = 8;i<20;i++)
{
DfVector p_temp (d->p, matgloss_address + i*matgloss_skip,4);
DfVector p_temp (d->p, matgloss_address + i*matgloss_skip);
vector< t_itemType > typesForVec;
for(uint32_t j =0; j<p_temp.getSize();j++)
{

@ -58,6 +58,7 @@ class memory_info::Private
uint32_t classindex;
int32_t base;
Process * p; // the process this belongs to
string version;
OSType OS;
@ -68,6 +69,7 @@ memory_info::memory_info()
:d(new Private)
{
d->base = 0;
d->p = 0;
d->classindex = 0;
}
@ -96,6 +98,10 @@ memory_info::memory_info(const memory_info &old)
d->traits = old.d->traits;
d->labors = old.d->labors;
}
void memory_info::setParentProcess(Process * _p)
{
d->p = _p;
}
// destructor
memory_info::~memory_info()
@ -327,7 +333,7 @@ void memory_info::setClassChild (t_class * parent, const char * name, const char
// FIXME: stupid. we need a better container
bool memory_info::resolveObjectToClassID(const uint32_t address, int32_t & classid)
{
uint32_t vtable = g_pProcess->readDWord(address);
uint32_t vtable = d->p->readDWord(address);
// try to find the vtable in our cache
map<uint32_t, t_class *>::iterator it;
it = d->classIDs.find(vtable);
@ -341,7 +347,7 @@ bool memory_info::resolveObjectToClassID(const uint32_t address, int32_t & class
else// couldn't find?
{
// we set up the class for the first time
string classname = g_pProcess->readClassName(vtable);
string classname = d->p->readClassName(vtable);
d->classIDs[vtable] = cl = setClass(classname.c_str(),vtable);
}
// and isn't a multi-class
@ -356,7 +362,7 @@ bool memory_info::resolveObjectToClassID(const uint32_t address, int32_t & class
{
// find the type
vector <t_type*>& vec = cl->subs;
uint32_t type = g_pProcess->readWord(address + cl->type_offset);
uint32_t type = d->p->readWord(address + cl->type_offset);
// return typed building if successful
//FIXME: the vector should map directly to the type IDs here, so we don't have to mess with O(n) search
for (uint32_t k = 0; k < vec.size();k++)
@ -393,6 +399,22 @@ bool memory_info::resolveClassnameToVPtr(const string classname, uint32_t & vptr
return false;
}
bool memory_info::resolveClassnameToClassID (const string classname, int32_t & classID)
{
// FIXME: another stupid search.
classID = -1;
for(uint32_t i = 0;i< d->classnames.size();i++)
{
if(d->classnames[i] == classname)
{
classID = i;
return true;
}
}
// we failed to find anything that would match
return false;
}
bool memory_info::resolveClassIDToClassname (const int32_t classID, string & classname)
{
if (classID >=0 && (uint32_t)classID < d->classnames.size())

@ -46,7 +46,7 @@ using namespace DFHack;
class SHMProcess::Private
{
public:
Private()
Private(Process * self_)
{
memdescriptor = NULL;
process_ID = 0;
@ -62,10 +62,12 @@ class SHMProcess::Private
suspend_lock = -1;
attachmentIdx = 0;
locked = false;
self = self_;
};
~Private(){};
memory_info * memdescriptor;
DFWindow * window;
Process * self;
pid_t process_ID;
char *shm_addr;
int shm_ID;
@ -118,7 +120,6 @@ bool SHMProcess::Private::SetAndWait (uint32_t state)
FreeLocks();
attached = locked = identified = false;
// we aren't the current process anymore
g_pProcess = NULL;
throw Error::SHMServerDisappeared();
}
else
@ -263,9 +264,10 @@ bool SHMProcess::Private::GetLocks()
}
SHMProcess::SHMProcess(uint32_t PID, vector< memory_info* >& known_versions)
: d(new Private())
: d(new Private(this))
{
d->process_ID = PID;
d->memdescriptor = 0;
if(!attach())
{
// couldn't attach to process
@ -336,8 +338,9 @@ bool SHMProcess::Private::validate(vector <memory_info *> & known_versions)
try{
if(hash == (*it)->getString("md5")) // are the md5 hashes the same?
{
memory_info * m = *it;
memory_info *m = new memory_info(**it);
memdescriptor = m;
m->setParentProcess(dynamic_cast<Process *>( self ));
identified = true;
// cerr << "identified " << m->getVersion() << endl;
return true;
@ -357,7 +360,8 @@ SHMProcess::~SHMProcess()
{
detach();
}
// destroy data model. this is assigned by processmanager
if(d->memdescriptor)
delete d->memdescriptor;
if(d->window)
{
delete d->window;
@ -537,11 +541,11 @@ bool SHMProcess::resume()
bool SHMProcess::attach()
{
if(g_pProcess != 0)
if(d->attached)
{
// FIXME: throw exception here - programmer error
cerr << "client is already attached to a process!" << endl;
return false;
if(!d->locked)
return suspend();
return true;
}
if(!d->GetLocks())
{
@ -576,7 +580,6 @@ bool SHMProcess::attach()
cerr << "unable to suspend" << endl;
return false;
}
g_pProcess = this;
return true;
}
@ -597,7 +600,6 @@ bool SHMProcess::detach()
d->locked = false;
d->attached = false;
d->shm_addr = 0;
g_pProcess = 0;
return true;
}
// fail if we can't detach
@ -608,7 +610,7 @@ bool SHMProcess::detach()
void SHMProcess::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
// normal read under 1MB
if(size <= SHM_BODY)
@ -645,7 +647,7 @@ void SHMProcess::read (uint32_t src_address, uint32_t size, uint8_t *target_buff
uint8_t SHMProcess::readByte (const uint32_t offset)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
gcc_barrier
@ -655,7 +657,7 @@ uint8_t SHMProcess::readByte (const uint32_t offset)
void SHMProcess::readByte (const uint32_t offset, uint8_t &val )
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
gcc_barrier
@ -665,7 +667,7 @@ void SHMProcess::readByte (const uint32_t offset, uint8_t &val )
uint16_t SHMProcess::readWord (const uint32_t offset)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
gcc_barrier
@ -675,7 +677,7 @@ uint16_t SHMProcess::readWord (const uint32_t offset)
void SHMProcess::readWord (const uint32_t offset, uint16_t &val)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
gcc_barrier
@ -685,7 +687,7 @@ void SHMProcess::readWord (const uint32_t offset, uint16_t &val)
uint32_t SHMProcess::readDWord (const uint32_t offset)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
gcc_barrier
@ -694,7 +696,26 @@ uint32_t SHMProcess::readDWord (const uint32_t offset)
}
void SHMProcess::readDWord (const uint32_t offset, uint32_t &val)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
gcc_barrier
d->SetAndWait(CORE_READ_DWORD);
val = D_SHMHDR->value;
}
float SHMProcess::readFloat (const uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
gcc_barrier
d->SetAndWait(CORE_READ_DWORD);
return D_SHMHDR->value;
}
void SHMProcess::readFloat (const uint32_t offset, float &val)
{
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
gcc_barrier
@ -708,7 +729,7 @@ void SHMProcess::readDWord (const uint32_t offset, uint32_t &val)
void SHMProcess::writeDWord (uint32_t offset, uint32_t data)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
@ -719,7 +740,7 @@ void SHMProcess::writeDWord (uint32_t offset, uint32_t data)
// using these is expensive.
void SHMProcess::writeWord (uint32_t offset, uint16_t data)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
@ -729,7 +750,7 @@ void SHMProcess::writeWord (uint32_t offset, uint16_t data)
void SHMProcess::writeByte (uint32_t offset, uint8_t data)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
@ -739,7 +760,7 @@ void SHMProcess::writeByte (uint32_t offset, uint8_t data)
void SHMProcess::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
// normal write under 1MB
if(size <= SHM_BODY)
@ -777,7 +798,7 @@ void SHMProcess::write (uint32_t dst_address, uint32_t size, uint8_t *source_buf
// FIXME: butt-fugly
const std::string SHMProcess::readCString (uint32_t offset)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
std::string temp;
char temp_c[256];
@ -796,7 +817,7 @@ const std::string SHMProcess::readCString (uint32_t offset)
const std::string SHMProcess::readSTLString(uint32_t offset)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
full_barrier
@ -806,7 +827,7 @@ const std::string SHMProcess::readSTLString(uint32_t offset)
size_t SHMProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
full_barrier
@ -820,7 +841,7 @@ size_t SHMProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapa
void SHMProcess::writeSTLString(const uint32_t address, const std::string writeString)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = address;
strncpy(D_SHMDATA(char),writeString.c_str(),writeString.length()+1); // length + 1 for the null terminator
@ -830,7 +851,7 @@ void SHMProcess::writeSTLString(const uint32_t address, const std::string writeS
string SHMProcess::readClassName (uint32_t vptr)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
int typeinfo = readDWord(vptr - 0x4);
int typestring = readDWord(typeinfo + 0x4);
@ -843,7 +864,7 @@ string SHMProcess::readClassName (uint32_t vptr)
// 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::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
modulelookup * payload = D_SHMDATA(modulelookup);
payload->version = version;
@ -873,7 +894,7 @@ char * SHMProcess::getSHMStart (void)
bool SHMProcess::Private::Aux_Core_Attach(bool & versionOK, pid_t & PID)
{
if(!locked) throw Error::SHMAccessDenied();
if(!locked) throw Error::MemoryAccessDenied();
SHMDATA(coreattach)->cl_affinity = OS_getAffinity();
if(!SetAndWait(CORE_ATTACH)) return false;
@ -888,4 +909,4 @@ bool SHMProcess::Private::Aux_Core_Attach(bool & versionOK, pid_t & PID)
if(useYield) cerr << "Using Yield!" << endl;
#endif
return true;
}
}

@ -34,7 +34,7 @@ using namespace DFHack;
class WineProcess::Private
{
public:
Private()
Private(Process * self_)
{
my_descriptor = NULL;
my_handle = NULL;
@ -43,10 +43,12 @@ class WineProcess::Private
attached = false;
suspended = false;
memFileHandle = 0;
self = self_;
};
~Private(){};
DFWindow* my_window;
memory_info * my_descriptor;
Process * self;
ProcessHandle my_handle;
uint32_t my_pid;
string memFile;
@ -58,7 +60,7 @@ class WineProcess::Private
};
WineProcess::WineProcess(uint32_t pid, vector <memory_info *> & known_versions)
: d(new Private())
: d(new Private(this))
{
char dir_name [256];
char exe_link_name [256];
@ -69,6 +71,7 @@ WineProcess::WineProcess(uint32_t pid, vector <memory_info *> & known_versions)
int target_result;
d->identified = false;
d->my_descriptor = 0;
sprintf(dir_name,"/proc/%d/", pid);
sprintf(exe_link_name,"/proc/%d/exe", pid);
@ -147,8 +150,11 @@ bool WineProcess::Private::validate(char* exe_file, uint32_t pid, char* mem_file
// are the md5 hashes the same?
if(memory_info::OS_WINDOWS == (*it)->getOS() && hash == thishash)
{
memory_info * m = *it;
// keep track of created memory_info object so we can destroy it later
memory_info *m = new memory_info(**it);
my_descriptor = m;
m->setParentProcess(dynamic_cast<Process *>( self ));
my_handle = my_pid = pid;
// tell WineProcess about the /proc/PID/mem file
memFile = mem_file;
@ -165,6 +171,9 @@ WineProcess::~WineProcess()
{
detach();
}
// destroy our copy of the memory descriptor
if(d->my_descriptor)
delete d->my_descriptor;
if(d->my_window)
delete d->my_window;
delete d;
@ -281,9 +290,11 @@ bool WineProcess::resume()
bool WineProcess::attach()
{
int status;
if(g_pProcess != NULL)
if(d->attached)
{
return false;
if(!d->suspended)
return suspend();
return true;
}
// can we attach?
if (ptrace(PTRACE_ATTACH , d->my_handle, NULL, NULL) == -1)
@ -323,7 +334,6 @@ bool WineProcess::attach()
else
{
d->attached = true;
g_pProcess = this;
d->memFileHandle = proc_pid_mem;
return true; // we are attached
@ -356,7 +366,6 @@ bool WineProcess::detach()
else
{
d->attached = false;
g_pProcess = NULL;
return true;
}
}
@ -377,6 +386,7 @@ void WineProcess::read (const uint32_t offset, const uint32_t size, uint8_t *tar
cerr << "pread failed: can't read " << size << " bytes at addres " << offset << endl;
cerr << "errno: " << errno << endl;
errno = 0;
throw Error::MemoryAccessDenied();
}
else
{
@ -420,6 +430,17 @@ void WineProcess::readDWord (const uint32_t offset, uint32_t &val)
read(offset, 4, (uint8_t *) &val);
}
float WineProcess::readFloat (const uint32_t offset)
{
float val;
read(offset, 4, (uint8_t *) &val);
return val;
}
void WineProcess::readFloat (const uint32_t offset, float &val)
{
read(offset, 4, (uint8_t *) &val);
}
/*
* WRITING
*/
@ -516,20 +537,20 @@ size_t WineProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcap
Uint32 capacity
*/
uint32_t start_offset = offset + 4;
size_t length = g_pProcess->readDWord(offset + 20);
size_t length = readDWord(offset + 20);
size_t capacity = g_pProcess->readDWord(offset + 24);
size_t capacity = readDWord(offset + 24);
size_t read_real = min(length, bufcapacity-1);// keep space for null termination
// read data from inside the string structure
if(capacity < 16)
{
g_pProcess->read(start_offset, read_real , (uint8_t *)buffer);
read(start_offset, read_real , (uint8_t *)buffer);
}
else // read data from what the offset + 4 dword points to
{
start_offset = g_pProcess->readDWord(start_offset);// dereference the start offset
g_pProcess->read(start_offset, read_real, (uint8_t *)buffer);
start_offset = readDWord(start_offset);// dereference the start offset
read(start_offset, read_real, (uint8_t *)buffer);
}
buffer[read_real] = 0;
@ -550,19 +571,19 @@ const string WineProcess::readSTLString (uint32_t offset)
Uint32 capacity
*/
uint32_t start_offset = offset + 4;
uint32_t length = g_pProcess->readDWord(offset + 20);
uint32_t capacity = g_pProcess->readDWord(offset + 24);
uint32_t length = readDWord(offset + 20);
uint32_t capacity = readDWord(offset + 24);
char * temp = new char[capacity+1];
// read data from inside the string structure
if(capacity < 16)
{
g_pProcess->read(start_offset, capacity, (uint8_t *)temp);
read(start_offset, capacity, (uint8_t *)temp);
}
else // read data from what the offset + 4 dword points to
{
start_offset = g_pProcess->readDWord(start_offset);// dereference the start offset
g_pProcess->read(start_offset, capacity, (uint8_t *)temp);
start_offset = readDWord(start_offset);// dereference the start offset
read(start_offset, capacity, (uint8_t *)temp);
}
temp[length] = 0;
@ -578,4 +599,4 @@ string WineProcess::readClassName (uint32_t vptr)
string raw = readCString(typeinfo + 0xC); // skips the .?AV
raw.resize(raw.length() - 2);// trim @@ from end
return raw;
}
}

@ -33,7 +33,7 @@ using namespace DFHack;
class NormalProcess::Private
{
public:
Private()
Private(Process * self_)
{
my_descriptor = NULL;
my_handle = NULL;
@ -42,6 +42,7 @@ class NormalProcess::Private
attached = false;
suspended = false;
memFileHandle = 0;
self = self_;
};
~Private(){};
DFWindow* my_window;
@ -53,11 +54,12 @@ class NormalProcess::Private
bool attached;
bool suspended;
bool identified;
Process * self;
bool validate(char * exe_file, uint32_t pid, char * mem_file, vector <memory_info *> & known_versions);
};
NormalProcess::NormalProcess(uint32_t pid, vector< memory_info* >& known_versions)
: d(new Private())
: d(new Private(this))
{
char dir_name [256];
char exe_link_name [256];
@ -68,6 +70,7 @@ NormalProcess::NormalProcess(uint32_t pid, vector< memory_info* >& known_version
int target_result;
d->identified = false;
d->my_descriptor = 0;
sprintf(dir_name,"/proc/%d/", pid);
sprintf(exe_link_name,"/proc/%d/exe", pid);
@ -125,7 +128,9 @@ bool NormalProcess::Private::validate(char * exe_file,uint32_t pid, char * memFi
memory_info * m = *it;
if (memory_info::OS_LINUX == m->getOS())
{
my_descriptor = m;
memory_info *m2 = new memory_info(*m);
my_descriptor = m2;
m2->setParentProcess(dynamic_cast<Process *>( self ));
my_handle = my_pid = pid;
}
else
@ -153,6 +158,9 @@ NormalProcess::~NormalProcess()
{
detach();
}
// destroy our copy of the memory descriptor
if(d->my_descriptor)
delete d->my_descriptor;
// destroy data model. this is assigned by processmanager
if(d->my_window)
delete d->my_window;
@ -270,9 +278,11 @@ bool NormalProcess::resume()
bool NormalProcess::attach()
{
int status;
if(g_pProcess != NULL)
if(d->attached)
{
return false;
if(!d->suspended)
return suspend();
return true;
}
// can we attach?
if (ptrace(PTRACE_ATTACH , d->my_handle, NULL, NULL) == -1)
@ -311,7 +321,6 @@ bool NormalProcess::attach()
else
{
d->attached = true;
g_pProcess = this;
d->memFileHandle = proc_pid_mem;
return true; // we are attached
@ -344,7 +353,6 @@ bool NormalProcess::detach()
else
{
d->attached = false;
g_pProcess = NULL;
return true;
}
}
@ -365,6 +373,7 @@ void NormalProcess::read (const uint32_t offset, const uint32_t size, uint8_t *t
cerr << "pread failed: can't read " << size << " bytes at addres " << offset << endl;
cerr << "errno: " << errno << endl;
errno = 0;
throw Error::MemoryAccessDenied();
}
else
{
@ -408,6 +417,17 @@ void NormalProcess::readDWord (const uint32_t offset, uint32_t &val)
read(offset, 4, (uint8_t *) &val);
}
float NormalProcess::readFloat (const uint32_t offset)
{
float val;
read(offset, 4, (uint8_t *) &val);
return val;
}
void NormalProcess::readFloat (const uint32_t offset, float &val)
{
read(offset, 4, (uint8_t *) &val);
}
/*
* WRITING
*/
@ -500,10 +520,10 @@ struct _Rep_base
size_t NormalProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
_Rep_base header;
offset = g_pProcess->readDWord(offset);
g_pProcess->read(offset - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header);
offset = 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
g_pProcess->read(offset,read_real,(uint8_t * )buffer);
read(offset,read_real,(uint8_t * )buffer);
buffer[read_real] = 0;
return read_real;
}
@ -512,12 +532,12 @@ const string NormalProcess::readSTLString (uint32_t offset)
{
_Rep_base header;
offset = g_pProcess->readDWord(offset);
g_pProcess->read(offset - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header);
offset = readDWord(offset);
read(offset - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header);
// FIXME: use char* everywhere, avoid string
char * temp = new char[header._M_length+1];
g_pProcess->read(offset,header._M_length+1,(uint8_t * )temp);
read(offset,header._M_length+1,(uint8_t * )temp);
string ret(temp);
delete temp;
return ret;
@ -531,4 +551,4 @@ string NormalProcess::readClassName (uint32_t vptr)
size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers
size_t end = raw.length();
return raw.substr(start,end-start);
}
}

@ -52,7 +52,7 @@ class SHMProcess::Private
~Private(){};
memory_info * memdescriptor;
DFWindow * window;
SHMProcess * q;
SHMProcess * self;
uint32_t process_ID;
char *shm_addr;
HANDLE DFSVMutex;
@ -110,7 +110,6 @@ bool SHMProcess::Private::SetAndWait (uint32_t state)
FreeLocks();
attached = locked = identified = false;
// we aren't the current process anymore
g_pProcess = NULL;
throw Error::SHMServerDisappeared();
}
else
@ -282,7 +281,7 @@ SHMProcess::SHMProcess(uint32_t PID, vector <memory_info *> & known_versions)
: d(new Private())
{
d->process_ID = PID;
d->q = this;
d->self = this;
// attach the SHM
if(!attach())
{
@ -345,9 +344,9 @@ bool SHMProcess::Private::validate(vector <memory_info *> & known_versions)
uint32_t base = (uint32_t)hmod;
// read from this process
uint32_t pe_offset = q->readDWord(base+0x3C);
q->read(base + pe_offset , sizeof(pe_header), (uint8_t *)&pe_header);
q->read(base + pe_offset+ sizeof(pe_header), sizeof(sections) , (uint8_t *)&sections );
uint32_t pe_offset = self->readDWord(base+0x3C);
self->read(base + pe_offset , sizeof(pe_header), (uint8_t *)&pe_header);
self->read(base + pe_offset+ sizeof(pe_header), sizeof(sections) , (uint8_t *)&sections );
// iterate over the list of memory locations
vector<memory_info *>::iterator it;
@ -367,6 +366,7 @@ bool SHMProcess::Private::validate(vector <memory_info *> & known_versions)
memory_info *m = new memory_info(**it);
m->RebaseAll(base);
memdescriptor = m;
m->setParentProcess(self);
identified = true;
cerr << "identified " << m->getVersion() << endl;
CloseHandle(hProcess);
@ -577,10 +577,11 @@ bool SHMProcess::resume()
bool SHMProcess::attach()
{
if(g_pProcess != 0)
if(d->attached)
{
cerr << "there's already a process attached" << endl;
return false;
if(!d->locked)
return suspend();
return true;
}
//cerr << "attach" << endl;// FIXME: throw
if(!d->GetLocks())
@ -639,7 +640,6 @@ bool SHMProcess::attach()
//cerr << "unable to suspend" << endl;// FIXME: throw
return false;
}
g_pProcess = this;
return true;
}
@ -663,13 +663,12 @@ bool SHMProcess::detach()
d->attached = false;
d->locked = false;
d->shm_addr = false;
g_pProcess = 0;
return true;
}
void SHMProcess::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
// normal read under 1MB
if(size <= SHM_BODY)
@ -706,7 +705,7 @@ void SHMProcess::read (uint32_t src_address, uint32_t size, uint8_t *target_buff
uint8_t SHMProcess::readByte (const uint32_t offset)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
full_barrier
@ -716,7 +715,7 @@ uint8_t SHMProcess::readByte (const uint32_t offset)
void SHMProcess::readByte (const uint32_t offset, uint8_t &val )
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
full_barrier
@ -726,7 +725,7 @@ void SHMProcess::readByte (const uint32_t offset, uint8_t &val )
uint16_t SHMProcess::readWord (const uint32_t offset)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
full_barrier
@ -736,7 +735,7 @@ uint16_t SHMProcess::readWord (const uint32_t offset)
void SHMProcess::readWord (const uint32_t offset, uint16_t &val)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
full_barrier
@ -746,7 +745,7 @@ void SHMProcess::readWord (const uint32_t offset, uint16_t &val)
uint32_t SHMProcess::readDWord (const uint32_t offset)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
full_barrier
@ -755,7 +754,26 @@ uint32_t SHMProcess::readDWord (const uint32_t offset)
}
void SHMProcess::readDWord (const uint32_t offset, uint32_t &val)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_DWORD);
val = D_SHMHDR->value;
}
float SHMProcess::readFloat (const uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_DWORD);
return D_SHMHDR->value;
}
void SHMProcess::readFloat (const uint32_t offset, float &val)
{
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
full_barrier
@ -763,13 +781,14 @@ void SHMProcess::readDWord (const uint32_t offset, uint32_t &val)
val = D_SHMHDR->value;
}
/*
* WRITING
*/
void SHMProcess::writeDWord (uint32_t offset, uint32_t data)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
@ -780,7 +799,7 @@ void SHMProcess::writeDWord (uint32_t offset, uint32_t data)
// using these is expensive.
void SHMProcess::writeWord (uint32_t offset, uint16_t data)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
@ -790,7 +809,7 @@ void SHMProcess::writeWord (uint32_t offset, uint16_t data)
void SHMProcess::writeByte (uint32_t offset, uint8_t data)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
@ -800,7 +819,7 @@ void SHMProcess::writeByte (uint32_t offset, uint8_t data)
void SHMProcess::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
// normal write under 1MB
if(size <= SHM_BODY)
@ -838,7 +857,7 @@ void SHMProcess::write (uint32_t dst_address, uint32_t size, uint8_t *source_buf
// FIXME: butt-fugly
const std::string SHMProcess::readCString (uint32_t offset)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
std::string temp;
char temp_c[256];
@ -857,7 +876,7 @@ const std::string SHMProcess::readCString (uint32_t offset)
const std::string SHMProcess::readSTLString(uint32_t offset)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
full_barrier
@ -867,7 +886,7 @@ const std::string SHMProcess::readSTLString(uint32_t offset)
size_t SHMProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
full_barrier
@ -881,7 +900,7 @@ size_t SHMProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapa
void SHMProcess::writeSTLString(const uint32_t address, const std::string writeString)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = address;
strncpy(D_SHMDATA(char),writeString.c_str(),writeString.length()+1); // length + 1 for the null terminator
@ -901,7 +920,7 @@ string SHMProcess::readClassName (uint32_t vptr)
// 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::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
modulelookup * payload = D_SHMDATA(modulelookup);
payload->version = version;
@ -924,13 +943,13 @@ bool SHMProcess::getModuleIndex (const char * name, const uint32_t version, uint
char * SHMProcess::getSHMStart (void)
{
if(!d->locked) throw Error::SHMAccessDenied();
if(!d->locked) throw Error::MemoryAccessDenied();
return /*d->shm_addr_with_cl_idx*/ d->shm_addr;
}
bool SHMProcess::Private::Aux_Core_Attach(bool & versionOK, uint32_t & PID)
{
if(!locked) throw Error::SHMAccessDenied();
if(!locked) throw Error::MemoryAccessDenied();
SHMDATA(coreattach)->cl_affinity = OS_getAffinity();
if(!SetAndWait(CORE_ATTACH)) return false;
@ -945,4 +964,4 @@ bool SHMProcess::Private::Aux_Core_Attach(bool & versionOK, uint32_t & PID)
if(useYield) cerr << "Using Yield!" << endl;
#endif
return true;
}
}

@ -82,11 +82,21 @@ NormalProcess::NormalProcess(uint32_t pid, vector <memory_info *> & known_versio
// temporarily assign this to allow some checks
d->my_handle = hProcess;
d->my_main_thread = 0;
// read from this process
uint32_t pe_offset = readDWord(base+0x3C);
read(base + pe_offset , sizeof(pe_header), (uint8_t *)&pe_header);
read(base + pe_offset+ sizeof(pe_header), sizeof(sections) , (uint8_t *)&sections );
d->my_handle = 0;
try
{
uint32_t pe_offset = readDWord(base+0x3C);
read(base + pe_offset , sizeof(pe_header), (uint8_t *)&pe_header);
read(base + pe_offset+ sizeof(pe_header), sizeof(sections) , (uint8_t *)&sections );
d->my_handle = 0;
}
catch (exception &)
{
CloseHandle(hProcess);
d->my_handle = 0;
return;
}
// see if there's a version entry that matches this process
vector<memory_info*>::iterator it;
@ -117,6 +127,7 @@ NormalProcess::NormalProcess(uint32_t pid, vector <memory_info *> & known_versio
m->RebaseAll(base);
// keep track of created memory_info object so we can destroy it later
d->my_descriptor = m;
m->setParentProcess(this);
// process is responsible for destroying its data model
d->my_pid = pid;
d->my_handle = hProcess;
@ -239,12 +250,13 @@ bool NormalProcess::resume()
bool NormalProcess::attach()
{
if(g_pProcess != NULL)
if(d->attached)
{
return false;
if(!d->suspended)
return suspend();
return true;
}
d->attached = true;
g_pProcess = this;
suspend();
return true;
@ -259,7 +271,6 @@ bool NormalProcess::detach()
}
resume();
d->attached = false;
g_pProcess = NULL;
return true;
}
@ -315,64 +326,89 @@ void NormalProcess::getMemRanges( vector<t_memrange> & ranges )
uint8_t NormalProcess::readByte (const uint32_t offset)
{
uint8_t result;
ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint8_t), NULL);
if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint8_t), NULL))
throw Error::MemoryAccessDenied();
return result;
}
void NormalProcess::readByte (const uint32_t offset,uint8_t &result)
{
ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint8_t), NULL);
if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint8_t), NULL))
throw Error::MemoryAccessDenied();
}
uint16_t NormalProcess::readWord (const uint32_t offset)
{
uint16_t result;
ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint16_t), NULL);
if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint16_t), NULL))
throw Error::MemoryAccessDenied();
return result;
}
void NormalProcess::readWord (const uint32_t offset, uint16_t &result)
{
ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint16_t), NULL);
if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint16_t), NULL))
throw Error::MemoryAccessDenied();
}
uint32_t NormalProcess::readDWord (const uint32_t offset)
{
uint32_t result;
ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint32_t), NULL);
if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint32_t), NULL))
throw Error::MemoryAccessDenied();
return result;
}
void NormalProcess::readDWord (const uint32_t offset, uint32_t &result)
{
ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint32_t), NULL);
if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint32_t), NULL))
throw Error::MemoryAccessDenied();
}
float NormalProcess::readFloat (const uint32_t offset)
{
float result;
if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(float), NULL))
throw Error::MemoryAccessDenied();
return result;
}
void NormalProcess::readFloat (const uint32_t offset, float &result)
{
if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(float), NULL))
throw Error::MemoryAccessDenied();
}
void NormalProcess::read (const uint32_t offset, uint32_t size, uint8_t *target)
{
ReadProcessMemory(d->my_handle, (int*) offset, target, size, NULL);
if(!ReadProcessMemory(d->my_handle, (int*) offset, target, size, NULL))
throw Error::MemoryAccessDenied();
}
// WRITING
void NormalProcess::writeDWord (const uint32_t offset, uint32_t data)
{
WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint32_t), NULL);
if(!WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint32_t), NULL))
throw Error::MemoryAccessDenied();
}
// using these is expensive.
void NormalProcess::writeWord (uint32_t offset, uint16_t data)
{
WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint16_t), NULL);
if(!WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint16_t), NULL))
throw Error::MemoryAccessDenied();
}
void NormalProcess::writeByte (uint32_t offset, uint8_t data)
{
WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint8_t), NULL);
if(!WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint8_t), NULL))
throw Error::MemoryAccessDenied();
}
void NormalProcess::write (uint32_t offset, uint32_t size, uint8_t *source)
{
WriteProcessMemory(d->my_handle, (int*) offset, source, size, NULL);
if(!WriteProcessMemory(d->my_handle, (int*) offset, source, size, NULL))
throw Error::MemoryAccessDenied();
}
@ -383,7 +419,9 @@ const string NormalProcess::readCString (const uint32_t offset)
string temp;
char temp_c[256];
DWORD read;
ReadProcessMemory(d->my_handle, (int *) offset, temp_c, 254, &read); // needs to be 254+1 byte for the null term
if(!ReadProcessMemory(d->my_handle, (int *) offset, temp_c, 254, &read))
throw Error::MemoryAccessDenied();
// needs to be 254+1 byte for the null term
temp_c[read+1] = 0;
temp.assign(temp_c);
return temp;
@ -403,20 +441,20 @@ Uint32 length
Uint32 capacity
*/
uint32_t start_offset = offset + 4;
size_t length = g_pProcess->readDWord(offset + 20);
size_t length = readDWord(offset + 20);
size_t capacity = g_pProcess->readDWord(offset + 24);
size_t capacity = readDWord(offset + 24);
size_t read_real = min(length, bufcapacity-1);// keep space for null termination
// read data from inside the string structure
if(capacity < 16)
{
g_pProcess->read(start_offset, read_real , (uint8_t *)buffer);
read(start_offset, read_real , (uint8_t *)buffer);
}
else // read data from what the offset + 4 dword points to
{
start_offset = g_pProcess->readDWord(start_offset);// dereference the start offset
g_pProcess->read(start_offset, read_real, (uint8_t *)buffer);
start_offset = readDWord(start_offset);// dereference the start offset
read(start_offset, read_real, (uint8_t *)buffer);
}
buffer[read_real] = 0;
@ -437,19 +475,19 @@ const string NormalProcess::readSTLString (uint32_t offset)
Uint32 capacity
*/
uint32_t start_offset = offset + 4;
uint32_t length = g_pProcess->readDWord(offset + 20);
uint32_t capacity = g_pProcess->readDWord(offset + 24);
uint32_t length = readDWord(offset + 20);
uint32_t capacity = readDWord(offset + 24);
char * temp = new char[capacity+1];
// read data from inside the string structure
if(capacity < 16)
{
g_pProcess->read(start_offset, capacity, (uint8_t *)temp);
read(start_offset, capacity, (uint8_t *)temp);
}
else // read data from what the offset + 4 dword points to
{
start_offset = g_pProcess->readDWord(start_offset);// dereference the start offset
g_pProcess->read(start_offset, capacity, (uint8_t *)temp);
start_offset = readDWord(start_offset);// dereference the start offset
read(start_offset, capacity, (uint8_t *)temp);
}
temp[length] = 0;
@ -465,4 +503,4 @@ string NormalProcess::readClassName (uint32_t vptr)
string raw = readCString(typeinfo + 0xC); // skips the .?AV
raw.resize(raw.length() - 2);// trim @@ from end
return raw;
}
}

@ -35,9 +35,6 @@ distribution.
using namespace DFHack;
/// HACK: global variables (only one process can be attached at the same time.)
Process * DFHack::g_pProcess; ///< current process. non-NULL when picked
class DFHack::ProcessEnumerator::Private
{
public:

@ -29,9 +29,6 @@ distribution.
#include "DFMemInfoManager.h"
using namespace DFHack;
/// HACK: global variables (only one process can be attached at the same time.)
Process * DFHack::g_pProcess; ///< current process. non-NULL when picked
class DFHack::ProcessEnumerator::Private
{
public:

@ -24,34 +24,8 @@ distribution.
#include "Tranquility.h"
#include "DFCommonInternal.h"
#include "DFVector.h"
#include "DFMemInfo.h"
#include "DFProcess.h"
#include "DFVector.h"
using namespace DFHack;
DfVector::DfVector(Process * p, uint32_t address, uint32_t _item_size)
{
uint32_t triplet[3];
item_size = _item_size;
memory_info * mem = p->getDescriptor();
uint32_t offs = mem->getOffset("vector_triplet");
p->read(address + offs, sizeof(triplet), (uint8_t *) &triplet);
start = triplet[0];
uint32_t byte_size = triplet[1] - triplet[0];
size = byte_size / item_size;
data = (uint8_t *) new char[byte_size];
g_pProcess->read(start,byte_size, (uint8_t *)data);
};
DfVector::DfVector()
{
data = 0;
};
DfVector::~DfVector()
{
if(data)
delete [] data;
};

@ -25,6 +25,10 @@ distribution.
#ifndef DFCOMMONINTERNAL_H_INCLUDED
#define DFCOMMONINTERNAL_H_INCLUDED
// this makes everything that includes this file export symbols whn using DFHACK_EXPORT (see Export.h)
#define BUILD_DFHACK_LIB
#include "DFGlobal.h"
#include "Tranquility.h"
#include <string>
@ -65,14 +69,6 @@ typedef pid_t ProcessHandle;
typedef HANDLE ProcessHandle;
#endif
namespace DFHack
{
class Process;
/*
* Currently attached process and its handle
*/
extern Process * g_pProcess; ///< current process. non-NULL when picked
}
#ifndef BUILD_DFHACK_LIB
# define BUILD_DFHACK_LIB
#endif

@ -236,11 +236,11 @@ namespace DFHack
return s.str().c_str();
}
};
class DFHACK_EXPORT SHMAccessDenied : public std::exception
class DFHACK_EXPORT MemoryAccessDenied : public std::exception
{
public:
SHMAccessDenied() {}
virtual ~SHMAccessDenied() throw(){};
MemoryAccessDenied() {}
virtual ~MemoryAccessDenied() throw(){};
std::string type;

@ -0,0 +1,11 @@
#ifndef DFHACK_GLOBAL
#define DFHACK_GLOBAL
#include "Export.h"
// globals, if any, should be placed here.
namespace DFHack
{
// extern DFHACK_EXPORT TYPE NAME;
}
#endif

@ -34,6 +34,12 @@ distribution.
namespace DFHack
{
/*
* Stubs
*/
class Process;
/*
* Common data types
*/
@ -148,6 +154,7 @@ namespace DFHack
void setLabor(const string &, const string &);
void RebaseVTable(const int32_t offset);
void setParentProcess(Process * _p);
t_class * setClass (const char * classname, uint32_t vptr = 0, uint32_t typeoffset = 0);
void setClassChild (t_class * parent, const char * classname, const char * type);
@ -160,18 +167,15 @@ namespace DFHack
bool resolveObjectToClassID (const uint32_t address, int32_t & classID);
/*
* Get a classID from an address. The address has to point to the start of a virtual object (one with a virtual base class)
* can fail if the class is not in the cache
* Get a ClassID when you know the classname. can fail if the class is not in the cache
*/
bool resolveClassnameToClassID (const string classname, int32_t & classID);
//bool resolveClassnameToClassID (const char * classname, int32_t & classID);
/*
* Get a vptr from a classname. Can fail if the type is not in the cache
* limited to normal classes, variable-dependent types will resolve to the base class
*/
bool resolveClassnameToVPtr ( const string classname, uint32_t & vptr );
//bool resolveClassnameToVPtr ( const char * classname, uint32_t & vptr );
/*
* Get a classname from a previous classID. Can fail if the type is not in the cache (you use bogus classID)

@ -34,7 +34,6 @@ namespace DFHack
class memory_info;
class Process;
class DFWindow;
class DfVector;
// structure describing a memory range
struct DFHACK_EXPORT t_memrange
@ -82,7 +81,9 @@ namespace DFHack
virtual bool forceresume() = 0;
virtual uint32_t readDWord(const uint32_t address) = 0;
virtual float readFloat(const uint32_t address) = 0;
virtual void readDWord(const uint32_t address, uint32_t & value) = 0;
virtual void readFloat(const uint32_t address, float & value) = 0;
virtual uint16_t readWord(const uint32_t address) = 0;
virtual void readWord(const uint32_t address, uint16_t & value) = 0;
virtual uint8_t readByte(const uint32_t address) = 0;
@ -151,7 +152,9 @@ namespace DFHack
bool forceresume();
uint32_t readDWord(const uint32_t address);
float readFloat(const uint32_t address);
void readDWord(const uint32_t address, uint32_t & value);
void readFloat(const uint32_t address, float & value);
uint16_t readWord(const uint32_t address);
void readWord(const uint32_t address, uint16_t & value);
uint8_t readByte(const uint32_t address);
@ -214,7 +217,9 @@ namespace DFHack
bool forceresume();
uint32_t readDWord(const uint32_t address);
float readFloat(const uint32_t address);
void readDWord(const uint32_t address, uint32_t & value);
void readFloat(const uint32_t address, float & value);
uint16_t readWord(const uint32_t address);
void readWord(const uint32_t address, uint16_t & value);
uint8_t readByte(const uint32_t address);
@ -276,7 +281,9 @@ namespace DFHack
bool forceresume();
uint32_t readDWord(const uint32_t address);
float readFloat(const uint32_t address);
void readDWord(const uint32_t address, uint32_t & value);
void readFloat(const uint32_t address, float & value);
uint16_t readWord(const uint32_t address);
void readWord(const uint32_t address, uint16_t & value);
uint8_t readByte(const uint32_t address);

@ -417,75 +417,75 @@ namespace DFHack
{0 ,EMPTY, AIR, VAR_1},
{"glowing floor" ,FLOOR, CYAN_GLOW, VAR_1},
{0 ,EMPTY, AIR, VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall RD2",WALL,OBSIDIAN,VAR_1},
// 270
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall R2D",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall R2U",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall RU2",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall L2U",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall LU2",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall L2D",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall LD2",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall LRUD",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall RUD",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall LRD",WALL,OBSIDIAN,VAR_1},
// 280
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall",WALL,OBSIDIAN,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth obsidian wall LRU",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall LUD",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall RD",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall RU",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall LU",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall LD",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall UD",WALL,OBSIDIAN,VAR_1},
{"smooth obsidian wall LR",WALL,OBSIDIAN,VAR_1},
{"smooth featstone wall RD2",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall R2D",WALL,FEATSTONE,VAR_1},
// 290
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall R2U",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall RU2",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall L2U",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall LU2",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall L2D",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall LD2",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall LRUD",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall RUD",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall LRD",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall LRU",WALL,FEATSTONE,VAR_1},
//300
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth featstone? wall",WALL,FEATSTONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth featstone wall LUD",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall RD",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall RU",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall LU",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall LD",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall UD",WALL,FEATSTONE,VAR_1},
{"smooth featstone wall LR",WALL,FEATSTONE,VAR_1},
{"smooth stone wall RD2",WALL,STONE,VAR_1},
{"smooth stone wall R2D",WALL,STONE,VAR_1},
{"smooth stone wall R2U",WALL,STONE,VAR_1},
//310
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall RU2",WALL,STONE,VAR_1},
{"smooth stone wall L2U",WALL,STONE,VAR_1},
{"smooth stone wall LU2",WALL,STONE,VAR_1},
{"smooth stone wall L2D",WALL,STONE,VAR_1},
{"smooth stone wall LD2",WALL,STONE,VAR_1},
{"smooth stone wall LRUD",WALL,STONE,VAR_1},
{"smooth stone wall RUD",WALL,STONE,VAR_1},
{"smooth stone wall LRD",WALL,STONE,VAR_1},
{"smooth stone wall LRU",WALL,STONE,VAR_1},
{"smooth stone wall LUD",WALL,STONE,VAR_1},
//320
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall",WALL,STONE,VAR_1},
{"smooth stone wall RD",WALL,STONE,VAR_1},
{"smooth stone wall RU",WALL,STONE,VAR_1},
{"smooth stone wall LU",WALL,STONE,VAR_1},
{"smooth stone wall LD",WALL,STONE,VAR_1},
{"smooth stone wall UD",WALL,STONE,VAR_1},
{"smooth stone wall LR",WALL,STONE,VAR_1},
{"obsidian fortification",FORTIFICATION,OBSIDIAN,VAR_1},
{"featstone? fortification",FORTIFICATION,FEATSTONE,VAR_1},
{"cracked obsidian wall",WALL,OBSIDIAN,VAR_1},
@ -494,10 +494,14 @@ namespace DFHack
// 330
{"worn obsidian wall",WALL,OBSIDIAN,VAR_1},
{"obsidian wall",WALL,OBSIDIAN,VAR_1},
{"cracked stone wall",WALL,STONE,VAR_1},
{"damaged stone wall",WALL,STONE,VAR_1},
{"worn stone wall",WALL,STONE,VAR_1},
{"stone wall",WALL,STONE,VAR_1},
/*MAPTILE_FEATSTONE_WALL_WORN1,
MAPTILE_FEATSTONE_WALL_WORN2,
MAPTILE_FEATSTONE_WALL_WORN3,
MAPTILE_FEATSTONE_WALL,*/
{"cracked featstone wall",WALL,STONE,VAR_1},
{"damaged featstone wall",WALL,STONE,VAR_1},
{"worn featstone wall",WALL,STONE,VAR_1},
{"featstone wall",WALL,STONE,VAR_1},
{"stone floor",FLOOR,STONE,VAR_1},
{"stone floor",FLOOR,STONE,VAR_2},
{"stone floor",FLOOR,STONE,VAR_3},
@ -508,16 +512,16 @@ namespace DFHack
{"obsidian floor",FLOOR,OBSIDIAN,VAR_2},
{"obsidian floor",FLOOR,OBSIDIAN,VAR_3},
{"obsidian floor",FLOOR,OBSIDIAN,VAR_4},
{"featstone? floor",FLOOR,FEATSTONE,VAR_1},
{"featstone? floor",FLOOR,FEATSTONE,VAR_2},
{"featstone? floor",FLOOR,FEATSTONE,VAR_3},
{"featstone? floor",FLOOR,FEATSTONE,VAR_4},
{"grass",FLOOR,GRASS,VAR_1},
{"grass",FLOOR,GRASS,VAR_2},
{"featstone floor 1",FLOOR,FEATSTONE,VAR_1},
{"featstone floor 2",FLOOR,FEATSTONE,VAR_2},
{"featstone floor 3",FLOOR,FEATSTONE,VAR_3},
{"featstone floor 4",FLOOR,FEATSTONE,VAR_4},
{"grass 1",FLOOR,GRASS,VAR_1},
{"grass 2",FLOOR,GRASS,VAR_2},
// 350
{"grass",FLOOR,GRASS,VAR_3},
{"grass",FLOOR,GRASS,VAR_4},
{"grass 3",FLOOR,GRASS,VAR_3},
{"grass 4",FLOOR,GRASS,VAR_4},
{"soil floor",FLOOR,SOIL,VAR_1},
{"soil floor",FLOOR,SOIL,VAR_2},
{"soil floor",FLOOR,SOIL,VAR_3},
@ -533,58 +537,58 @@ namespace DFHack
{"damaged ice wall",WALL,ICE,VAR_1},
{"worn ice wall",WALL,ICE,VAR_1},
{"ice wall",WALL,ICE,VAR_1},
{"river",FLOOR,SOIL,VAR_1},
{"river",FLOOR,SOIL,VAR_1},
{"river",FLOOR,SOIL,VAR_1},
{"river",FLOOR,SOIL,VAR_1},
{"river",FLOOR,SOIL,VAR_1},
{"river N",FLOOR,SOIL,VAR_1},
{"river S",FLOOR,SOIL,VAR_1},
{"river E",FLOOR,SOIL,VAR_1},
{"river W",FLOOR,SOIL,VAR_1},
{"river NW",FLOOR,SOIL,VAR_1},
//370
{"river",FLOOR,SOIL,VAR_1},
{"river",FLOOR,SOIL,VAR_1},
{"river",FLOOR,SOIL,VAR_1},
{"stream",FLOOR,SOIL,VAR_1},
{"stream",FLOOR,SOIL,VAR_1},
{"stream",FLOOR,SOIL,VAR_1},
{"stream",FLOOR,SOIL,VAR_1},
{"stream",FLOOR,SOIL,VAR_1},
{"stream",FLOOR,SOIL,VAR_1},
{"stream",FLOOR,SOIL,VAR_1},
{"river NE",FLOOR,SOIL,VAR_1},
{"river SW",FLOOR,SOIL,VAR_1},
{"river SE",FLOOR,SOIL,VAR_1},
{"stream bed N",FLOOR,SOIL,VAR_1},
{"stream bed S",FLOOR,SOIL,VAR_1},
{"stream bed E",FLOOR,SOIL,VAR_1},
{"stream bed W",FLOOR,SOIL,VAR_1},
{"stream bed NW",FLOOR,SOIL,VAR_1},
{"stream bed NE",FLOOR,SOIL,VAR_1},
{"stream bed SW",FLOOR,SOIL,VAR_1},
// 380
{"stream",FLOOR,SOIL,VAR_1},
{"stream bed SE",FLOOR,SOIL,VAR_1},
{"stream top",FLOOR,SOIL,VAR_1},
{0 ,EMPTY, AIR, VAR_1},
{0 ,EMPTY, AIR, VAR_1},
{0 ,EMPTY, AIR, VAR_1},
{0 ,EMPTY, AIR, VAR_1},
{0 ,EMPTY, AIR, VAR_1},
{"dry grass",FLOOR,GRASS_DRY,VAR_1},
{"dry grass",FLOOR,GRASS_DRY,VAR_2},
{"dry grass",FLOOR,GRASS_DRY,VAR_3},
{"dry grass 1",FLOOR,GRASS_DRY,VAR_1},
{"dry grass 2",FLOOR,GRASS_DRY,VAR_2},
{"dry grass 3",FLOOR,GRASS_DRY,VAR_3},
// 390
{"dry grass",FLOOR,GRASS_DRY,VAR_4},
{"dry grass 4",FLOOR,GRASS_DRY,VAR_4},
{"dead tree",TREE_DEAD,SOIL,VAR_1},
{"dead sapling",SAPLING_DEAD,SOIL,VAR_1},
{"dead shrub",SHRUB_DEAD,SOIL,VAR_1},
{"dead grass",FLOOR,GRASS_DEAD,VAR_1},
{"dead grass",FLOOR,GRASS_DEAD,VAR_2},
{"dead grass",FLOOR,GRASS_DEAD,VAR_3},
{"dead grass",FLOOR,GRASS_DEAD,VAR_4},
{"grass",FLOOR,GRASS2,VAR_1},
{"grass",FLOOR,GRASS2,VAR_2},
{"dead grass 1",FLOOR,GRASS_DEAD,VAR_1},
{"dead grass 2",FLOOR,GRASS_DEAD,VAR_2},
{"dead grass 3",FLOOR,GRASS_DEAD,VAR_3},
{"dead grass 4",FLOOR,GRASS_DEAD,VAR_4},
{"grass B1",FLOOR,GRASS2,VAR_1},
{"grass B2",FLOOR,GRASS2,VAR_2},
// 400
{"grass",FLOOR,GRASS2,VAR_3},
{"grass",FLOOR,GRASS2,VAR_4},
{"grass B3",FLOOR,GRASS2,VAR_3},
{"grass B4",FLOOR,GRASS2,VAR_4},
{"boulder",BOULDER,STONE,VAR_1},
{"obsidian boulder",BOULDER,OBSIDIAN,VAR_1},
{"featstone? boulder",BOULDER,FEATSTONE,VAR_1},
{"pebbles",PEBBLES,STONE,VAR_1},
{"pebbles",PEBBLES,STONE,VAR_2},
{"pebbles",PEBBLES,STONE,VAR_3},
{"pebbles",PEBBLES,STONE,VAR_4},
{"pebbles 1",PEBBLES,STONE,VAR_1},
{"pebbles 2",PEBBLES,STONE,VAR_2},
{"pebbles 3",PEBBLES,STONE,VAR_3},
{"pebbles 4",PEBBLES,STONE,VAR_4},
{"obsidian shards",PEBBLES,OBSIDIAN,VAR_1},
// 410

@ -27,41 +27,61 @@ distribution.
#include "Tranquility.h"
#include "Export.h"
namespace DFHack
{
class Process;
template <class T>
class DFHACK_EXPORT DfVector
{
private:
// starting offset
uint32_t start;
// vector size
uint32_t size;
uint32_t item_size;
uint8_t* data;
uint32_t _start;// starting offset
uint32_t _size;// vector size
T * data; // cached data
public:
DfVector();
DfVector(Process * p, uint32_t address, uint32_t item_size);
~DfVector();
DfVector(Process * p, uint32_t address)
{
uint32_t triplet[3];
memory_info * mem = p->getDescriptor();
uint32_t offs = mem->getOffset("vector_triplet");
p->read(address + offs, sizeof(triplet), (uint8_t *) &triplet);
_start = triplet[0];
uint32_t byte_size = triplet[1] - triplet[0];
_size = byte_size / sizeof(T);
data = new T[_size];
p->read(_start,byte_size, (uint8_t *)data);
};
DfVector()
{
data = 0;
};
~DfVector()
{
if(data)
delete [] data;
};
// get offset of the specified index
inline void* operator[] (uint32_t index)
inline T& operator[] (uint32_t index)
{
// FIXME: vector out of bounds exception
//assert(index < size);
return data + index*item_size;
return data[index];
};
// get offset of the specified index
inline void* at (uint32_t index)
inline T& at (uint32_t index)
{
//assert(index < size);
return data + index*item_size;
return data[index];
};
// get vector size
inline uint32_t getSize ()
inline uint32_t size ()
{
return _size;
};
// get vector start
inline uint32_t start ()
{
return size;
return _start;
};
};
}

@ -32,9 +32,15 @@ namespace DFHack
Buildings(APIPrivate * d);
~Buildings();
bool Start(uint32_t & numBuildings);
// read one building at offset
bool Read (const uint32_t index, t_building & building);
bool Finish();
// read a vector of names
bool ReadCustomWorkshopTypes(map <uint32_t, string> & btypes);
// returns -1 on error, >= 0 for real value
int32_t GetCustomWorkshopType(t_building & building);
private:
struct Private;
Private *d;

@ -14,7 +14,7 @@ namespace DFHack
constr_boulder = 4,
constr_logs = 5,
};
#pragma pack(1)
#pragma pack(push, 1)
struct t_construction
{
//0
@ -38,7 +38,7 @@ namespace DFHack
// added later by dfhack
uint32_t origin;
};
#pragma pack (pop)
class APIPrivate;
class DFHACK_EXPORT Constructions
{

@ -319,6 +319,7 @@ namespace DFHack
uint16_t y;
uint16_t z;
uint32_t race;
int32_t civ;
t_creaturflags1 flags1;
t_creaturflags2 flags2;
@ -344,9 +345,9 @@ namespace DFHack
t_attrib recuperation;
t_attrib disease_resistance;
int32_t squad_leader_id;
uint8_t sex;
uint8_t sex; // really a caste
uint32_t pregnancy_timer; //Countdown timer to giving birth
bool has_default_soul;
t_soul defaultSoul;
};
@ -368,10 +369,11 @@ namespace DFHack
bool ReadCreature(const int32_t index, t_creature & furball);
/// write labors of a creature (for Dwarf Therapist)
bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]);
uint32_t GetDwarfRaceIndex ( void );
int32_t GetDwarfCivId ( void );
private:
struct Private;
Private *d;
};
}
#endif
#endif

@ -114,9 +114,10 @@ namespace DFHack
e_traffic traffic : 2; // needs enum
unsigned int flow_forbid : 1; // what?
unsigned int liquid_static : 1;
unsigned int moss : 1;// I LOVE MOSS
unsigned int feature_present : 1; // another wtf... is this required for magma pipes to work?
unsigned int feature_type_1 : 1; // this tile is a part of a feature
unsigned int feature_type_2 : 1; // this tile is a part of a feature
unsigned int liquid_character : 2; // those ripples on streams?
};
union t_designation
@ -199,6 +200,7 @@ namespace DFHack
typedef DFHack::t_designation designations40d [16][16];
typedef DFHack::t_occupancy occupancies40d [16][16];
typedef uint8_t biome_indices40d [16];
typedef uint16_t t_temperatures [16][16];
typedef struct
{
@ -290,6 +292,10 @@ namespace DFHack
bool ReadDesignations(uint32_t blockx, uint32_t blocky, uint32_t blockz, designations40d *buffer);
bool WriteDesignations (uint32_t blockx, uint32_t blocky, uint32_t blockz, designations40d *buffer);
/// read/write temperatures
bool ReadTemperatures(uint32_t blockx, uint32_t blocky, uint32_t blockz, t_temperatures *temp1, t_temperatures *temp2);
bool WriteTemperatures (uint32_t blockx, uint32_t blocky, uint32_t blockz, t_temperatures *temp1, t_temperatures *temp2);
/// read/write block occupancies
bool ReadOccupancy(uint32_t blockx, uint32_t blocky, uint32_t blockz, occupancies40d *buffer);
bool WriteOccupancy(uint32_t blockx, uint32_t blocky, uint32_t blockz, occupancies40d *buffer);

@ -17,6 +17,15 @@ namespace DFHack
char name[128]; //this is the name displayed ingame
};
struct t_descriptor_color
{
char id[128]; // id in the raws
float r;
float v;
float b;
char name[128]; //displayed name
};
struct t_matglossPlant
{
char id[128]; //the id in the raws
@ -29,6 +38,27 @@ namespace DFHack
char extract_name[128];
};
struct t_creaturecaste
{
char rawname[128];
char singular[128];
char plural[128];
char adjective[128];
};
// this doesn't transfer well across the shm gap...
struct t_creaturetype
{
char rawname[128];
vector <t_creaturecaste> castes;
uint8_t tile_character;
struct
{
uint16_t fore;
uint16_t back;
uint16_t bright;
} tilecolor;
};
class DFHACK_EXPORT Materials
{
public:
@ -45,8 +75,12 @@ namespace DFHack
// TODO: maybe move to creatures?
bool ReadCreatureTypes (std::vector<t_matgloss> & output);
bool ReadCreatureTypesEx (vector<t_creaturetype> & creatures);
bool ReadDescriptorColors(std::vector<t_descriptor_color> & output);
private:
APIPrivate* d;
class Private;
Private* d;
};
}
#endif

@ -52,10 +52,14 @@ struct t_building_df40d
struct Buildings::Private
{
uint32_t buildings_vector;
// translation
DfVector * p_bld;
uint32_t custom_workshop_vector;
uint32_t building_custom_workshop_type;
uint32_t custom_workshop_type;
uint32_t custom_workshop_name;
int32_t custom_workshop_id;
DfVector <uint32_t> * p_bld;
APIPrivate *d;
Process * owner;
bool Inited;
bool Started;
};
@ -64,9 +68,15 @@ Buildings::Buildings(APIPrivate * d_)
{
d = new Private;
d->d = d_;
d->owner = d_->p;
d->Inited = d->Started = false;
memory_info * mem = d->d->offset_descriptor;
d->custom_workshop_vector = mem->getAddress("custom_workshop_vector");
d->building_custom_workshop_type = mem->getOffset("building_custom_workshop_type");
d->custom_workshop_type = mem->getOffset("custom_workshop_type");
d->custom_workshop_name = mem->getOffset("custom_workshop_name");
d->buildings_vector = mem->getAddress ("buildings_vector");
mem->resolveClassnameToClassID("building_custom_workshop", d->custom_workshop_id);
d->Inited = true;
}
@ -79,8 +89,8 @@ Buildings::~Buildings()
bool Buildings::Start(uint32_t & numbuildings)
{
d->p_bld = new DfVector (g_pProcess, d->buildings_vector, 4);
numbuildings = d->p_bld->getSize();
d->p_bld = new DfVector <uint32_t> (d->owner, d->buildings_vector);
numbuildings = d->p_bld->size();
d->Started = true;
return true;
}
@ -92,15 +102,15 @@ bool Buildings::Read (const uint32_t index, t_building & building)
t_building_df40d bld_40d;
// read pointer from vector at position
uint32_t temp = * (uint32_t *) d->p_bld->at (index);
uint32_t temp = d->p_bld->at (index);
//d->p_bld->read(index,(uint8_t *)&temp);
//read building from memory
g_pProcess->read (temp, sizeof (t_building_df40d), (uint8_t *) &bld_40d);
d->owner->read (temp, sizeof (t_building_df40d), (uint8_t *) &bld_40d);
// transform
int32_t type = -1;
d->d->offset_descriptor->resolveObjectToClassID (temp, type);
d->owner->getDescriptor()->resolveObjectToClassID (temp, type);
building.origin = temp;
building.vtable = bld_40d.vtable;
building.x1 = bld_40d.x1;
@ -122,4 +132,40 @@ bool Buildings::Finish()
}
d->Started = false;
return true;
}
bool Buildings::ReadCustomWorkshopTypes(map <uint32_t, string> & btypes)
{
if(!d->Started)
return false;
Process * p = d->owner;
DfVector <uint32_t> p_matgloss (p, d->custom_workshop_vector);
uint32_t size = p_matgloss.size();
btypes.clear();
for (uint32_t i = 0; i < size;i++)
{
string out = p->readSTLString (p_matgloss[i] + d->custom_workshop_name);
uint32_t type = p->readDWord (p_matgloss[i] + d->custom_workshop_type);
#ifdef DEBUG
cout << out << ": " << type << endl;
#endif
btypes[type] = out;
}
return true;
}
int32_t Buildings::GetCustomWorkshopType(t_building & building)
{
if(!d->Inited)
return false;
int32_t type = (int32_t)building.type;
int32_t ret = -1;
if(type != -1 && type == d->custom_workshop_id)
{
// read the custom workshop subtype
ret = (int32_t) d->owner->readDWord(building.origin + d->building_custom_workshop_type);
}
return ret;
}

@ -37,9 +37,10 @@ struct Constructions::Private
{
uint32_t construction_vector;
// translation
DfVector * p_cons;
DfVector <uint32_t> * p_cons;
APIPrivate *d;
Process * owner;
bool Inited;
bool Started;
};
@ -48,6 +49,7 @@ Constructions::Constructions(APIPrivate * d_)
{
d = new Private;
d->d = d_;
d->owner = d_->p;
d->p_cons = 0;
d->Inited = d->Started = false;
memory_info * mem = d->d->offset_descriptor;
@ -64,8 +66,8 @@ Constructions::~Constructions()
bool Constructions::Start(uint32_t & numconstructions)
{
d->p_cons = new DfVector (g_pProcess, d->construction_vector, 4);
numconstructions = d->p_cons->getSize();
d->p_cons = new DfVector <uint32_t> (d->owner, d->construction_vector);
numconstructions = d->p_cons->size();
d->Started = true;
return true;
}
@ -76,10 +78,10 @@ bool Constructions::Read (const uint32_t index, t_construction & construction)
if(!d->Started) return false;
// read pointer from vector at position
uint32_t temp = * (uint32_t *) d->p_cons->at (index);
uint32_t temp = d->p_cons->at (index);
//read construction from memory
g_pProcess->read (temp, sizeof (t_construction), (uint8_t *) &construction);
d->owner->read (temp, sizeof (t_construction), (uint8_t *) &construction);
// transform
construction.origin = temp;

@ -25,9 +25,9 @@ distribution.
#include "DFCommonInternal.h"
#include "../private/APIPrivate.h"
#include "DFVector.h"
#include "DFMemInfo.h"
#include "DFProcess.h"
#include "DFVector.h"
#include "DFError.h"
#include "DFTypes.h"
@ -51,14 +51,18 @@ struct Creatures::Private
bool Started;
Creatures2010::creature_offsets creatures;
uint32_t creature_module;
DfVector *p_cre;
uint32_t dwarf_race_index_addr;
uint32_t dwarf_civ_id_addr;
DfVector <uint32_t> *p_cre;
APIPrivate *d;
Process *owner;
};
Creatures::Creatures(APIPrivate* _d)
{
d = new Private;
d->d = _d;
Process * p = d->owner = _d->p;
d->Inited = false;
d->Started = false;
d->d->InitReadNames(); // throws on error
@ -71,6 +75,7 @@ Creatures::Creatures(APIPrivate* _d)
creatures.profession_offset = minfo->getOffset ("creature_profession");
creatures.custom_profession_offset = minfo->getOffset ("creature_custom_profession");
creatures.race_offset = minfo->getOffset ("creature_race");
creatures.civ_offset = minfo->getOffset ("creature_civ");
creatures.flags1_offset = minfo->getOffset ("creature_flags1");
creatures.flags2_offset = minfo->getOffset ("creature_flags2");
creatures.name_offset = minfo->getOffset ("creature_name");
@ -83,6 +88,7 @@ Creatures::Creatures(APIPrivate* _d)
creatures.default_soul_offset = minfo->getOffset("creature_default_soul");
creatures.physical_offset = minfo->getOffset("creature_physical");
creatures.mood_offset = minfo->getOffset("creature_mood");
creatures.pickup_equipment_bit = minfo->getOffset("creature_pickup_equipment_bit");
// soul offsets
creatures.soul_skills_vector_offset = minfo->getOffset("soul_skills_vector");
creatures.soul_mental_offset = minfo->getOffset("soul_mental");
@ -92,14 +98,15 @@ Creatures::Creatures(APIPrivate* _d)
creatures.name_firstname_offset = minfo->getOffset("name_firstname");
creatures.name_nickname_offset = minfo->getOffset("name_nickname");
creatures.name_words_offset = minfo->getOffset("name_words");
d->dwarf_race_index_addr = minfo->getAddress("dwarf_race_index");
d->dwarf_civ_id_addr = minfo->getAddress("dwarf_civ_id");
// upload offsets to the SHM
if(g_pProcess->getModuleIndex("Creatures2010",1,d->creature_module))
if(p->getModuleIndex("Creatures2010",1,d->creature_module))
{
// supply the module with offsets so it can work with them
memcpy(SHMDATA(Creatures2010::creature_offsets),&creatures,sizeof(Creatures2010::creature_offsets));
const uint32_t cmd = Creatures2010::CREATURE_INIT + (d->creature_module << 16);
g_pProcess->SetAndWait(cmd);
p->SetAndWait(cmd);
}
d->Inited = true;
}
@ -118,9 +125,9 @@ Creatures::~Creatures()
bool Creatures::Start( uint32_t &numcreatures )
{
d->p_cre = new DfVector (d->d->p, d->creatures.vector, 4);
d->p_cre = new DfVector <uint32_t> (d->owner, d->creatures.vector);
d->Started = true;
numcreatures = d->p_cre->getSize();
numcreatures = d->p_cre->size();
return true;
}
@ -139,11 +146,12 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
{
if(!d->Started) return false;
// SHM fast path
Process * p = d->owner;
if(d->creature_module)
{
SHMCREATURESHDR->index = index;
const uint32_t cmd = Creatures2010::CREATURE_AT_INDEX + (d->creature_module << 16);
g_pProcess->SetAndWait(cmd);
p->SetAndWait(cmd);
memcpy(&furball,SHMDATA(t_creature),sizeof(t_creature));
return true;
}
@ -151,7 +159,7 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
// non-SHM slow path
// read pointer from vector at position
uint32_t temp = * (uint32_t *) d->p_cre->at (index);
uint32_t temp = d->p_cre->at (index);
furball.origin = temp;
Creatures2010::creature_offsets &offs = d->creatures;
@ -161,38 +169,39 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
d->d->readName(furball.name,temp + offs.name_offset);
// basic stuff
g_pProcess->readDWord (temp + offs.happiness_offset, furball.happiness);
g_pProcess->readDWord (temp + offs.id_offset, furball.id);
g_pProcess->read (temp + offs.pos_offset, 3 * sizeof (uint16_t), (uint8_t *) & (furball.x)); // xyz really
g_pProcess->readDWord (temp + offs.race_offset, furball.race);
g_pProcess->readByte (temp + offs.sex_offset, furball.sex);
g_pProcess->readDWord (temp + offs.flags1_offset, furball.flags1.whole);
g_pProcess->readDWord (temp + offs.flags2_offset, furball.flags2.whole);
p->readDWord (temp + offs.happiness_offset, furball.happiness);
p->readDWord (temp + offs.id_offset, furball.id);
p->read (temp + offs.pos_offset, 3 * sizeof (uint16_t), (uint8_t *) & (furball.x)); // xyz really
p->readDWord (temp + offs.race_offset, furball.race);
furball.civ = p->readDWord (temp + offs.civ_offset);
p->readByte (temp + offs.sex_offset, furball.sex);
p->readDWord (temp + offs.flags1_offset, furball.flags1.whole);
p->readDWord (temp + offs.flags2_offset, furball.flags2.whole);
// physical attributes
g_pProcess->read(temp + offs.physical_offset, sizeof(t_attrib) * 6, (uint8_t *)&furball.strength);
p->read(temp + offs.physical_offset, sizeof(t_attrib) * 6, (uint8_t *)&furball.strength);
// mood stuff
furball.mood = (int16_t) g_pProcess->readWord (temp + offs.mood_offset);
furball.mood = (int16_t) p->readWord (temp + offs.mood_offset);
d->d->readName(furball.artifact_name, temp + offs.artifact_name_offset);
// custom profession
fill_char_buf (furball.custom_profession, g_pProcess->readSTLString (temp + offs.custom_profession_offset));
fill_char_buf (furball.custom_profession, p->readSTLString (temp + offs.custom_profession_offset));
// labors
g_pProcess->read (temp + offs.labors_offset, NUM_CREATURE_LABORS, furball.labors);
p->read (temp + offs.labors_offset, NUM_CREATURE_LABORS, furball.labors);
// profession
furball.profession = g_pProcess->readByte (temp + offs.profession_offset);
furball.profession = p->readByte (temp + offs.profession_offset);
// current job HACK: the job object isn't cleanly represented here
/*
uint32_t jobIdAddr = g_pProcess->readDWord (temp + offs.creature_current_job_offset);
uint32_t jobIdAddr = p->readDWord (temp + offs.creature_current_job_offset);
if (jobIdAddr)
{
furball.current_job.active = true;
furball.current_job.jobId = g_pProcess->readByte (jobIdAddr + offs.creature_current_job_id_offset);
furball.current_job.jobId = p->readByte (jobIdAddr + offs.creature_current_job_id_offset);
}
else
{
@ -201,39 +210,43 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
*/
/*
g_pProcess->readDWord(temp + offs.creature_pregnancy_offset, furball.pregnancy_timer);
p->readDWord(temp + offs.creature_pregnancy_offset, furball.pregnancy_timer);
*/
/*
// enum soul pointer vector
DfVector souls(g_pProcess,temp + offs.creature_soul_vector_offset,4);
DfVector <uint32_t> souls(p,temp + offs.creature_soul_vector_offset);
*/
uint32_t soul = g_pProcess->readDWord(temp + offs.default_soul_offset);
// get first soul's skills
DfVector skills(g_pProcess, soul + offs.soul_skills_vector_offset, 4 );
furball.defaultSoul.numSkills = skills.getSize();
for (uint32_t i = 0; i < furball.defaultSoul.numSkills;i++)
uint32_t soul = p->readDWord(temp + offs.default_soul_offset);
furball.has_default_soul = false;
if(soul)
{
uint32_t temp2 = * (uint32_t *) skills[i];
// a byte: this gives us 256 skills maximum.
furball.defaultSoul.skills[i].id = g_pProcess->readByte (temp2);
furball.defaultSoul.skills[i].rating = g_pProcess->readByte (temp2 + 4);
furball.defaultSoul.skills[i].experience = g_pProcess->readWord (temp2 + 8);
furball.has_default_soul = true;
// get first soul's skills
DfVector <uint32_t> skills(p, soul + offs.soul_skills_vector_offset);
furball.defaultSoul.numSkills = skills.size();
for (uint32_t i = 0; i < furball.defaultSoul.numSkills;i++)
{
uint32_t temp2 = skills[i];
// a byte: this gives us 256 skills maximum.
furball.defaultSoul.skills[i].id = p->readByte (temp2);
furball.defaultSoul.skills[i].rating = p->readByte (temp2 + 4);
furball.defaultSoul.skills[i].experience = p->readWord (temp2 + 8);
}
// mental attributes are part of the soul
p->read(soul + offs.soul_mental_offset, sizeof(t_attrib) * 13, (uint8_t *)&furball.defaultSoul.analytical_ability);
// traits as well
p->read(soul + offs.soul_traits_offset, sizeof (uint16_t) * NUM_CREATURE_TRAITS, (uint8_t *) &furball.defaultSoul.traits);
}
// mental attributes are part of the soul
g_pProcess->read(soul + offs.soul_mental_offset, sizeof(t_attrib) * 13, (uint8_t *)&furball.defaultSoul.analytical_ability);
// traits as well
g_pProcess->read(soul + offs.soul_traits_offset, sizeof (uint16_t) * NUM_CREATURE_TRAITS, (uint8_t *) &furball.defaultSoul.traits);
//likes
/*
DfVector likes(d->p, temp + offs.creature_likes_offset, 4);
DfVector <uint32_t> likes(d->p, temp + offs.creature_likes_offset);
furball.numLikes = likes.getSize();
for(uint32_t i = 0;i<furball.numLikes;i++)
{
uint32_t temp2 = *(uint32_t *) likes[i];
g_pProcess->read(temp2,sizeof(t_like),(uint8_t *) &furball.likes[i]);
p->read(temp2,sizeof(t_like),(uint8_t *) &furball.likes[i]);
}*/
return true;
@ -244,7 +257,11 @@ int32_t Creatures::ReadCreatureInBox (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)
{
if (!d->Started) return -1;
if (!d->Started)
return -1;
Process *p = d->owner;
if(d->creature_module)
{
// supply the module with offsets so it can work with them
@ -256,7 +273,7 @@ int32_t Creatures::ReadCreatureInBox (int32_t index, t_creature & furball,
SHMCREATURESHDR->y2 = y2;
SHMCREATURESHDR->z2 = z2;
const uint32_t cmd = Creatures2010::CREATURE_FIND_IN_BOX + (d->creature_module << 16);
g_pProcess->SetAndWait(cmd);
p->SetAndWait(cmd);
if(SHMCREATURESHDR->index != -1)
memcpy(&furball,SHMDATA(void),sizeof(t_creature));
return SHMCREATURESHDR->index;
@ -264,12 +281,12 @@ int32_t Creatures::ReadCreatureInBox (int32_t index, t_creature & furball,
else
{
uint16_t coords[3];
uint32_t size = d->p_cre->getSize();
uint32_t size = d->p_cre->size();
while (uint32_t(index) < size)
{
// read pointer from vector at position
uint32_t temp = * (uint32_t *) d->p_cre->at (index);
g_pProcess->read (temp + d->creatures.pos_offset, 3 * sizeof (uint16_t), (uint8_t *) &coords);
uint32_t temp = d->p_cre->at(index);
p->read (temp + d->creatures.pos_offset, 3 * sizeof (uint16_t), (uint8_t *) &coords);
if (coords[0] >= x1 && coords[0] < x2)
{
if (coords[1] >= y1 && coords[1] < y2)
@ -292,16 +309,36 @@ int32_t Creatures::ReadCreatureInBox (int32_t index, t_creature & furball,
bool Creatures::WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS])
{
if(!d->Started) return false;
uint32_t temp = * (uint32_t *) d->p_cre->at (index);
g_pProcess->write(temp + d->creatures.labors_offset, NUM_CREATURE_LABORS, labors);
uint32_t temp = d->p_cre->at (index);
Process * p = d->owner;
p->write(temp + d->creatures.labors_offset, NUM_CREATURE_LABORS, labors);
uint32_t pickup_equip;
p->readDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip);
pickup_equip |= 1u;
p->writeDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip);
return true;
}
uint32_t Creatures::GetDwarfRaceIndex()
{
if(!d->Inited) return 0;
Process * p = d->owner;
return p->readDWord(d->dwarf_race_index_addr);
}
int32_t Creatures::GetDwarfCivId()
{
if(!d->Inited) return -1;
Process * p = d->owner;
return p->readDWord(d->dwarf_civ_id_addr);
}
/*
bool API::getCurrentCursorCreature(uint32_t & creature_index)
bool Creatures::getCurrentCursorCreature(uint32_t & creature_index)
{
if(!d->cursorWindowInited) return false;
creature_index = g_pProcess->readDWord(d->current_cursor_creature_offset);
Process * p = d->owner;
creature_index = p->readDWord(d->current_cursor_creature_offset);
return true;
}
*/
*/

@ -40,6 +40,7 @@ struct Gui::Private
uint32_t current_cursor_creature_offset;
uint32_t current_menu_state_offset;
APIPrivate *d;
Process * owner;
};
Gui::Gui(APIPrivate * _d)
@ -47,6 +48,7 @@ Gui::Gui(APIPrivate * _d)
d = new Private;
d->d = _d;
d->owner = _d->p;
d->Inited = d->Started = true;
memory_info * mem = d->d->offset_descriptor;
@ -76,29 +78,30 @@ bool Gui::ReadPauseState()
// replace with an exception
if(!d->Inited) return false;
uint32_t pauseState = g_pProcess->readDWord (d->pause_state_offset);
uint32_t pauseState = d->owner->readDWord (d->pause_state_offset);
return pauseState & 1;
}
uint32_t Gui::ReadMenuState()
{
if(d->Inited)
return(g_pProcess->readDWord(d->current_menu_state_offset));
return(d->owner->readDWord(d->current_menu_state_offset));
return false;
}
bool Gui::ReadViewScreen (t_viewscreen &screen)
{
if (!d->Inited) return false;
Process * p = d->owner;
uint32_t last = g_pProcess->readDWord (d->view_screen_offset);
uint32_t screenAddr = g_pProcess->readDWord (last);
uint32_t nextScreenPtr = g_pProcess->readDWord (last + 4);
uint32_t last = p->readDWord (d->view_screen_offset);
uint32_t screenAddr = p->readDWord (last);
uint32_t nextScreenPtr = p->readDWord (last + 4);
while (nextScreenPtr != 0)
{
last = nextScreenPtr;
screenAddr = g_pProcess->readDWord (nextScreenPtr);
nextScreenPtr = g_pProcess->readDWord (nextScreenPtr + 4);
screenAddr = p->readDWord (nextScreenPtr);
nextScreenPtr = p->readDWord (nextScreenPtr + 4);
}
return d->d->offset_descriptor->resolveObjectToClassID (last, screen.type);
}

@ -51,6 +51,7 @@ struct Maps::Private
Server::Maps::maps_offsets offsets;
APIPrivate *d;
Process * owner;
bool Inited;
bool Started;
vector<uint16_t> v_geology[eBiomeCount];
@ -60,9 +61,10 @@ Maps::Maps(APIPrivate* _d)
{
d = new Private;
d->d = _d;
Process *p = d->owner = _d->p;
d->Inited = d->Started = false;
DFHack::memory_info * mem = d->d->offset_descriptor;
DFHack::memory_info * mem = p->getDescriptor();
Server::Maps::maps_offsets &off = d->offsets;
// get the offsets once here
@ -70,12 +72,14 @@ Maps::Maps(APIPrivate* _d)
off.x_count_offset = mem->getAddress ("x_count_block");
off.y_count_offset = mem->getAddress ("y_count_block");
off.z_count_offset = mem->getAddress ("z_count_block");
off.tile_type_offset = mem->getOffset ("type");
off.designation_offset = mem->getOffset ("designation");
off.occupancy_offset = mem->getOffset("occupancy");
off.biome_stuffs = mem->getOffset ("biome_stuffs");
off.veinvector = mem->getOffset ("v_vein");
off.tile_type_offset = mem->getOffset ("map_data_type");
off.designation_offset = mem->getOffset ("map_data_designation");
off.occupancy_offset = mem->getOffset("map_data_occupancy");
off.biome_stuffs = mem->getOffset ("map_data_biome_stuffs");
off.veinvector = mem->getOffset ("map_data_vein_vector");
off.temperature1_offset = mem->getOffset ("map_data_temperature1_offset");
off.temperature2_offset = mem->getOffset ("map_data_temperature2_offset");
// these can fail and will be found when looking at the actual veins later
// basically a cache
off.vein_ice_vptr = 0;
@ -85,14 +89,14 @@ Maps::Maps(APIPrivate* _d)
// upload offsets to SHM server if possible
d->maps_module = 0;
if(g_pProcess->getModuleIndex("Maps2010",1,d->maps_module))
if(p->getModuleIndex("Maps2010",1,d->maps_module))
{
// supply the module with offsets so it can work with them
Server::Maps::maps_offsets *off2 = SHMDATA(Server::Maps::maps_offsets);
memcpy(off2, &(d->offsets), sizeof(Server::Maps::maps_offsets));
full_barrier
const uint32_t cmd = Server::Maps::MAP_INIT + (d->maps_module << 16);
g_pProcess->SetAndWait(cmd);
p->SetAndWait(cmd);
}
d->Inited = true;
}
@ -112,9 +116,10 @@ bool Maps::Start()
return false;
if(d->Started)
Finish();
Process *p = d->owner;
Server::Maps::maps_offsets &off = d->offsets;
// get the map pointer
uint32_t x_array_loc = g_pProcess->readDWord (off.map_offset);
uint32_t x_array_loc = p->readDWord (off.map_offset);
if (!x_array_loc)
{
return false;
@ -122,9 +127,9 @@ bool Maps::Start()
// get the size
uint32_t mx, my, mz;
mx = d->x_block_count = g_pProcess->readDWord (off.x_count_offset);
my = d->y_block_count = g_pProcess->readDWord (off.y_count_offset);
mz = d->z_block_count = g_pProcess->readDWord (off.z_count_offset);
mx = d->x_block_count = p->readDWord (off.x_count_offset);
my = d->y_block_count = p->readDWord (off.y_count_offset);
mz = d->z_block_count = p->readDWord (off.z_count_offset);
// test for wrong map dimensions
if (mx == 0 || mx > 48 || my == 0 || my > 48 || mz == 0)
@ -137,23 +142,21 @@ bool Maps::Start()
d->block = new uint32_t[mx*my*mz];
uint32_t *temp_x = new uint32_t[mx];
uint32_t *temp_y = new uint32_t[my];
uint32_t *temp_z = new uint32_t[mz];
g_pProcess->read (x_array_loc, mx * sizeof (uint32_t), (uint8_t *) temp_x);
p->read (x_array_loc, mx * sizeof (uint32_t), (uint8_t *) temp_x);
for (uint32_t x = 0; x < mx; x++)
{
g_pProcess->read (temp_x[x], my * sizeof (uint32_t), (uint8_t *) temp_y);
p->read (temp_x[x], my * sizeof (uint32_t), (uint8_t *) temp_y);
// y -> map column
for (uint32_t y = 0; y < my; y++)
{
g_pProcess->read (temp_y[y],
p->read (temp_y[y],
mz * sizeof (uint32_t),
(uint8_t *) (d->block + x*my*mz + y*mz));
}
}
delete [] temp_x;
delete [] temp_y;
delete [] temp_z;
return true;
}
@ -195,13 +198,14 @@ uint32_t Maps::getBlockPtr (uint32_t x, uint32_t y, uint32_t z)
bool Maps::ReadBlock40d(uint32_t x, uint32_t y, uint32_t z, mapblock40d * buffer)
{
Process *p = d->owner;
if(d->d->shm_start && d->maps_module) // ACCELERATE!
{
SHMMAPSHDR->x = x;
SHMMAPSHDR->y = y;
SHMMAPSHDR->z = z;
volatile uint32_t cmd = Server::Maps::MAP_READ_BLOCK_BY_COORDS + (d->maps_module << 16);
if(!g_pProcess->SetAndWait(cmd))
if(!p->SetAndWait(cmd))
return false;
memcpy(buffer,SHMDATA(mapblock40d),sizeof(mapblock40d));
return true;
@ -211,13 +215,13 @@ bool Maps::ReadBlock40d(uint32_t x, uint32_t y, uint32_t z, mapblock40d * buffer
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if (addr)
{
g_pProcess->read (addr + d->offsets.tile_type_offset, sizeof (buffer->tiletypes), (uint8_t *) buffer->tiletypes);
g_pProcess->read (addr + d->offsets.designation_offset, sizeof (buffer->designation), (uint8_t *) buffer->designation);
g_pProcess->read (addr + d->offsets.occupancy_offset, sizeof (buffer->occupancy), (uint8_t *) buffer->occupancy);
g_pProcess->read (addr + d->offsets.biome_stuffs, sizeof (biome_indices40d), (uint8_t *) buffer->biome_indices);
p->read (addr + d->offsets.tile_type_offset, sizeof (buffer->tiletypes), (uint8_t *) buffer->tiletypes);
p->read (addr + d->offsets.designation_offset, sizeof (buffer->designation), (uint8_t *) buffer->designation);
p->read (addr + d->offsets.occupancy_offset, sizeof (buffer->occupancy), (uint8_t *) buffer->occupancy);
p->read (addr + d->offsets.biome_stuffs, sizeof (biome_indices40d), (uint8_t *) buffer->biome_indices);
buffer->origin = addr;
uint32_t addr_of_struct = g_pProcess->readDWord(addr);
buffer->blockflags.whole = g_pProcess->readDWord(addr_of_struct);
uint32_t addr_of_struct = p->readDWord(addr);
buffer->blockflags.whole = p->readDWord(addr_of_struct);
return true;
}
return false;
@ -233,7 +237,7 @@ bool Maps::ReadTileTypes (uint32_t x, uint32_t y, uint32_t z, tiletypes40d *buff
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if (addr)
{
g_pProcess->read (addr + d->offsets.tile_type_offset, sizeof (tiletypes40d), (uint8_t *) buffer);
d->owner->read (addr + d->offsets.tile_type_offset, sizeof (tiletypes40d), (uint8_t *) buffer);
return true;
}
return false;
@ -244,7 +248,7 @@ bool Maps::WriteTileTypes (uint32_t x, uint32_t y, uint32_t z, tiletypes40d *buf
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if (addr)
{
g_pProcess->write (addr + d->offsets.tile_type_offset, sizeof (tiletypes40d), (uint8_t *) buffer);
d->owner->write (addr + d->offsets.tile_type_offset, sizeof (tiletypes40d), (uint8_t *) buffer);
return true;
}
return false;
@ -259,8 +263,9 @@ bool Maps::ReadDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool &dirtybit)
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if(addr)
{
uint32_t addr_of_struct = g_pProcess->readDWord(addr);
dirtybit = g_pProcess->readDWord(addr_of_struct) & 1;
Process * p = d->owner;
uint32_t addr_of_struct = p->readDWord(addr);
dirtybit = p->readDWord(addr_of_struct) & 1;
return true;
}
return false;
@ -271,11 +276,12 @@ bool Maps::WriteDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool dirtybit)
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if (addr)
{
uint32_t addr_of_struct = g_pProcess->readDWord(addr);
uint32_t dirtydword = g_pProcess->readDWord(addr_of_struct);
Process * p = d->owner;
uint32_t addr_of_struct = p->readDWord(addr);
uint32_t dirtydword = p->readDWord(addr_of_struct);
dirtydword &= 0xFFFFFFFE;
dirtydword |= (uint32_t) dirtybit;
g_pProcess->writeDWord (addr_of_struct, dirtydword);
p->writeDWord (addr_of_struct, dirtydword);
return true;
}
return false;
@ -287,8 +293,9 @@ bool Maps::ReadBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags &bloc
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if(addr)
{
uint32_t addr_of_struct = g_pProcess->readDWord(addr);
blockflags.whole = g_pProcess->readDWord(addr_of_struct);
Process * p = d->owner;
uint32_t addr_of_struct = p->readDWord(addr);
blockflags.whole = p->readDWord(addr_of_struct);
return true;
}
return false;
@ -298,8 +305,9 @@ bool Maps::WriteBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags bloc
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if (addr)
{
uint32_t addr_of_struct = g_pProcess->readDWord(addr);
g_pProcess->writeDWord (addr_of_struct, blockflags.whole);
Process * p = d->owner;
uint32_t addr_of_struct = p->readDWord(addr);
p->writeDWord (addr_of_struct, blockflags.whole);
return true;
}
return false;
@ -314,7 +322,7 @@ bool Maps::ReadDesignations (uint32_t x, uint32_t y, uint32_t z, designations40d
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if (addr)
{
g_pProcess->read (addr + d->offsets.designation_offset, sizeof (designations40d), (uint8_t *) buffer);
d->owner->read (addr + d->offsets.designation_offset, sizeof (designations40d), (uint8_t *) buffer);
return true;
}
return false;
@ -325,7 +333,7 @@ bool Maps::WriteDesignations (uint32_t x, uint32_t y, uint32_t z, designations40
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if (addr)
{
g_pProcess->write (addr + d->offsets.designation_offset, sizeof (designations40d), (uint8_t *) buffer);
d->owner->write (addr + d->offsets.designation_offset, sizeof (designations40d), (uint8_t *) buffer);
return true;
}
return false;
@ -340,7 +348,7 @@ bool Maps::ReadOccupancy (uint32_t x, uint32_t y, uint32_t z, occupancies40d *bu
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if (addr)
{
g_pProcess->read (addr + d->offsets.occupancy_offset, sizeof (occupancies40d), (uint8_t *) buffer);
d->owner->read (addr + d->offsets.occupancy_offset, sizeof (occupancies40d), (uint8_t *) buffer);
return true;
}
return false;
@ -351,7 +359,37 @@ bool Maps::WriteOccupancy (uint32_t x, uint32_t y, uint32_t z, occupancies40d *b
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if (addr)
{
g_pProcess->write (addr + d->offsets.occupancy_offset, sizeof (tiletypes40d), (uint8_t *) buffer);
d->owner->write (addr + d->offsets.occupancy_offset, sizeof (tiletypes40d), (uint8_t *) buffer);
return true;
}
return false;
}
/*
* Temperatures
*/
bool Maps::ReadTemperatures(uint32_t x, uint32_t y, uint32_t z, t_temperatures *temp1, t_temperatures *temp2)
{
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if (addr)
{
if(temp1)
d->owner->read (addr + d->offsets.temperature1_offset, sizeof (t_temperatures), (uint8_t *) temp1);
if(temp2)
d->owner->read (addr + d->offsets.temperature2_offset, sizeof (t_temperatures), (uint8_t *) temp2);
return true;
}
return false;
}
bool Maps::WriteTemperatures (uint32_t x, uint32_t y, uint32_t z, t_temperatures *temp1, t_temperatures *temp2)
{
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if (addr)
{
if(temp1)
d->owner->write (addr + d->offsets.temperature1_offset, sizeof (t_temperatures), (uint8_t *) temp1);
if(temp2)
d->owner->write (addr + d->offsets.temperature2_offset, sizeof (t_temperatures), (uint8_t *) temp2);
return true;
}
return false;
@ -365,7 +403,7 @@ bool Maps::ReadRegionOffsets (uint32_t x, uint32_t y, uint32_t z, biome_indices4
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if (addr)
{
g_pProcess->read (addr + d->offsets.biome_stuffs, sizeof (biome_indices40d), (uint8_t *) buffer);
d->owner->read (addr + d->offsets.biome_stuffs, sizeof (biome_indices40d), (uint8_t *) buffer);
return true;
}
return false;
@ -379,6 +417,7 @@ bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector <t_vein>* veins,
t_vein v;
t_frozenliquidvein fv;
t_spattervein sv;
Process* p = d->owner;
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if(veins) veins->clear();
@ -390,19 +429,19 @@ bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector <t_vein>* veins,
{
// veins are stored as a vector of pointers to veins
/*pointer is 4 bytes! we work with a 32bit program here, no matter what architecture we compile khazad for*/
DfVector p_veins (d->d->p, addr + off.veinvector, 4);
uint32_t size = p_veins.getSize();
DfVector <uint32_t> p_veins (p, addr + off.veinvector);
uint32_t size = p_veins.size();
// read all veins
for (uint32_t i = 0; i < size;i++)
{
// read the vein pointer from the vector
uint32_t temp = * (uint32_t *) p_veins[i];
uint32_t type = g_pProcess->readDWord(temp);
uint32_t temp = p_veins[i];
uint32_t type = p->readDWord(temp);
try_again:
if(veins && type == off.vein_mineral_vptr)
{
// read the vein data (dereference pointer)
g_pProcess->read (temp, sizeof(t_vein), (uint8_t *) &v);
p->read (temp, sizeof(t_vein), (uint8_t *) &v);
v.address_of = temp;
// store it in the vector
veins->push_back (v);
@ -410,7 +449,7 @@ try_again:
else if(ices && type == off.vein_ice_vptr)
{
// read the ice vein data (dereference pointer)
g_pProcess->read (temp, sizeof(t_frozenliquidvein), (uint8_t *) &fv);
p->read (temp, sizeof(t_frozenliquidvein), (uint8_t *) &fv);
fv.address_of = temp;
// store it in the vector
ices->push_back (fv);
@ -418,14 +457,14 @@ try_again:
else if(splatter && type == off.vein_spatter_vptr)
{
// read the splatter vein data (dereference pointer)
g_pProcess->read (temp, sizeof(t_spattervein), (uint8_t *) &sv);
p->read (temp, sizeof(t_spattervein), (uint8_t *) &sv);
sv.address_of = temp;
// store it in the vector
splatter->push_back (sv);
}
else
{
string cname = g_pProcess->readClassName(type);
string cname = p->readClassName(type);
if(ices && cname == "block_square_event_frozen_liquidst")
{
off.vein_ice_vptr = type;
@ -516,6 +555,7 @@ __int16 __userpurge GetGeologicalRegion<ax>(__int16 block_X<cx>, int X<ebx>, __i
bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
{
memory_info * minfo = d->d->offset_descriptor;
Process *p = d->owner;
// get needed addresses and offsets. Now this is what I call crazy.
int region_x_offset = minfo->getAddress ("region_x");
int region_y_offset = minfo->getAddress ("region_y");
@ -534,19 +574,19 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
uint16_t worldSizeX, worldSizeY;
// read position of the region inside DF world
g_pProcess->readDWord (region_x_offset, regionX);
g_pProcess->readDWord (region_y_offset, regionY);
g_pProcess->readDWord (region_z_offset, regionZ);
p->readDWord (region_x_offset, regionX);
p->readDWord (region_y_offset, regionY);
p->readDWord (region_z_offset, regionZ);
// get world size
g_pProcess->readWord (world_size_x, worldSizeX);
g_pProcess->readWord (world_size_y, worldSizeY);
p->readWord (world_size_x, worldSizeX);
p->readWord (world_size_y, worldSizeY);
// get pointer to first part of 2d array of regions
uint32_t regions = g_pProcess->readDWord (world_regions);
uint32_t regions = p->readDWord (world_regions);
// read the geoblock vector
DfVector geoblocks (d->d->p, world_geoblocks_vector, 4);
DfVector <uint32_t> geoblocks (d->d->p, world_geoblocks_vector);
// iterate over 8 surrounding regions + local region
for (int i = eNorthWest; i < eBiomeCount; i++)
@ -563,32 +603,32 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
/// regions are of region_size size
// get pointer to column of regions
uint32_t geoX;
g_pProcess->readDWord (regions + bioRX*4, geoX);
p->readDWord (regions + bioRX*4, geoX);
// get index into geoblock vector
uint16_t geoindex;
g_pProcess->readWord (geoX + bioRY*region_size + region_geo_index_offset, geoindex);
p->readWord (geoX + bioRY*region_size + region_geo_index_offset, geoindex);
/// geology blocks are assigned to regions from a vector
// get the geoblock from the geoblock vector using the geoindex
// read the matgloss pointer from the vector into temp
uint32_t geoblock_off = * (uint32_t *) geoblocks[geoindex];
uint32_t geoblock_off = geoblocks[geoindex];
/// geology blocks have a vector of layer descriptors
// get the vector with pointer to layers
DfVector geolayers (d->d->p, geoblock_off + geolayer_geoblock_offset , 4); // let's hope
DfVector <uint32_t> geolayers (p, geoblock_off + geolayer_geoblock_offset); // let's hope
// make sure we don't load crap
assert (geolayers.getSize() > 0 && geolayers.getSize() <= 16);
assert (geolayers.size() > 0 && geolayers.size() <= 16);
/// layer descriptor has a field that determines the type of stone/soil
d->v_geology[i].reserve (geolayers.getSize());
d->v_geology[i].reserve (geolayers.size());
// finally, read the layer matgloss
for (uint32_t j = 0;j < geolayers.getSize();j++)
for (uint32_t j = 0;j < geolayers.size();j++)
{
// read pointer to a layer
uint32_t geol_offset = * (uint32_t *) geolayers[j];
uint32_t geol_offset = geolayers[j];
// read word at pointer + 2, store in our geology vectors
d->v_geology[i].push_back (g_pProcess->readWord (geol_offset + type_inside_geolayer));
d->v_geology[i].push_back (p->readWord (geol_offset + type_inside_geolayer));
}
}
assign.clear();

@ -25,17 +25,33 @@ distribution.
#include "DFCommonInternal.h"
#include "../private/APIPrivate.h"
#include "modules/Materials.h"
#include "DFVector.h"
#include "DFMemInfo.h"
#include "DFProcess.h"
#include "DFVector.h"
using namespace DFHack;
class Materials::Private
{
public:
APIPrivate *d;
Process * owner;
/*
bool Inited;
bool Started;
*/
};
Materials::Materials(APIPrivate * d_)
{
d = d_;
d = new Private;
d->d = d_;
d->owner = d_->p;
}
Materials::~Materials()
{
delete d;
}
Materials::~Materials(){}
/*
{
LABEL_53:
@ -131,12 +147,13 @@ LABEL_53:
/*
bool API::ReadInorganicMaterials (vector<t_matgloss> & inorganic)
{
memory_info * minfo = d->offset_descriptor;
Process *p = d->owner;
memory_info * minfo = p->getDescriptor();
int matgloss_address = minfo->getAddress ("mat_inorganics");
int matgloss_colors = minfo->getOffset ("material_color");
int matgloss_stone_name_offset = minfo->getOffset("matgloss_stone_name");
DfVector p_matgloss (d->p, matgloss_address, 4);
DfVector <uint32_t> p_matgloss (p, matgloss_address);
uint32_t size = p_matgloss.getSize();
inorganic.resize (0);
@ -144,17 +161,17 @@ bool API::ReadInorganicMaterials (vector<t_matgloss> & inorganic)
for (uint32_t i = 0; i < size;i++)
{
// read the matgloss pointer from the vector into temp
uint32_t temp = * (uint32_t *) p_matgloss[i];
uint32_t temp = p_matgloss[i];
// read the string pointed at by
t_matgloss mat;
//cout << temp << endl;
//fill_char_buf(mat.id, d->p->readSTLString(temp)); // reads a C string given an address
d->p->readSTLString (temp, mat.id, 128);
p->readSTLString (temp, mat.id, 128);
d->p->readSTLString (temp+matgloss_stone_name_offset, mat.name, 128);
mat.fore = (uint8_t) g_pProcess->readWord (temp + matgloss_colors);
mat.back = (uint8_t) g_pProcess->readWord (temp + matgloss_colors + 2);
mat.bright = (uint8_t) g_pProcess->readWord (temp + matgloss_colors + 4);
p->readSTLString (temp+matgloss_stone_name_offset, mat.name, 128);
mat.fore = (uint8_t) p->readWord (temp + matgloss_colors);
mat.back = (uint8_t) p->readWord (temp + matgloss_colors + 2);
mat.bright = (uint8_t) p->readWord (temp + matgloss_colors + 4);
inorganic.push_back (mat);
}
@ -167,14 +184,14 @@ bool API::ReadInorganicMaterials (vector<t_matgloss> & inorganic)
// good for now
inline bool ReadNamesOnly(Process* p, uint32_t address, vector<t_matgloss> & names)
{
DfVector p_matgloss (p, address, 4);
uint32_t size = p_matgloss.getSize();
DfVector <uint32_t> p_matgloss (p, address);
uint32_t size = p_matgloss.size();
names.clear();
names.reserve (size);
for (uint32_t i = 0; i < size;i++)
{
t_matgloss mat;
p->readSTLString (*(uint32_t *) p_matgloss[i], mat.id, 128);
p->readSTLString (p_matgloss[i], mat.id, 128);
names.push_back(mat);
}
return true;
@ -182,33 +199,85 @@ inline bool ReadNamesOnly(Process* p, uint32_t address, vector<t_matgloss> & nam
bool Materials::ReadInorganicMaterials (vector<t_matgloss> & inorganic)
{
return ReadNamesOnly(d->p, d->offset_descriptor->getAddress ("mat_inorganics"), inorganic );
return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("mat_inorganics"), inorganic );
}
bool Materials::ReadOrganicMaterials (vector<t_matgloss> & organic)
{
return ReadNamesOnly(d->p, d->offset_descriptor->getAddress ("mat_organics_all"), organic );
return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("mat_organics_all"), organic );
}
bool Materials::ReadWoodMaterials (vector<t_matgloss> & trees)
{
return ReadNamesOnly(d->p, d->offset_descriptor->getAddress ("mat_organics_trees"), trees );
return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("mat_organics_trees"), trees );
}
bool Materials::ReadPlantMaterials (vector<t_matgloss> & plants)
{
return ReadNamesOnly(d->p, d->offset_descriptor->getAddress ("mat_organics_plants"), plants );
return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("mat_organics_plants"), plants );
}
/*
Gives bad results combined with the creature race field!
bool Materials::ReadCreatureTypes (vector<t_matgloss> & creatures)
{
return ReadNamesOnly(d->p, d->offset_descriptor->getAddress ("mat_creature_types"), creatures );
return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("creature_type_vector"), creatures );
return true;
}
*/
bool Materials::ReadCreatureTypes (vector<t_matgloss> & creatures)
bool Materials::ReadDescriptorColors (vector<t_descriptor_color> & color)
{
return ReadNamesOnly(d->p, d->offset_descriptor->getAddress ("creature_type_vector"), creatures );
Process * p = d->owner;
DfVector <uint32_t> p_colors (p, p->getDescriptor()->getAddress ("descriptor_colors_vector"));
uint32_t size = p_colors.size();
color.clear();
color.reserve(size);
for (uint32_t i = 0; i < size;i++)
{
t_descriptor_color col;
p->readSTLString (p_colors[i] + p->getDescriptor()->getOffset ("descriptor_rawname"), col.id, 128);
p->readSTLString (p_colors[i] + p->getDescriptor()->getOffset ("descriptor_name"), col.name, 128);
col.r = p->readFloat( p_colors[i] + p->getDescriptor()->getOffset ("descriptor_color_r") );
col.v = p->readFloat( p_colors[i] + p->getDescriptor()->getOffset ("descriptor_color_v") );
col.b = p->readFloat( p_colors[i] + p->getDescriptor()->getOffset ("descriptor_color_b") );
color.push_back(col);
}
}
bool Materials::ReadCreatureTypesEx (vector<t_creaturetype> & creatures)
{
Process *p = d->owner;
memory_info *mem = d->owner->getDescriptor();
DfVector <uint32_t> p_races (p, mem->getAddress ("creature_type_vector"));
uint32_t castes_vector_offset = mem->getOffset ("creature_type_caste_vector");
uint32_t sizeof_string = mem->getHexValue ("sizeof_string");
uint32_t size = p_races.size();
uint32_t sizecas = 0;
uint32_t tile_offset = mem->getOffset ("creature_tile");
uint32_t tile_color_offset = mem->getOffset ("creature_tile_color");
creatures.clear();
creatures.reserve (size);
for (uint32_t i = 0; i < size;i++)
{
t_creaturetype mat;
p->readSTLString (p_races[i], mat.rawname, sizeof(mat.rawname));
DfVector <uint32_t> p_castes(p, p_races[i] + castes_vector_offset);
sizecas = p_castes.size();
for (uint32_t j = 0; j < sizecas;j++)
{
t_creaturecaste caste;
uint32_t caste_start = p_castes[j];
p->readSTLString (caste_start, caste.rawname, sizeof(caste.rawname));
p->readSTLString (caste_start + sizeof_string, caste.singular, sizeof(caste.singular));
p->readSTLString (caste_start + 2 * sizeof_string, caste.plural, sizeof(caste.plural));
p->readSTLString (caste_start + 3 * sizeof_string, caste.adjective, sizeof(caste.adjective));
mat.castes.push_back(caste);
}
mat.tile_character = p->readByte( p_races[i] + tile_offset );
mat.tilecolor.fore = p->readWord( p_races[i] + tile_color_offset );
mat.tilecolor.back = p->readWord( p_races[i] + tile_color_offset + 2 );
mat.tilecolor.bright = p->readWord( p_races[i] + tile_color_offset + 4 );
creatures.push_back(mat);
}
return true;
}

@ -46,6 +46,7 @@ struct Position::Private
uint32_t hotkey_size;
APIPrivate *d;
Process * owner;
bool Inited;
bool Started;
bool StartedHotkeys;
@ -57,6 +58,7 @@ Position::Position(APIPrivate * d_)
{
d = new Private;
d->d = d_;
d->owner = d_->p;
d->Inited = true;
d->StartedHotkeys = d->Started = false;
memory_info * mem;
@ -88,11 +90,13 @@ bool Position::ReadHotkeys(t_hotkey hotkeys[])
{
if (!d->StartedHotkeys) return false;
uint32_t currHotkey = d->hotkey_start;
Process * p = d->owner;
for(uint32_t i = 0 ; i < NUM_HOTKEYS ;i++)
{
g_pProcess->readSTLString(currHotkey,hotkeys[i].name,10);
hotkeys[i].mode = g_pProcess->readWord(currHotkey+d->hotkey_mode_offset);
g_pProcess->read (currHotkey + d->hotkey_xyz_offset, 3*sizeof (int32_t), (uint8_t *) &hotkeys[i].x);
p->readSTLString(currHotkey,hotkeys[i].name,10);
hotkeys[i].mode = p->readWord(currHotkey+d->hotkey_mode_offset);
p->read (currHotkey + d->hotkey_xyz_offset, 3*sizeof (int32_t), (uint8_t *) &hotkeys[i].x);
currHotkey+=d->hotkey_size;
}
return true;
@ -101,9 +105,11 @@ bool Position::ReadHotkeys(t_hotkey hotkeys[])
bool Position::getViewCoords (int32_t &x, int32_t &y, int32_t &z)
{
if (!d->Inited) return false;
g_pProcess->readDWord (d->window_x_offset, (uint32_t &) x);
g_pProcess->readDWord (d->window_y_offset, (uint32_t &) y);
g_pProcess->readDWord (d->window_z_offset, (uint32_t &) z);
Process * p = d->owner;
p->readDWord (d->window_x_offset, (uint32_t &) x);
p->readDWord (d->window_y_offset, (uint32_t &) y);
p->readDWord (d->window_z_offset, (uint32_t &) z);
return true;
}
@ -111,9 +117,11 @@ bool Position::getViewCoords (int32_t &x, int32_t &y, int32_t &z)
bool Position::setViewCoords (const int32_t x, const int32_t y, const int32_t z)
{
if (!d->Inited) return false;
g_pProcess->writeDWord (d->window_x_offset, (uint32_t) x);
g_pProcess->writeDWord (d->window_y_offset, (uint32_t) y);
g_pProcess->writeDWord (d->window_z_offset, (uint32_t) z);
Process * p = d->owner;
p->writeDWord (d->window_x_offset, (uint32_t) x);
p->writeDWord (d->window_y_offset, (uint32_t) y);
p->writeDWord (d->window_z_offset, (uint32_t) z);
return true;
}
@ -121,7 +129,7 @@ bool Position::getCursorCoords (int32_t &x, int32_t &y, int32_t &z)
{
if(!d->Inited) return false;
int32_t coords[3];
g_pProcess->read (d->cursor_xyz_offset, 3*sizeof (int32_t), (uint8_t *) coords);
d->owner->read (d->cursor_xyz_offset, 3*sizeof (int32_t), (uint8_t *) coords);
x = coords[0];
y = coords[1];
z = coords[2];
@ -134,7 +142,7 @@ bool Position::setCursorCoords (const int32_t x, const int32_t y, const int32_t
{
if (!d->Inited) return false;
int32_t coords[3] = {x, y, z};
g_pProcess->write (d->cursor_xyz_offset, 3*sizeof (int32_t), (uint8_t *) coords);
d->owner->write (d->cursor_xyz_offset, 3*sizeof (int32_t), (uint8_t *) coords);
return true;
}
@ -143,7 +151,7 @@ bool Position::getWindowSize (int32_t &width, int32_t &height)
if(!d->Inited) return false;
int32_t coords[2];
g_pProcess->read (d->window_dims_offset, 2*sizeof (int32_t), (uint8_t *) coords);
d->owner->read (d->window_dims_offset, 2*sizeof (int32_t), (uint8_t *) coords);
width = coords[0];
height = coords[1];
return true;

@ -73,15 +73,15 @@ bool Translation::Start()
if(!d->Inited)
return false;
Process * p = d->d->p;
DfVector genericVec (p, d->genericAddress, 4);
DfVector transVec (p, d->transAddress, 4);
DfVector <uint32_t> genericVec (p, d->genericAddress);
DfVector <uint32_t> transVec (p, d->transAddress);
DFDict & translations = d->dicts.translations;
DFDict & foreign_languages = d->dicts.foreign_languages;
translations.resize(10);
for (uint32_t i = 0;i < genericVec.getSize();i++)
for (uint32_t i = 0;i < genericVec.size();i++)
{
uint32_t genericNamePtr = * (uint32_t *) genericVec.at (i);
uint32_t genericNamePtr = genericVec.at(i);
for(int i=0; i<10;i++)
{
string word = p->readSTLString (genericNamePtr + i * d->sizeof_string);
@ -89,15 +89,15 @@ bool Translation::Start()
}
}
foreign_languages.resize(transVec.getSize());
for (uint32_t i = 0; i < transVec.getSize();i++)
foreign_languages.resize(transVec.size());
for (uint32_t i = 0; i < transVec.size();i++)
{
uint32_t transPtr = * (uint32_t *) transVec.at (i);
//string transName = d->p->readSTLString (transPtr);
DfVector trans_names_vec (p, transPtr + d->word_table_offset, 4);
for (uint32_t j = 0;j < trans_names_vec.getSize();j++)
uint32_t transPtr = transVec.at(i);
DfVector <uint32_t> trans_names_vec (p, transPtr + d->word_table_offset);
for (uint32_t j = 0;j < trans_names_vec.size();j++)
{
uint32_t transNamePtr = * (uint32_t *) trans_names_vec.at (j);
uint32_t transNamePtr = trans_names_vec.at(j);
string name = p->readSTLString (transNamePtr);
foreign_languages[i].push_back (name);
}

@ -38,9 +38,10 @@ struct Vegetation::Private
uint32_t vegetation_vector;
uint32_t tree_desc_offset;
// translation
DfVector * p_veg;
DfVector <uint32_t> * p_veg;
APIPrivate *d;
Process * owner;
bool Inited;
bool Started;
};
@ -48,6 +49,7 @@ struct Vegetation::Private
Vegetation::Vegetation(APIPrivate * d_)
{
d = new Private;
d->owner = d_->p;
d->d = d_;
d->Inited = d->Started = false;
memory_info * mem = d->d->offset_descriptor;
@ -65,8 +67,8 @@ Vegetation::~Vegetation()
bool Vegetation::Start(uint32_t & numplants)
{
d->p_veg = new DfVector (g_pProcess, d->vegetation_vector, 4);
numplants = d->p_veg->getSize();
d->p_veg = new DfVector <uint32_t> (d->owner, d->vegetation_vector);
numplants = d->p_veg->size();
d->Started = true;
return true;
}
@ -77,9 +79,9 @@ bool Vegetation::Read (const uint32_t index, t_tree & shrubbery)
if(!d->Started)
return false;
// read pointer from vector at position
uint32_t temp = * (uint32_t *) d->p_veg->at (index);
uint32_t temp = d->p_veg->at (index);
// read from memory
g_pProcess->read (temp + d->tree_desc_offset, sizeof (t_tree), (uint8_t *) &shrubbery);
d->owner->read (temp + d->tree_desc_offset, sizeof (t_tree), (uint8_t *) &shrubbery);
shrubbery.address = temp;
return true;
}

@ -39,6 +39,7 @@ typedef struct
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;
@ -49,6 +50,7 @@ typedef struct
uint32_t artifact_name_offset;
uint32_t physical_offset;
uint32_t mood_offset;
uint32_t pickup_equipment_bit;
uint32_t soul_vector_offset;
uint32_t default_soul_offset;
// soul offsets
@ -93,4 +95,4 @@ DFPP_module Init(void);
}
}
#endif
#endif

@ -84,7 +84,6 @@ void ReadCreatureAtIndex(void *data)
} raw_skill;
// learned skills
std::vector <void *> * skillv = (std::vector <void *> *) (temp + offsets.creature_skills_offset + offsets.vector_correct);
//DfVector skills (d->p->readVector (temp + offsets.creature_skills_offset, 4));
furball->numSkills = skillv->size();
for (uint32_t i = 0; i < furball->numSkills;i++)
{

@ -47,6 +47,8 @@ typedef struct
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 temperature1_offset;
uint32_t temperature2_offset;
uint32_t vein_mineral_vptr;
uint32_t vein_ice_vptr;
uint32_t vein_spatter_vptr;

@ -69,10 +69,10 @@ TARGET_LINK_LIBRARIES(dftreedump dfhack)
ADD_EXECUTABLE(dfspatterdump spatterdump.cpp)
TARGET_LINK_LIBRARIES(dfspatterdump dfhack)
# catsplosion - Makes every cat pregnant, and almost due...
# catsplosion - Accelerates pregnancy
# Author: Zhentar
# ADD_EXECUTABLE(dfcatsplosion catsplosion.cpp)
# TARGET_LINK_LIBRARIES(dfcatsplosion dfhack)
ADD_EXECUTABLE(dfcatsplosion catsplosion.cpp)
TARGET_LINK_LIBRARIES(dfcatsplosion dfhack)
IF(UNIX)
SET(CURSES_NEED_WIDE "YES")

@ -8,6 +8,7 @@
#include <vector>
using namespace std;
#include <DFGlobal.h>
#include <DFError.h>
#include <DFTypes.h>
#include <DFHackAPI.h>
@ -44,7 +45,7 @@ int main (int argc,const char* argv[])
mode = 1;
}
vector<DFHack::t_matgloss> creaturestypes;
map <uint32_t, string> custom_workshop_types;
DFHack::API DF ("Memory.xml");
try
@ -59,6 +60,7 @@ int main (int argc,const char* argv[])
#endif
return 1;
}
DFHack::memory_info * mem = DF.getMemoryInfo();
DFHack::Buildings * Bld = DF.getBuildings();
DFHack::Position * Pos = DF.getPosition();
@ -66,6 +68,7 @@ int main (int argc,const char* argv[])
uint32_t numBuildings;
if(Bld->Start(numBuildings))
{
Bld->ReadCustomWorkshopTypes(custom_workshop_types);
if(mode)
{
cout << numBuildings << endl;
@ -110,6 +113,11 @@ int main (int argc,const char* argv[])
mem->resolveClassIDToClassname(temp.type, typestr);
printf("Address 0x%x, type %d (%s), %d/%d/%d\n",temp.origin, temp.type, typestr.c_str(), temp.x1,temp.y1,temp.z);
printf("Material %d %d\n", temp.material.type, temp.material.index);
int32_t custom;
if((custom = Bld->GetCustomWorkshopType(temp)) != -1)
{
printf("Custom workshop type %s (%d)\n",custom_workshop_types[custom].c_str(),custom);
}
hexdump(DF,temp.origin,120);
}
}

@ -21,28 +21,34 @@ using namespace std;
#include <DFMemInfo.h>
#include <DFProcess.h>
#include <argstream.h>
#include <modules/Materials.h>
#include <modules/Creatures.h>
vector<DFHack::t_matgloss> creaturestypes;
DFHack::memory_info *mem;
DFHack::Process *proc;
uint32_t creature_pregnancy_offset;
bool femaleonly = 0;
bool showcreatures = 0;
int maxpreg = 1000; // random start value, since its not required and im not sure how to set it to infinity
list<string> s_creatures;
using namespace DFHack;
int main ( int argc, char** argv )
{
vector<DFHack::t_creaturetype> creaturestypes;
DFHack::memory_info *mem;
DFHack::Process *proc;
uint32_t creature_pregnancy_offset;
//bool femaleonly = 0;
bool showcreatures = 0;
int maxpreg = 1000; // random start value, since its not required and im not sure how to set it to infinity
list<string> s_creatures;
// parse input, handle this nice and neat before we get to the connecting
argstream as(argc,argv);
as >>option('f',"female",femaleonly,"Impregnate females only")
as // >>option('f',"female",femaleonly,"Impregnate females only")
>>option('s',"show",showcreatures,"Show creature list (read only)")
>>parameter('m',"max",maxpreg,"The maximum limit of pregnancies ", false)
>>values<string>(back_inserter(s_creatures), "any number of creatures")
>>help();
// make the creature list unique
s_creatures.unique();
if (!as.isOk())
{
cout << as.errorLog();
@ -58,8 +64,9 @@ int main ( int argc, char** argv )
}
else if (s_creatures.size() == 0 && showcreatures != 1)
{
cout << as.usage();
return(1);
cout << as.usage() << endl << "---------------------------------------" << endl;
cout << "Creature list empty, assuming CATs" << endl;
s_creatures.push_back("CAT");
}
DFHack::API DF("Memory.xml");
@ -78,9 +85,11 @@ int main ( int argc, char** argv )
proc = DF.getProcess();
mem = DF.getMemoryInfo();
DFHack::Materials *Mats = DF.getMaterials();
DFHack::Creatures *Cre = DF.getCreatures();
creature_pregnancy_offset = mem->getOffset("creature_pregnancy");
if(!DF.ReadCreatureMatgloss(creaturestypes))
if(!Mats->ReadCreatureTypesEx(creaturestypes))
{
cerr << "Can't get the creature types." << endl;
#ifndef LINUX_BUILD
@ -90,7 +99,7 @@ int main ( int argc, char** argv )
}
uint32_t numCreatures;
if(!DF.InitReadCreatures(numCreatures))
if(!Cre->Start(numCreatures))
{
cerr << "Can't get creatures" << endl;
#ifndef LINUX_BUILD
@ -104,68 +113,62 @@ int main ( int argc, char** argv )
string sextype;
// shows all the creatures and returns.
if (showcreatures == 1)
int maxlength = 0;
map<string, vector <t_creature> > male_counts;
map<string, vector <t_creature> > female_counts;
// classify
for(uint32_t i =0;i < numCreatures;i++)
{
int maxlength = 0;
map<string,uint32_t> male_counts;
map<string,uint32_t> female_counts;
for(uint32_t i =0;i < numCreatures;i++)
DFHack::t_creature creature;
Cre->ReadCreature(i,creature);
DFHack::t_creaturetype & crt = creaturestypes[creature.race];
string castename = crt.castes[creature.sex].rawname;
if(castename == "FEMALE")
{
DFHack::t_creature creature;
DF.ReadCreature(i,creature);
if(creature.sex == 1){
male_counts[creaturestypes[creature.type].id]++;
female_counts[creaturestypes[creature.type].id]+=0; //auto initialize the females as well
}
else{
female_counts[creaturestypes[creature.type].id]++;
male_counts[creaturestypes[creature.type].id]+=0;
}
female_counts[creaturestypes[creature.race].rawname].push_back(creature);
male_counts[creaturestypes[creature.race].rawname].size();
}
cout << "Type\t\t\tMale #\tFemale #" << endl;
for(map<string, uint32_t>::iterator it1 = male_counts.begin();it1!=male_counts.end();it1++)
else // male, other, etc.
{
cout << it1->first << "\t\t" << it1->second << "\t" << female_counts[it1->first] << endl;
male_counts[creaturestypes[creature.race].rawname].push_back(creature);
female_counts[creaturestypes[creature.race].rawname].size(); //auto initialize the females as well
}
return(1);
}
for(uint32_t i = 0; i < numCreatures && totalchanged != maxpreg; i++)
// print (optional)
if (showcreatures == 1)
{
DFHack::t_creature creature;
DF.ReadCreature(i,creature);
if (showcreatures == 1)
cout << "Type\t\tMale #\tFemale #" << endl;
for(map<string, vector <t_creature> >::iterator it1 = male_counts.begin();it1!=male_counts.end();it1++)
{
if (creature.sex == 0) { sextype = "Female"; } else { sextype = "Male";}
cout << string(creaturestypes[creature.type].id) << ":" << sextype << "" << endl;
cout << it1->first << "\t\t" << it1->second.size() << "\t" << female_counts[it1->first].size() << endl;
}
else
}
// process
for (list<string>::iterator it = s_creatures.begin(); it != s_creatures.end(); ++it)
{
std::string clinput = *it;
std::transform(clinput.begin(), clinput.end(), clinput.begin(), ::toupper);
vector <t_creature> &females = female_counts[clinput];
uint32_t sz_fem = females.size();
totalcount += sz_fem;
for(uint32_t i = 0; i < sz_fem && totalchanged != maxpreg; i++)
{
s_creatures.unique();
for (list<string>::iterator it = s_creatures.begin(); it != s_creatures.end(); ++it)
t_creature & female = females[i];
uint32_t preg_timer = proc->readDWord(female.origin + creature_pregnancy_offset);
if(preg_timer != 0)
{
std::string clinput = *it;
std::transform(clinput.begin(), clinput.end(), clinput.begin(), ::toupper);
if(string(creaturestypes[creature.type].id) == clinput)
{
if((femaleonly == 1 && creature.sex == 0) || (femaleonly != 1))
{
proc->writeDWord(creature.origin + creature_pregnancy_offset, rand() % 100 + 1);
totalchanged+=1;
totalcount+=1;
}
else
{
totalcount+=1;
}
}
proc->writeDWord(female.origin + creature_pregnancy_offset, rand() % 100 + 1);
totalchanged++;
}
}
}
cout << totalchanged << " animals impregnated out of a possible " << totalcount << "." << endl;
DF.FinishReadCreatures();
cout << totalchanged << " pregnancies accelerated. Total creatures checked: " << totalcount << "." << endl;
Cre->Finish();
DF.Detach();
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;

@ -10,11 +10,11 @@
#include <cstdio>
using namespace std;
#include <DFGlobal.h>
#include <DFTypes.h>
#include <DFHackAPI.h>
#include <DFProcess.h>
#include <DFMemInfo.h>
#include <DFVector.h>
#include <DFTypes.h>
#include <modules/Materials.h>
#include <modules/Position.h>

@ -6,6 +6,7 @@
#include <vector>
using namespace std;
#include <DFGlobal.h>
#include <DFError.h>
#include <DFTypes.h>
#include <DFHackAPI.h>
@ -14,17 +15,8 @@ using namespace std;
#include <modules/Materials.h>
#include <modules/Creatures.h>
#include <modules/Translation.h>
#include "miscutils.h"
template <typename T>
void print_bits ( T val, std::ostream& out )
{
T n_bits = sizeof ( val ) * CHAR_BIT;
for ( unsigned i = 0; i < n_bits; ++i ) {
out<< !!( val & 1 ) << " ";
val >>= 1;
}
}
struct matGlosses
{
vector<DFHack::t_matglossPlant> plantMat;
@ -41,7 +33,7 @@ enum likeType
FOOD = 3
};
vector<DFHack::t_matgloss> creaturestypes;
vector<DFHack::t_creaturetype> creaturestypes;
matGlosses mat;
vector< vector <DFHack::t_itemType> > itemTypes;
DFHack::memory_info *mem;
@ -155,7 +147,13 @@ likeType printLike40d(DFHack::t_like like, const matGlosses & mat,const vector<
void printCreature(DFHack::API & DF, const DFHack::t_creature & creature)
{
cout << "address: " << hex << creature.origin << dec << " creature type: " << creaturestypes[creature.race].id << ", position: " << creature.x << "x " << creature.y << "y "<< creature.z << "z" << endl;
cout << "address: " << hex << creature.origin << dec << " creature type: " << creaturestypes[creature.race].rawname
<< "[" << creaturestypes[creature.race].tile_character
<< "," << creaturestypes[creature.race].tilecolor.fore
<< "," << creaturestypes[creature.race].tilecolor.back
<< "," << creaturestypes[creature.race].tilecolor.bright
<< "]"
<< ", position: " << creature.x << "x " << creature.y << "y "<< creature.z << "z" << endl;
bool addendl = false;
if(creature.name.first_name[0])
{
@ -177,6 +175,14 @@ void printCreature(DFHack::API & DF, const DFHack::t_creature & creature)
cout << ", trans name: " << transName;
addendl=true;
}
transName = Tran->TranslateName(creature.name,true);
if(!transName.empty())
{
cout << ", last name: " << transName;
addendl=true;
}
/*
cout << ", likes: ";
@ -240,46 +246,46 @@ void printCreature(DFHack::API & DF, const DFHack::t_creature & creature)
*/
cout << endl;
//skills
cout << "Skills" << endl;
for(unsigned int i = 0; i < creature.defaultSoul.numSkills;i++)
if(creature.has_default_soul)
{
if(i > 0)
//skills
cout << "Skills" << endl;
for(unsigned int i = 0; i < creature.defaultSoul.numSkills;i++)
{
cout << ", ";
if(i > 0)
{
cout << ", ";
}
cout << mem->getSkill(creature.defaultSoul.skills[i].id) << ": " << creature.defaultSoul.skills[i].rating;
}
cout << mem->getSkill(creature.defaultSoul.skills[i].id) << ": " << creature.defaultSoul.skills[i].rating;
}
cout << endl;
// labors
cout << "Labors" << endl;
for(unsigned int i = 0; i < NUM_CREATURE_LABORS;i++)
{
if(!creature.labors[i])
continue;
string laborname;
try
cout << endl;
cout << "Traits" << endl;
for(uint32_t i = 0; i < 30;i++)
{
laborname = mem->getLabor(i);
string trait = mem->getTrait (i, creature.defaultSoul.traits[i]);
if(!trait.empty()) cout << trait << ", ";
}
catch(exception &)
cout << endl;
// labors
cout << "Labors" << endl;
for(unsigned int i = 0; i < NUM_CREATURE_LABORS;i++)
{
break;
if(!creature.labors[i])
continue;
string laborname;
try
{
laborname = mem->getLabor(i);
}
catch(exception &)
{
break;
}
cout << laborname << ", ";
}
cout << laborname << ", ";
}
cout << endl;
cout << "Traits" << endl;
for(uint32_t i = 0; i < 30;i++)
{
string trait = mem->getTrait (i, creature.defaultSoul.traits[i]);
if(!trait.empty())
cout << trait << ", ";
cout << endl;
}
cout << endl;
/*
* FLAGS 1
*/
@ -341,17 +347,17 @@ void printCreature(DFHack::API & DF, const DFHack::t_creature & creature)
cout << "from the underworld, ";
}
cout << endl;
/*
if(creature.flags1.bits.had_mood && (creature.mood == -1 || creature.mood == 8 ) )
{
string artifact_name = DF.TranslateName(creature.artifact_name,englishWords,foreignWords,false);
string artifact_name = Tran->TranslateName(creature.artifact_name,false);
cout << "artifact: " << artifact_name << endl;
}*/
}
cout << endl;
}
int main (void)
int main (int numargs, char ** args)
{
DFHack::API DF("Memory.xml");
try
@ -366,6 +372,9 @@ int main (void)
#endif
return 1;
}
string check = "";
if(numargs == 2)
check = args[1];
DFHack::Creatures * Creatures = DF.getCreatures();
DFHack::Materials * Materials = DF.getMaterials();
@ -388,17 +397,10 @@ int main (void)
#endif
return 1;
}
/*
DF.ReadItemTypes(itemTypes);
DF.ReadPlantMatgloss(mat.plantMat);
DF.ReadWoodMatgloss(mat.woodMat);
DF.ReadStoneMatgloss(mat.stoneMat);
DF.ReadMetalMatgloss(mat.metalMat);
DF.ReadCreatureMatgloss(mat.creatureMat);
*/
mem = DF.getMemoryInfo();
// get stone matgloss mapping
if(!Materials->ReadCreatureTypes(creaturestypes))
if(!Materials->ReadCreatureTypesEx(creaturestypes))
{
cerr << "Can't get the creature types." << endl;
return 1;
@ -409,18 +411,21 @@ int main (void)
cerr << "Can't get name tables" << endl;
return 1;
}
vector<uint32_t> addrs;
//DF.InitViewAndCursor();
for(uint32_t i = 0; i < numCreatures; i++)
{
DFHack::t_creature temp;
Creatures->ReadCreature(i,temp);
if(string(creaturestypes[temp.race].id) == "DWARF")
if(check.empty() || string(creaturestypes[temp.race].rawname) == check)
{
cout << "index " << i << " ";
printCreature(DF,temp);
addrs.push_back(temp.origin);
}
}
interleave_hex(DF,addrs,200);
/*
uint32_t currentIdx;
DFHack::t_creature currentCreature;

@ -8,6 +8,7 @@
#include <ctime>
using namespace std;
#include <DFGlobal.h>
#include <DFTypes.h>
#include <DFHackAPI.h>
#include <DFProcess.h>
@ -56,13 +57,47 @@ int main (int numargs, const char ** args)
{
cout << i << ": " << matgloss[i].id << endl;
}
cout << endl << "----==== Creature types ====----" << endl;
vector<DFHack::t_matgloss> creature;
Materials->ReadCreatureTypes (matgloss);
cout << endl << "----==== Organic - trees ====----" << endl;
Materials->ReadWoodMaterials (matgloss);
for(uint32_t i = 0; i < matgloss.size();i++)
{
cout << i << ": " << matgloss[i].id << endl;
}
cout << endl << "----==== Organic - plants ====----" << endl;
Materials->ReadPlantMaterials (matgloss);
for(uint32_t i = 0; i < matgloss.size();i++)
{
cout << i << ": " << matgloss[i].id << endl;
}
cout << endl << "----==== Creature types ====----" << endl;
vector<DFHack::t_creaturetype> creature;
Materials->ReadCreatureTypesEx (creature);
for(uint32_t i = 0; i < creature.size();i++)
{
cout << i << ": " << creature[i].rawname << endl;
vector<DFHack::t_creaturecaste> & castes = creature[i].castes;
for(uint32_t j = 0; j < castes.size();j++)
{
cout << " ["
<< castes[j].rawname << ":"
<< castes[j].singular << ":"
<< castes[j].plural << ":"
<< castes[j].adjective << "] ";
cout << endl;
}
cout << endl;
}
cout << endl << "----==== Color descriptors ====----" << endl;
vector<DFHack::t_descriptor_color> colors;
Materials->ReadDescriptorColors(colors);
for(uint32_t i = 0; i < colors.size();i++)
{
cout << i << ": " << colors[i].id << " - " << colors[i].name << "["
<< (unsigned int) (colors[i].r*255) << ":"
<< (unsigned int) (colors[i].v*255) << ":"
<< (unsigned int) (colors[i].b*255) << ":"
<< "]" << endl;
}
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();

@ -10,15 +10,17 @@
#include <cstdio>
using namespace std;
#include <DFProcess.h>
#include <DFMemInfo.h>
#include <DFVector.h>
void DumpObjStr0Vector (const char * name, DFHack::Process *p, uint32_t addr)
{
cout << "----==== " << name << " ====----" << endl;
DFHack::DfVector vect(p,addr,4);
for(uint32_t i = 0; i < vect.getSize();i++)
DFHack::DfVector <uint32_t> vect(p,addr);
for(uint32_t i = 0; i < vect.size();i++)
{
uint32_t addr = *(uint32_t *) vect[i];
uint32_t addr = vect[i];
cout << p->readSTLString(addr) << endl;
}
cout << endl;
@ -26,10 +28,10 @@ void DumpObjStr0Vector (const char * name, DFHack::Process *p, uint32_t addr)
void DumpObjVtables (const char * name, DFHack::Process *p, uint32_t addr)
{
cout << "----==== " << name << " ====----" << endl;
DFHack::DfVector vect(p,addr,4);
for(uint32_t i = 0; i < vect.getSize();i++)
DFHack::DfVector <uint32_t> vect(p,addr);
for(uint32_t i = 0; i < vect.size();i++)
{
uint32_t addr = *(uint32_t *) vect[i];
uint32_t addr = vect[i];
uint32_t vptr = p->readDWord(addr);
cout << p->readClassName(vptr) << endl;
}
@ -38,10 +40,10 @@ void DumpObjVtables (const char * name, DFHack::Process *p, uint32_t addr)
void DumpDWordVector (const char * name, DFHack::Process *p, uint32_t addr)
{
cout << "----==== " << name << " ====----" << endl;
DFHack::DfVector vect(p,addr,4);
for(uint32_t i = 0; i < vect.getSize();i++)
DFHack::DfVector <uint32_t> vect(p,addr);
for(uint32_t i = 0; i < vect.size();i++)
{
uint32_t number = *(uint32_t *) vect[i];
uint32_t number = vect[i];
cout << number << endl;
}
cout << endl;

@ -10,6 +10,7 @@
#include <cstdio>
using namespace std;
#include <DFGlobal.h>
#include <DFTypes.h>
#include <DFHackAPI.h>
#include <DFProcess.h>

@ -27,7 +27,6 @@ int main (void)
#endif
return 1;
}
cout << "Attached, DF should be suspended now" << endl;
getline(cin, blah);

@ -10,6 +10,7 @@
#include <cstdio>
using namespace std;
#include <DFGlobal.h>
#include <DFTypes.h>
#include <DFHackAPI.h>
#include <DFProcess.h>

@ -10,6 +10,7 @@
#include <cstdio>
using namespace std;
#include <DFGlobal.h>
#include <DFTypes.h>
#include <DFHackAPI.h>
#include <DFProcess.h>
@ -21,9 +22,76 @@ using namespace std;
#include <modules/Maps.h>
#include <modules/Constructions.h>
#include "miscutils.h"
#include <DFTileTypes.h>
using namespace DFHack;
/*
int __userpurge get_feature_at<eax>(__int16 tZ<ax>, __int16 tY<cx>, int world_base<ebx>, signed __int16 tX)
{
int block; // ebp@1
signed __int16 __tX; // di@1
signed int _tY; // esi@1
int designation; // eax@2
int _tX; // ecx@2
signed int v9; // eax@4
int v10; // edx@4
__int64 region_x_local; // qax@4
__int16 v12; // cx@4
__int16 v13; // ax@5
int v14; // esi@5
int result; // eax@7
unsigned int some_stuff; // ebp@10
int v17; // edx@11
int _designation; // [sp+10h] [bp+4h]@2
__tX = tX;
LOWORD(_tY) = tY;
block = getBlock(world_base, tX, tY, tZ);
if ( !block )
goto LABEL_17;
_tX = tX;
_tY = (signed __int16)_tY;
designation = *(_DWORD *)(block + 0x29C + 4 * ((signed __int16)_tY % 16 + 16 * tX % 16));
_designation = designation;
if ( designation & 0x10000000 && *(_WORD *)(block + 0x2C) != -1 )// first feature_present bit - adamantine
{
region_x_local = __tX / 48 + *(_DWORD *)(world_base + 0x525C8);// tile_x / 48 + region_x
v12 = ((BYTE4(region_x_local) & 0xF) + (_DWORD)region_x_local) >> 4;
WORD2(region_x_local) = (_tY / 48 + *(_DWORD *)(world_base + 0x525CC)) / 16;// tile_y / 48 + region_y
v9 = v12;
_tX = SWORD2(region_x_local);
v10 = *(_DWORD *)(*(_DWORD *)(*(_DWORD *)(world_base + 0x54440) + 4 * (v9 >> 4))
+ 16 * (SWORD2(region_x_local) >> 4)
+ 4);
if ( v10 )
{
_tX %= 16;
v14 = v10 + 24 * ((signed __int16)_tX + 16 * v9 % 16);
v13 = *(_WORD *)(block + 0x2C);
if ( v13 >= 0 )
{
_tX = (*(_DWORD *)(v14 + 16) - *(_DWORD *)(v14 + 12)) >> 2;
if ( v13 < (unsigned int)_tX )
return *(_DWORD *)sub_519100(_tX, v10);
}
}
designation = _designation;
}
if ( designation & 0x20000000 && (some_stuff = *(_DWORD *)(block + 0x30), some_stuff != -1) )// second feature_present bit - slade and hell
{
v17 = (*(_DWORD *)(world_base + 0x54384) - *(_DWORD *)(world_base + 0x54380)) >> 2;
if ( some_stuff >= v17 )
_invalid_parameter_noinfo(_tX, v17);
result = *(_DWORD *)(*(_DWORD *)(*(_DWORD *)(world_base + 0x54380) + 4 * some_stuff) + 0x100);
}
else
{
LABEL_17:
result = 0;
}
return result;
}
*/
int main (int numargs, const char ** args)
{
DFHack::API DF("Memory.xml");
@ -39,46 +107,127 @@ int main (int numargs, const char ** args)
#endif
return 1;
}
/*
DFHack::Position *Pos = DF.getPosition();
DFHack::Position *Pos = DF.getPosition();
DFHack::memory_info* mem = DF.getMemoryInfo();
DFHack::Maps *Maps = DF.getMaps();
DFHack::Process * p = DF.getProcess();
uint32_t designatus = mem->getOffset("map_data_designation");
uint32_t block_feature1 = mem->getOffset("map_data_feature1");
uint32_t block_feature2 = mem->getOffset("map_data_feature2");
uint32_t region_x_offset = mem->getAddress("region_x");
uint32_t region_y_offset = mem->getAddress("region_y");
uint32_t region_z_offset = mem->getAddress("region_z");
uint32_t feature1_start_ptr = mem->getAddress("feature1_start_ptr");
uint32_t regionX, regionY, regionZ;
// read position of the region inside DF world
p->readDWord (region_x_offset, regionX);
p->readDWord (region_y_offset, regionY);
p->readDWord (region_z_offset, regionZ);
Maps->Start();
int32_t cx, cy, cz;
Pos->getCursorCoords(cx,cy,cz);
if(cx != -30000)
int32_t cursorX, cursorY, cursorZ;
Pos->getCursorCoords(cursorX,cursorY,cursorZ);
if(cursorX != -30000)
{
uint32_t bx = cx / 16;
uint32_t tx = cx % 16;
uint32_t by = cy / 16;
uint32_t ty = cy % 16;
uint32_t blockX = cursorX / 16;
uint32_t tileX = cursorX % 16;
uint32_t blockY = cursorY / 16;
uint32_t tileY = cursorY % 16;
mapblock40d block;
if(Maps->ReadBlock40d(bx,by,cz,&block))
{
int16_t tiletype = block.tiletypes[tx][ty];
cout << tiletype << endl;
}
}
*/
vector <string> classIdStrings;
DFHack::memory_info * minfo = DF.getMemoryInfo();
if(!minfo)
{
cerr <<"FAIL!" << endl;
return 1;
}
for(int i = 0; ; i++)
{
string temp;
if(!minfo->resolveClassIDToClassname(i, temp))
if(Maps->ReadBlock40d(blockX,blockY,cursorZ,&block))
{
break;
printf("block addr: 0x%x\n", block.origin);
int16_t tiletype = block.tiletypes[tileX][tileY];
naked_designation &des = block.designation[tileX][tileY].bits;
uint32_t &desw = block.designation[tileX][tileY].whole;
print_bits<uint32_t>(block.designation[tileX][tileY].whole,cout);
cout << endl;
print_bits<uint32_t>(block.occupancy[tileX][tileY].whole,cout);
cout << endl;
// tiletype
cout <<"tiletype: " << tiletype;
if(tileTypeTable[tiletype].name)
cout << " = " << tileTypeTable[tiletype].name;
cout << endl;
// features present
if(des.feature_type_1)
{
cout << "feature type 1 present: " << p->readDWord(block.origin + block_feature1) << endl;
int32_t idx = p->readDWord(block.origin + block_feature1);
if(idx != -1)
{
uint64_t bigblock_x = cursorX / 48 + regionX;
// blah, dumb disassembly. too tired to think
uint16_t v12 = ((bigblock_x % 16) + bigblock_x) / 16;
uint64_t region_y_local = (cursorY / 48 + regionY) / 16;
// deref pointer to the humongo-structure
uint32_t base = p->readDWord(feature1_start_ptr);
// this is just a few pointers to arrays of 16B (4 DWORD) structs
uint32_t array_elem = p->readDWord(base + (v12 / 16) * 4);
// second element of the struct is a pointer
uint32_t wtf = p->readDWord(array_elem + (16*(region_y_local/16)) + 4); // rounding!
if(wtf)
{
uint32_t feat_vector = wtf + 24 * (region_y_local % 16);
DfVector<uint32_t> p_features(p, feat_vector);
printf("feature addr: 0x%x\n", p_features[idx]);
string name = p->readClassName(p->readDWord( p_features[idx] ));
cout << name << endl;
}
}
}
if(des.feature_type_2)
{
int32_t idx = p->readDWord(block.origin + block_feature2);
cout << "feature type 2 present: " << idx << endl;
if(idx != -1)
{
DfVector<uint32_t> p_features (p,mem->getAddress("feature2_vector"));
if(idx < p_features.size())
{
uint32_t feat_ptr = p->readDWord(p_features[idx] + mem->getOffset("feature2_funcptr_"));
printf("feature descriptor?: 0x%x\n", feat_ptr);
string name = p->readClassName(p->readDWord( feat_ptr));
cout << name << endl;
}
}
}
// biome, geolayer
cout << "biome: " << des.biome << endl;
cout << "geolayer: " << des.geolayer_index << endl;
// liquids
if(des.flow_size)
{
if(des.liquid_type == DFHack::liquid_magma)
cout <<"magma: ";
else cout <<"water: ";
cout << des.flow_size << endl;
}
if(des.flow_forbid)
cout << "flow forbid" << endl;
if(des.pile)
cout << "stockpile?" << endl;
if(des.rained)
cout << "rained?" << endl;
if(des.smooth)
cout << "smooth?" << endl;
uint32_t designato = block.origin + designatus + (tileX * 16 + tileY) * sizeof(t_designation);
printf("designation offset: 0x%x\n", designato);
/*
block.designation[tx][ty].bits.moss = 1;
block.designation[tx][ty].bits.geolayer_index = 15;
block.tiletypes[tx][ty] = 344;
print_bits<uint32_t>(block.designation[tx][ty].whole,cout);
Maps->WriteDesignations(bx,by,cz,&(block.designation));
Maps->WriteTileTypes(bx,by,cz,&(block.tiletypes));
*/
}
classIdStrings.push_back(temp);
}
for (int i = 0; i < classIdStrings.size(); i++)
cout << i << ": " << classIdStrings[i] << endl;
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();

@ -14,7 +14,9 @@ using namespace std;
#include <stdlib.h>
#include <signal.h>
#include <locale.h>
#include <math.h>
#include <DFGlobal.h>
#include <DFTypes.h>
#include <DFTileTypes.h>
#include <DFHackAPI.h>
@ -30,6 +32,22 @@ string error;
API * pDF = 0;
struct t_tempz
{
int32_t limit;
int character;
};
t_tempz temp_limits[]=
{
{50, '.'},
{100, '+'},
{500, '*'},
{1000, '#'},
{2000, '!'}
};
#define NUM_LIMITS 5
static void finish(int sig);
int gotoxy(int x, int y)
@ -315,6 +333,8 @@ main(int argc, char *argv[])
vector<t_vein> veinVector;
vector<t_frozenliquidvein> IceVeinVector;
vector<t_spattervein> splatter;
t_temperatures b_temp1;
t_temperatures b_temp2;
DFHack::Materials * Mats = 0;
DFHack::Maps * Maps = 0;
@ -392,6 +412,13 @@ main(int argc, char *argv[])
uint32_t blockaddr2 = 0;
t_blockflags bflags;
bflags.whole = 0;
enum e_tempmode
{
TEMP_NO,
TEMP_1,
TEMP_2
};
e_tempmode temperature = TEMP_NO;
// resume so we don't block DF while we wait for input
DF.Resume();
@ -451,6 +478,15 @@ main(int argc, char *argv[])
case 't':
dotwiddle = true;
break;
case 'b':
temperature = TEMP_NO;
break;
case 'n':
temperature = TEMP_1;
break;
case 'm':
temperature = TEMP_2;
break;
default:
break;
}
@ -520,6 +556,9 @@ main(int argc, char *argv[])
}
Maps->WriteDesignations(cursorX+i,cursorY+j,cursorZ, &(Block->designation));
}
// read temperature data
Maps->ReadTemperatures(cursorX+i,cursorY+j,cursorZ,&b_temp1, &b_temp2 );
if(dotwiddle)
{
bitset<32> bs = Block->designation[0][0].whole;
@ -528,6 +567,7 @@ main(int argc, char *argv[])
Maps->WriteDesignations(cursorX+i,cursorY+j,cursorZ, &(Block->designation));
dotwiddle = false;
}
// do a dump of the block data
if(dump)
{
@ -588,11 +628,11 @@ main(int argc, char *argv[])
}
*/
}
gotoxy(0,48);
gotoxy(50,0);
cprintf("arrow keys, PGUP, PGDN = navigate");
gotoxy(0,49);
gotoxy(50,1);
cprintf("+,- = switch vein");
gotoxy(0,50);
gotoxy(50,2);
uint32_t mineralsize = veinVector.size();
uint32_t icesize = IceVeinVector.size();
uint32_t splattersize = splatter.size();
@ -630,7 +670,7 @@ main(int argc, char *argv[])
}
}
}
gotoxy(0,51);
gotoxy(50,3);
cprintf("Mineral: %s",stonetypes[veinVector[vein].type].id);
}
else if (vein < mineralsize + icesize)
@ -650,7 +690,7 @@ main(int argc, char *argv[])
attroff(A_STANDOUT);
}
}
gotoxy(0,51);
gotoxy(50,3);
cprintf("ICE");
}
else
@ -670,25 +710,78 @@ main(int argc, char *argv[])
}
}
}
gotoxy(0,51);
gotoxy(50,3);
cprintf("Spatter: %s",PrintSplatterType(splatter[realvein].mat1,splatter[realvein].mat2,creature_types).c_str());
}
}
}
mapblock40d * Block = &blocks[1][1];
for(int x = 0; x < 16; x++) for(int y = 0; y < 16; y++)
t_temperatures * ourtemp;
if(temperature == TEMP_NO)
{
if((Block->occupancy[x][y].whole & (1 << twiddle)))
for(int x = 0; x < 16; x++) for(int y = 0; y < 16; y++)
{
putch(x + 16,y + 16,'@',COLOR_WHITE);
if((Block->occupancy[x][y].whole & (1 << twiddle)))
{
putch(x + 16,y + 16,'@',COLOR_WHITE);
}
}
}
else
{
if(temperature == TEMP_1)
ourtemp = &b_temp1;
else if(temperature == TEMP_2)
ourtemp = &b_temp2;
uint64_t sum = 0;
uint16_t min, max;
min = max = (*ourtemp)[0][0];
for(int x = 0; x < 16; x++) for(int y = 0; y < 16; y++)
{
uint16_t temp = (*ourtemp)[x][y];
if(temp < min) min = temp;
if(temp > max) max = temp;
sum += temp;
}
uint64_t average = sum/256;
gotoxy (50,8);
if(temperature == TEMP_1)
cprintf ("temperature1 [°U] (min,avg,max): %d,%d,%d", min, average, max);
else if(temperature == TEMP_2)
cprintf ("temperature2 [°U] (min,avg,max): %d,%d,%d", min, average, max);
for(int x = 0; x < 16; x++) for(int y = 0; y < 16; y++)
{
int32_t temper = (int32_t) (*ourtemp)[x][y];
temper -= average;
uint32_t abs_temp = abs(temper);
int color;
unsigned char character = ' ';
if(temper >= 0)
color = COLOR_RED;
else
color = COLOR_BLUE;
for(int i = 0; i < NUM_LIMITS; i++)
{
if(temp_limits[i].limit < abs_temp)
character = temp_limits[i].character;
else break;
}
if( character != ' ')
{
putch(x + 16,y + 16,character,color);
}
}
}
gotoxy (0,52);
gotoxy (50,4);
cprintf("block address 0x%x, flags 0x%08x",blockaddr, bflags.whole);
gotoxy (0,53);
gotoxy (50,5);
cprintf("dirty bit: %d, twiddle: %d",dirtybit,twiddle);
gotoxy (0,54);
gotoxy (50,6);
cprintf ("d - dig veins, o - dump map block, z - toggle dirty bit");
gotoxy (50,7);
cprintf ("b - no temperature, n - temperature 1, m - temperature 2");
wrefresh(stdscr);
}
pDF = 0;

@ -920,6 +920,7 @@ size=212
<class name="building_asheryst" type="0x14"/>
<class name="building_dyers_shopst" type="0x15"/>
<class name="building_millstonest" type="0x16"/>
<class name="building_custom_workshop" type="0x17" />
</multiclass>
<multiclass name="building_furnacest" typeoffset="0x152">
<class name="building_wood_furnacest" type="0x0"/>
@ -1052,11 +1053,23 @@ size=212
Map stuff
=========
<Address name="map_data">0x016AD718</Address>
<Offset name="v_vein">0x08</Offset>
<Offset name="type">0x009A</Offset>
<Offset name="designation">0x029C</Offset>
<Offset name="occupancy">0x069c</Offset>
<Offset name="biome_stuffs">0x1D9C</Offset>
<Offset name="map_data_vein_vector">0x08</Offset>
<Offset name="map_data_type">0x009A</Offset>
<Offset name="map_data_designation">0x029C</Offset>
<Offset name="map_data_occupancy">0x069c</Offset>
<Offset name="map_data_temperature1_offset">0x159c</Offset>
<Offset name="map_data_temperature2_offset">0x179c</Offset>
<Offset name="map_data_biome_stuffs">0x1D9C</Offset>
<Offset name="map_data_pathfinding_offset">0x0D9c</Offset>
<Offset name="map_data_feature1">0x2C</Offset> adamantine?
<Offset name="map_data_feature2">0x30</Offset> hell?
WORLD + 0x54374
<Address name="feature2_vector">0x16AF4FC</Address>
<Offset name= "feature2_funcptr_">0x100</Offset>
WORLD + 0x54440
<Address name="feature1_start_ptr">0x16AF5C8</Address>
<!--
map_data_map_x_offset 0x0058
map_data_map_y_offset 0x005A
@ -1084,8 +1097,11 @@ map_data_1b60_offset 0x1B9c
<Address name="z_count">0x016ad74C</Address>
* Suspected region coords *
WORLD + 0x525C8
<Address name="region_x">0x016ad750</Address>
WORLD + 0x525CC
<Address name="region_y">0x016ad754</Address>
WORLD + 0x525D0
<Address name="region_z">0x016ad758</Address>
* World size * (WORDs)
@ -1120,6 +1136,7 @@ map_data_1b60_offset 0x1B9c
=========
<Address name="creature_vector">0x0166ecc4</Address>
<Address name="dwarf_race_index">0x01470fbc</Address>
<Address name="dwarf_civ_id">0x01470fb0</Address>
<Offset name="creature_name">0x0</Offset>
<Offset name="creature_custom_profession">0x6c</Offset>
@ -1130,10 +1147,14 @@ map_data_1b60_offset 0x1B9c
<Offset name="creature_flags2">0xFC</Offset>
<Offset name="creature_sex">0x110</Offset>
<Offset name="creature_id">0x114</Offset>
<Offset name="creature_side">0X120</Offset> <!-- what? -->
<Offset name="creature_civ">0X120</Offset>
<Offset name="creature_soulskill_vector">0X1F4</Offset>
<Offset name="creature_pickup_equipment_bit">0X21C</Offset>
<Offset name="creature_mood">0x238</Offset>
<Offset name="creature_pregnancy">0x28C</Offset>
<Offset name="creature_pregnancy_ptr">0x290</Offset>
<Offset name="creature_physical">0x464</Offset>
<!--
<Offset name="creature_strength">0x464</Offset>
@ -1175,68 +1196,90 @@ map_data_1b60_offset 0x1B9c
Materials
=========
<!-- Number vectors are vector <uint32_t> -->
<!-- Others are vector<object *> -->
<!-- first member of 'object' is a STL string with the name of said object -->
this is an array of 4B pointers to material templates and length 0x292
base_type_array = WORLD + 0x5DF44
<Address name="base_type_array">0x016b90cc</Address>
<Address name="mat_templates">0x16afcec</Address>
<!-- soil, stone, metal -->
soil, stone, metal
inorganics vector = WORLD + 0x54B7C = 0x16AFD04
<Address name="mat_inorganics">0x16afd04</Address>
<Offset name="inorganic_material_template_instantiation">0x178</Offset>
<!-- wood and plant matter -->
wood and plant matter, WORLD + 0x54B94
<Address name="mat_organics_all">0x16afd1C</Address>
<!-- plant matter -->
plant matter, WORLD + 0x54BAC
<Address name="mat_organics_plants">0x16afd34</Address>
<!-- maybe maps beween organics_all and organics_plants -->
just wood, WORLD + 0x54BDC
<Address name="mat_organics_trees">0x16afd64</Address>
creature types actually used for creatures,
WORLD + 0x54CD0
<Address name="creature_type_vector">0x016AFE58</Address>
<Offset name="creature_type_caste_vector">0x138</Offset>
<Offset name="creature_tile">0xE0</Offset>
<Offset name="creature_tile_color">0xF6</Offset>
<!--
NOT used yet
Number vectors are vector <uint32_t>
Others are vector<object *>
first member of 'object' is a STL string with the name of said object
<Offset name="inorganic_material_template_instantiation">0x178</Offset>
this is an array of 4B pointers to material templates and length 0x292
base_type_array = WORLD + 0x5DF44
<Address name="base_type_array">0x016b90cc</Address>
<Address name="mat_templates">0x16afcec</Address>
maybe maps beween organics_all and organics_plants
<Address name="mat_unk1_numbers">0x16afd4C</Address>
<!-- wood -->
<Address name="mat_organics_trees">0x16afd64</Address>
<!-- maybe maps beween organics_all and organics_trees -->
maybe maps beween organics_all and organics_trees
<Address name="mat_unk2_numbers">0x16afd7C</Address>
<!-- body material stuff -->
body material stuff
<Address name="mat_body_material_templates">0x16AFD94</Address>
<Address name="mat_body_detail_plans">0x16AFDAC</Address>
<Address name="mat_bodies">0x16AFDC4</Address>
<Address name="mat_bodygloss">0x16AFDDC</Address>
<Address name="mat_creature_variations">0x16AFDF4</Address>
<!-- *raw* creature types -->
*raw* creature types
<Address name="mat_creature_types">0x16AFE0C</Address>
<!-- creature types actually used for creatures? -->
<Address name="creature_type_vector">0x016AFE58</Address>
<!--<Address name="mat_creature_types2">0x16AEE08</Address>-->
-->
Constructions
=============
WORLD + 0x108
<Address name="construction_vector">0x165b290</Address>
<Offset name="sizeof_construction">0x14</Offset>
Translations
============
WORLD + 0x54E50
<Address name="language_vector">0x016AFFD8</Address>
WORLD + 0x54E80
<Address name="translation_vector">0x016B0008</Address>
<Offset name="word_table">0x4C</Offset>
Vegetation
==========
WORLD + 0x15184
<Address name="vegetation_vector">0x0167030C</Address> belal: 0x017f6d98 ... what?
<Offset name="tree_desc_offset">0x6C</Offset>
Buildings
=========
WORLD + 0x14818
<Address name="buildings_vector">0x0166f9a0</Address>
<Offset name="building_custom_workshop_type">0x164</Offset>
WORLD + 0x5D610
<Address name="custom_workshop_vector">0x016B8798</Address>
<Offset name="custom_workshop_name">0x4</Offset>
<Offset name="custom_workshop_type">0x20</Offset>
Effects
=======
@ -1291,6 +1334,141 @@ map_data_1b60_offset 0x1B9c
<Entry version="v0.31.02" os="windows" id="0.31.02" base="0.31.01">
<String name="md5">23dfe141c7ea4e63ebb3c618a12b48ec</String>
<HexValue name="pe_timestamp">0x4BBDF378</HexValue>
</Entry>
<Entry version="v0.31.03" os="windows" id="0.31.03" base="0.31.01" rebase="0x1000">
<String name="md5">94641d97a0ecff6f2194e3d0b310d946</String>
<HexValue name="pe_timestamp">0x4BC3C470</HexValue>
WORLD: 0x0165c1d0 ?
Position
========
<Address name="window_dims">0x17f6b00</Address> Was 0x17f5ab8
0x17f6b00
0x17f6b08
0x17f6b10
Map
===
<Address name="map_data">0x016AE760</Address>
* map size in blocks *
<Address name="x_count_block">0x016AE780</Address>
<Address name="y_count_block">0x016AE784</Address>
<Address name="z_count_block">0x016AE788</Address>
* map size in tiles *
<Address name="x_count">0x016AE78C</Address>
<Address name="y_count">0x016AE790</Address>
<Address name="z_count">0x016AE794</Address>
* Suspected region coords *
<Address name="region_x">0x016AE798</Address>
<Address name="region_y">0x016AE79C</Address>
<Address name="region_z">0x016AE7A0</Address>
* World size * (WORDs)
<Address name="world_size_x">0x016AFE1C</Address>
<Address name="world_size_y">0x016AFE1E</Address>
* geology *
<Address name="geoblock_vector">0x16B0574</Address>
<Address name="ptr2_region_array">0x16B05BC</Address>
* features *
WORLD + 0x54374
<Address name="feature2_vector">0x16B0544</Address>
<Address name="feature1_start_ptr">0x16B0610</Address>
Creatures
=========
<Address name="creature_vector">0x166FD0C</Address>
<Address name="dwarf_race_index">0x01471fbc</Address>
<Offset name="creature_name">0x0</Offset>
<Offset name="creature_custom_profession">0x6c</Offset>
<Offset name="creature_profession">0x88</Offset>
<Offset name="creature_race">0x8C</Offset>
<Offset name="creature_position">0x90</Offset>
<Offset name="creature_flags1">0xF8</Offset>
<Offset name="creature_flags2">0xFC</Offset>
<Offset name="creature_sex">0x110</Offset>
<Offset name="creature_id">0x114</Offset>
<Offset name="creature_civ">0X120</Offset>
<Offset name="creature_soulskill_vector">0X1F4</Offset>
<Offset name="creature_pickup_equipment_bit">0X21C</Offset>
<!--<Offset name="creature_mood">0x238</Offset>-->
<Offset name="creature_physical">0x464</Offset>
<!--
<Offset name="creature_strength">0x464</Offset>
<Offset name="creature_agility">0x480</Offset>
<Offset name="creature_toughness">0x49C</Offset>
<Offset name="creature_endurance">0x4B8</Offset>
<Offset name="creature_recuperation">0x4D4</Offset>
<Offset name="creature_disease_resistance">0x4F0</Offset>
-->
<Offset name="creature_current_job">0x390</Offset> <!-- from chmod -->
<Offset name="creature_artifact_name">0x6D4</Offset>
<Offset name="creature_labors">0x774</Offset>
<Offset name="creature_soul_vector">0x0740</Offset>
<Offset name="creature_default_soul">0x0758</Offset>
<Offset name="creature_happiness">0x834</Offset>
Materials
=========
soil, stone, metal
inorganics vector = WORLD + 0x54B7C = 0x16B0D4C
<Address name="mat_inorganics">0x16B0D4C</Address>
wood and plant matter, WORLD + 0x54B94
<Address name="mat_organics_all">0x16B0D64</Address>
plant matter, WORLD + 0x54BAC
<Address name="mat_organics_plants">0x16B0D7C</Address>
just wood, WORLD + 0x54BDC
<Address name="mat_organics_trees">0x16B0DAC</Address>
creature types actually used for creatures, WORLD + 0x54CD0
<Address name="creature_type_vector">0x16B0EA0</Address>
Constructions
=============
WORLD + 0x108
<Address name="construction_vector">0x165C2D8</Address>
Translations
============
WORLD + 0x54E50
<Address name="language_vector">0x016B1020</Address>
WORLD + 0x54E80
<Address name="translation_vector">0x16B1050</Address>
Vegetation
==========
WORLD + 0x15184
<Address name="vegetation_vector">0x1671354</Address>
Buildings
=========
WORLD + 0x14818
<Address name="buildings_vector">0x16709E8</Address>
WORLD + 0x5D610
<Address name="custom_workshop_vector">0x16B97E0</Address>
<Offset name="custom_workshop_name">0x4</Offset>
<Offset name="custom_workshop_type">0x20</Offset>
Descriptor colors
=================
<Address name="descriptor_shape_vector">0x16B9780</Address>
<Offset name="descriptor_rawname">0x0</Offset>
<Offset name="descriptor_name">0x4C</Offset>
<Address name="descriptor_colors_vector">0x16B9768</Address>
<Offset name="descriptor_color_r">0x6C</Offset> floats !
<Offset name="descriptor_color_v">0x70</Offset>
<Offset name="descriptor_color_b">0x74</Offset>
</Entry>
.-"""-.
' \

@ -0,0 +1 @@
dfvdig.exe -x

@ -50,8 +50,8 @@ TARGET_LINK_LIBRARIES(dfdigger dfhack)
# a magma creation tool
# Author: Aleric
ADD_EXECUTABLE(dfmagma_create magma_create.cpp)
TARGET_LINK_LIBRARIES(dfmagma_create dfhack)
ADD_EXECUTABLE(dfliquids liquids.cpp)
TARGET_LINK_LIBRARIES(dfliquids dfhack)
IF(UNIX)
install(TARGETS

@ -60,7 +60,7 @@ int main (void)
for(uint32_t i = 0; i < splatter.size(); i++)
{
DFHack::t_spattervein & vein = splatter[i];
if(vein.mat1 > 19)
if(vein.mat1 != 0xC)
{
uint32_t addr = vein.address_of;
uint32_t offset = offsetof(DFHack::t_spattervein, intensity);

@ -31,7 +31,7 @@ int main ()
{
DFHack::Process *proc;
DFHack::memory_info *meminfo;
DFHack::DfVector *items_vector;
DFHack::DfVector <uint32_t> *items_vector;
DFHack::t_item_df40d item_40d;
DFHack::t_matglossPair item_40d_material;
vector<DFHack::t_matgloss> stoneMat;
@ -105,11 +105,11 @@ int main ()
return EXIT_FAILURE;
}
items_vector = new DFHack::DfVector (proc, items, 4);
for(uint32_t i = 0; i < items_vector->getSize(); i++)
items_vector = new DFHack::DfVector <uint32_t> (proc, items);
for(uint32_t i = 0; i < items_vector->size(); i++)
{
// get pointer to object
temp = * (uint32_t *) items_vector->at (i);
temp = items_vector->at (i);
// read object
proc->read (temp, sizeof (DFHack::t_item_df40d), (uint8_t *) &item_40d);

@ -0,0 +1,252 @@
// This will create 7 deep magama on the square the cursor is on. It does not
// enable magma buildings at this time.
#include <iostream>
#include <integers.h>
#include <vector>
using namespace std;
#include <DFTypes.h>
#include <DFHackAPI.h>
#include <modules/Maps.h>
#include <modules/Position.h>
#include <DFTileTypes.h>
int main (void)
{
int32_t x,y,z;
DFHack::designations40d designations;
DFHack::tiletypes40d tiles;
DFHack::t_temperatures temp1,temp2;
uint32_t x_max,y_max,z_max;
DFHack::API DF("Memory.xml");
DFHack::Maps * Maps;
DFHack::Position * Position;
try
{
DF.Attach();
Maps = DF.getMaps();
Position = DF.getPosition();
}
catch (exception& e)
{
cerr << e.what() << endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
return 1;
}
bool end = false;
cout << "Welcome to the liquid spawner. type 'help' for a list of available commands, 'q' to quit." << endl;
string mode="magma";
string brush="point";
string flowmode="f+";
int amount = 7;
while(!end)
{
Maps->getSize(x_max,y_max,z_max);
DF.Resume();
string command = "";
cout <<"[" << mode << ":" << amount << ":" << flowmode << "]# ";
getline(cin, command);
if(command=="help")
{
cout << "Modes:" << endl
<< "m - switch to magma" << endl
<< "w - switch to water" << endl
<< "o - make obsidian wall instead" << endl
<< "f - flow bits only" << endl
<< "Properties:" << endl
<< "f+ - make the spawned liquid flow" << endl
<< "f. - don't change flow state (read state in flow mode)" << endl
<< "f- - make the spawned liquid static" << endl
<< "0-7 - set liquid amount" << endl
<< "Brush:" << endl
<< "point - single tile" << endl
<< "block - block with cursor in it" << endl
<< "Other:" << endl
<< "q - quit" << endl
<< "help - print this list of commands" << endl
<< "empty line - put liquid" << endl
<< endl
<< "Usage: point the DF cursor at a tile you want to modify" << endl
<< "and use the commands available :)" << endl;
}
else if(command == "m")
{
mode = "magma";
}
else if(command == "o")
{
mode = "obsidian";
}
else if(command == "clmn")
{
mode = "column";
}
else if(command == "w")
{
mode = "water";
}
else if(command == "f")
{
mode = "flowbits";
}
else if(command == "point")
{
brush = "point";
}
else if(command == "block")
{
brush = "block";
}
else if(command == "q")
{
end = true;
}
else if(command == "f+")
{
flowmode = "f+";
}
else if(command == "f-")
{
flowmode = "f-";
}
else if(command == "f.")
{
flowmode = "f.";
}
// blah blah, bad code, bite me.
else if(command == "0")
amount = 0;
else if(command == "1")
amount = 1;
else if(command == "2")
amount = 2;
else if(command == "3")
amount = 3;
else if(command == "4")
amount = 4;
else if(command == "5")
amount = 5;
else if(command == "6")
amount = 6;
else if(command == "7")
amount = 7;
else if(command.empty())
{
DF.Suspend();
do
{
if(!Maps->Start())
{
cout << "Can't see any DF map loaded." << endl;
break;
}
if(!Position->getCursorCoords(x,y,z))
{
cout << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl;
break;
}
cout << "cursor coords: " << x << "/" << y << "/" << z << endl;
if(!Maps->isValidBlock(x/16,y/16,z))
{
cout << "Not a valid block." << endl;
break;
}
if(mode == "obsidian")
{
Maps->ReadTileTypes((x/16),(y/16),z, &tiles);
tiles[x%16][y%16] = 331;
Maps->WriteTileTypes((x/16),(y/16),z, &tiles);
}
else if(mode == "column")
{
int zzz = z;
int16_t tile;
while ( zzz < z_max )
{
Maps->ReadTileTypes((x/16),(y/16),zzz, &tiles);
tile = tiles[x%16][y%16];
if (DFHack::tileTypeTable[tile].c == DFHack::WALL)
break;
tiles[x%16][y%16] = 331;
Maps->WriteTileTypes((x/16),(y/16),zzz, &tiles);
zzz++;
}
}
else
{
// place the magma
Maps->ReadDesignations((x/16),(y/16),z, &designations);
Maps->ReadTemperatures((x/16),(y/16),z, &temp1, &temp2);
if(brush == "point")
{
if(mode != "flowbits")
{
// fix temperatures so we don't produce lethal heat traps
if(amount == 0 || designations[x%16][y%16].bits.liquid_type == DFHack::liquid_magma && mode == "water")
temp1[x%16][y%16] = temp2[x%16][y%16] = 10015;
designations[x%16][y%16].bits.flow_size = amount;
}
if(mode == "magma")
designations[x%16][y%16].bits.liquid_type = DFHack::liquid_magma;
else if(mode == "water")
designations[x%16][y%16].bits.liquid_type = DFHack::liquid_water;
}
else
{
for(uint32_t xx = 0; xx < 16; xx++) for(uint32_t yy = 0; yy < 16; yy++)
{
if(mode != "flowbits")
{
// fix temperatures so we don't produce lethal heat traps
if(amount == 0 || designations[xx][yy].bits.liquid_type == DFHack::liquid_magma && mode == "water")
temp1[xx%16][yy%16] = temp2[xx%16][yy%16] = 10015;
designations[xx][yy].bits.flow_size = amount;
}
if(mode == "magma")
designations[xx][yy].bits.liquid_type = DFHack::liquid_magma;
else if(mode == "water")
designations[xx][yy].bits.liquid_type = DFHack::liquid_water;
}
}
Maps->WriteTemperatures((x/16),(y/16),z, &temp1, &temp2);
Maps->WriteDesignations(x/16,y/16,z, &designations);
}
// make the magma flow :)
DFHack::t_blockflags bflags;
Maps->ReadBlockFlags((x/16),(y/16),z,bflags);
// 0x00000001 = job-designated
// 0x0000000C = run flows? - both bit 3 and 4 required for making magma placed on a glacier flow
if(flowmode == "f+")
{
bflags.bits.liquid_1 = true;
bflags.bits.liquid_2 = true;
}
else if(flowmode == "f-")
{
bflags.bits.liquid_1 = false;
bflags.bits.liquid_2 = false;
}
else
{
cout << "flow bit 1 = " << bflags.bits.liquid_1 << endl;
cout << "flow bit 2 = " << bflags.bits.liquid_2 << endl;
}
Maps->WriteBlockFlags((x/16),(y/16),z,bflags);
cout << "OK" << endl;
Maps->Finish();
} while (0);
}
}
DF.Detach();
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();
#endif
return 0;
}

@ -1,72 +0,0 @@
// This will create 7 deep magama on the square the cursor is on. It does not
// enable magma buildings at this time.
#include <iostream>
#include <integers.h>
#include <vector>
using namespace std;
#include <DFTypes.h>
#include <DFHackAPI.h>
#include <modules/Maps.h>
#include <modules/Position.h>
int main (void)
{
int32_t x,y,z;
DFHack::designations40d designations;
DFHack::API DF("Memory.xml");
DFHack::Maps * Maps;
DFHack::Position * Position;
try
{
DF.Attach();
Maps = DF.getMaps();
Position = DF.getPosition();
}
catch (exception& e)
{
cerr << e.what() << endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
return 1;
}
Maps->Start();
if(Position->getCursorCoords(x,y,z))
{
cout << "cursor coords: " << x << "/" << y << "/" << z << endl;
if(Maps->isValidBlock(x/16,y/16,z))
{
// place the magma
Maps->ReadDesignations((x/16),(y/16),z, &designations);
designations[x%16][y%16].bits.flow_size = 7;
designations[x%16][y%16].bits.liquid_type = DFHack::liquid_magma;
Maps->WriteDesignations(x/16,y/16,z, &designations);
// make the magma flow :)
DFHack::t_blockflags bflags;
Maps->ReadBlockFlags((x/16),(y/16),z,bflags);
// 0x00000001 = job-designated
// 0x0000000C = run flows? - both bit 3 and 4 required for making magma placed on a glacier flow
bflags.bits.liquid_1 = true;
bflags.bits.liquid_2 = true;
Maps->WriteBlockFlags((x/16),(y/16),z,bflags);
Maps->Finish();
cout << "Success" << endl;
}
else
cout << "Failure 1" << endl;
}
else
cout << "Failure 2" << endl;
DF.Detach();
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();
#endif
return 0;
}

@ -9,6 +9,15 @@ using namespace std;
#include <DFHackAPI.h>
#include <modules/Maps.h>
struct hideblock
{
uint32_t x;
uint32_t y;
uint32_t z;
uint8_t hiddens [16][16];
};
int main (void)
{
uint32_t x_max,y_max,z_max;
@ -40,8 +49,9 @@ int main (void)
}
Maps->getSize(x_max,y_max,z_max);
// walk the map
vector <hideblock> hidesaved;
// walk the map, save the hide bits, reveal.
cout << "Revealing... please wait." << endl;
for(uint32_t x = 0; x< x_max;x++)
{
for(uint32_t y = 0; y< y_max;y++)
@ -50,20 +60,45 @@ int main (void)
{
if(Maps->isValidBlock(x,y,z))
{
hideblock hb;
hb.x = x;
hb.y = y;
hb.z = z;
// read block designations
Maps->ReadDesignations(x,y,z, &designations);
// change the hidden flag to 0
for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++)
{
hb.hiddens[i][j] = designations[i][j].bits.hidden;
designations[i][j].bits.hidden = 0;
}
hidesaved.push_back(hb);
// write the designations back
Maps->WriteDesignations(x,y,z, &designations);
}
}
}
}
// FIXME: force game pause here!
DF.Detach();
cout << "Map revealed. Close window/force exit to keep it that way." << endl;
cout << "Press any key to unreveal. Don't close DF or unpause in that case!" << endl;
cin.ignore();
cout << "Unrevealing... please wait." << endl;
// FIXME: do some consistency checks here!
DF.Attach();
Maps = DF.getMaps();
Maps->Start();
for(int i = 0; i < hidesaved.size();i++)
{
hideblock & hb = hidesaved[i];
Maps->ReadDesignations(hb.x,hb.y,hb.z, &designations);
for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++)
{
designations[i][j].bits.hidden = hb.hiddens[i][j];
}
Maps->WriteDesignations(hb.x,hb.y,hb.z, &designations);
}
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();

@ -6,6 +6,7 @@
#include <stack>
#include <map>
#include <stdio.h>
#include <cstdlib>
using namespace std;
#include <DFTypes.h>
@ -15,53 +16,66 @@ using namespace std;
#include <modules/Position.h>
#include <modules/Materials.h>
#include <DFTileTypes.h>
#include <argstream.h>
#define MAX_DIM 0x300
class Point
{
public:
Point(uint32_t x, uint32_t y)
Point(uint32_t x, uint32_t y, uint32_t z)
{
this->x = x;
this->y = y;
this->z = z;
}
Point()
{
x = y = z = 0;
}
bool operator==(const Point &other) const
{
return (other.x == x && other.y == y);
return (other.x == x && other.y == y && other.z == z);
}
bool operator<(const Point &other) const
{
return ( (y*MAX_DIM + x) < (other.y*MAX_DIM + other.x));
return ( (z*MAX_DIM*MAX_DIM + y*MAX_DIM + x) < (other.z*MAX_DIM*MAX_DIM + other.y*MAX_DIM + other.x));
}
Point operator/(int number) const
{
return Point(x/number, y/number);
return Point(x/number, y/number, z);
}
Point operator%(int number) const
{
return Point(x%number, y%number);
return Point(x%number, y%number, z);
}
Point operator-(int number) const
{
return Point(x,y,z-number);
}
Point operator+(int number) const
{
return Point(x,y,z+number);
}
uint32_t x;
uint32_t y;
uint32_t z;
};
class Block
{
public:
Block(DFHack::Maps *_m, uint32_t x_, uint32_t y_, uint32_t z_)
Block(DFHack::Maps *_m, Point _bcoord)
{
vector <DFHack::t_vein> veins;
m = _m;
dirty = false;
valid = false;
x = x_;
y = y_;
z = z_;
if(m->ReadBlock40d(x_,y_,z_,&raw))
bcoord = _bcoord;
if(m->ReadBlock40d(bcoord.x,bcoord.y,bcoord.z,&raw))
{
memset(materials,-1,sizeof(materials));
memset(bitmap,0,sizeof(bitmap));
m->ReadVeins(x,y,z,&veins);
m->ReadVeins(bcoord.x,bcoord.y,bcoord.z,&veins);
// for each vein
for(int i = 0; i < (int)veins.size();i++)
{
@ -119,36 +133,31 @@ class Block
if(dirty)
{
//printf("writing %d/%d/%d\n",x,y,z);
m->WriteDesignations(x,y,z, &raw.designation);
m->WriteDirtyBit(x,y,z,true);
m->WriteDesignations(bcoord.x,bcoord.y,bcoord.z, &raw.designation);
m->WriteDirtyBit(bcoord.x,bcoord.y,bcoord.z,true);
}
return true;
}
bool valid;
bool dirty;
volatile bool valid;
volatile bool dirty;
DFHack::Maps * m;
DFHack::mapblock40d raw;
uint32_t x;
uint32_t y;
uint32_t z;
Point bcoord;
int16_t materials[16][16];
int8_t bitmap[16][16];
};
class Layer
class MapCache
{
public:
Layer(DFHack::Maps * Maps, uint32_t _z)
MapCache(DFHack::Maps * Maps)
{
valid = 0;
this->Maps = Maps;
z = _z;
uint32_t z_max;
Maps->getSize(x_bmax, y_bmax, z_max);
if(z < z_max)
valid = true;
valid = true;
};
~Layer()
~MapCache()
{
map<Point, Block *>::iterator p;
for(p = blocks.begin(); p != blocks.end(); p++)
@ -173,9 +182,13 @@ class Layer
}
else
{
Block * nblo = new Block(Maps,blockcoord.x,blockcoord.y,z);
blocks[blockcoord] = nblo;
return nblo;
if(blockcoord.x < x_bmax && blockcoord.y < y_bmax && blockcoord.z < z_max)
{
Block * nblo = new Block(Maps,blockcoord);
blocks[blockcoord] = nblo;
return nblo;
}
return 0;
}
}
@ -230,6 +243,15 @@ class Layer
}
return false;
}
bool testCoord (Point tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return true;
}
return false;
}
bool WriteAll()
{
@ -242,18 +264,31 @@ class Layer
return true;
}
private:
bool valid;
uint32_t z;
volatile bool valid;
uint32_t x_bmax;
uint32_t y_bmax;
uint32_t x_tmax;
uint32_t y_tmax;
uint32_t z_max;
DFHack::Maps * Maps;
map<Point, Block *> blocks;
};
int main (int argc, const char* argv[])
int main (int argc, char* argv[])
{
// Command line options
bool updown = false;
argstream as(argc,argv);
as >>option('x',"updown",updown,"Dig up and down stairs to reach other z-levels.")
>>help();
// sane check
if (!as.isOk())
{
cout << as.errorLog();
return 1;
}
DFHack::API DF("Memory.xml");
try
@ -287,6 +322,9 @@ int main (int argc, const char* argv[])
int32_t cx, cy, cz;
Maps->getSize(x_max,y_max,z_max);
uint32_t tx_max = x_max * 16;
uint32_t ty_max = y_max * 16;
Pos->getCursorCoords(cx,cy,cz);
while(cx == -30000)
{
@ -296,18 +334,27 @@ int main (int argc, const char* argv[])
DF.Suspend();
Pos->getCursorCoords(cx,cy,cz);
}
Point xy ((uint32_t)cx,(uint32_t)cy,cz);
if(xy.x == 0 || xy.x == tx_max - 1 || xy.y == 0 || xy.y == ty_max - 1)
{
cerr << "I won't dig the borders. That would be cheating!" << endl;
DF.Detach();
#ifndef LINUX_BUILD
cin.ignore();
#endif
return 1;
}
MapCache * MCache = new MapCache(Maps);
Layer * L = new Layer(Maps,cz);
Point xy ((uint32_t)cx,(uint32_t)cy);
DFHack::t_designation des = L->designationAt(xy);
int16_t tt = L->tiletypeAt(xy);
int16_t veinmat = L->materialAt(xy);
DFHack::t_designation des = MCache->designationAt(xy);
int16_t tt = MCache->tiletypeAt(xy);
int16_t veinmat = MCache->materialAt(xy);
if( veinmat == -1 )
{
cerr << "This tile is non-vein. Bye :)" << endl;
delete L;
delete MCache;
DF.Detach();
#ifndef LINUX_BUILD
cin.ignore();
@ -317,56 +364,111 @@ int main (int argc, const char* argv[])
printf("%d/%d/%d tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole);
stack <Point> flood;
flood.push(xy);
uint32_t tx_max = x_max * 16;
uint32_t ty_max = y_max * 16;
while( !flood.empty() )
{
Point current = flood.top();
flood.pop();
int16_t vmat2 = L->materialAt(current);
int16_t vmat2 = MCache->materialAt(current);
if(vmat2!=veinmat)
continue;
// found a good tile, dig+unset material
DFHack::t_designation des = L->designationAt(current);
des.bits.dig = DFHack::designation_default;
if(L->setDesignationAt(current,des))
DFHack::t_designation des = MCache->designationAt(current);
DFHack::t_designation des_minus;
DFHack::t_designation des_plus;
des_plus.whole = des_minus.whole = 0;
int16_t vmat_minus = -1;
int16_t vmat_plus = -1;
bool below = 0;
bool above = 0;
if(updown)
{
if(MCache->testCoord(current-1))
{
below = 1;
des_minus = MCache->designationAt(current-1);
vmat_minus = MCache->materialAt(current-1);
}
if(MCache->testCoord(current+1))
{
above = 1;
des_plus = MCache->designationAt(current+1);
vmat_plus = MCache->materialAt(current+1);
}
}
if(MCache->testCoord(current))
{
L->clearMaterialAt(current);
if(current.x < tx_max)
MCache->clearMaterialAt(current);
if(current.x < tx_max - 2)
{
flood.push(Point(current.x + 1, current.y, current.z));
if(current.y < ty_max - 2)
{
flood.push(Point(current.x + 1, current.y + 1,current.z));
flood.push(Point(current.x, current.y + 1,current.z));
}
if(current.y > 1)
{
flood.push(Point(current.x + 1, current.y - 1,current.z));
flood.push(Point(current.x, current.y - 1,current.z));
}
}
if(current.x > 1)
{
flood.push(Point(current.x + 1, current.y));
if(current.y < ty_max)
flood.push(Point(current.x - 1, current.y,current.z));
if(current.y < ty_max - 2)
{
flood.push(Point(current.x + 1, current.y + 1));
flood.push(Point(current.x, current.y + 1));
flood.push(Point(current.x - 1, current.y + 1,current.z));
flood.push(Point(current.x, current.y + 1,current.z));
}
if(current.y != 0)
if(current.y > 1)
{
flood.push(Point(current.x + 1, current.y - 1));
flood.push(Point(current.x, current.y - 1));
flood.push(Point(current.x - 1, current.y - 1,current.z));
flood.push(Point(current.x, current.y - 1,current.z));
}
}
if(current.x != 0)
if(updown)
{
flood.push(Point(current.x - 1, current.y));
if(current.y < ty_max)
if(current.z > 0 && below && vmat_minus == vmat2)
{
flood.push(Point(current.x - 1, current.y + 1));
flood.push(Point(current.x, current.y + 1));
flood.push(current-1);
if(des_minus.bits.dig == DFHack::designation_d_stair)
des_minus.bits.dig = DFHack::designation_ud_stair;
else
des_minus.bits.dig = DFHack::designation_u_stair;
MCache->setDesignationAt(current-1,des_minus);
des.bits.dig = DFHack::designation_d_stair;
}
if(current.y != 0)
if(current.z < z_max - 1 && above && vmat_plus == vmat2)
{
flood.push(Point(current.x - 1, current.y - 1));
flood.push(Point(current.x, current.y - 1));
flood.push(current+ 1);
if(des_plus.bits.dig == DFHack::designation_u_stair)
des_plus.bits.dig = DFHack::designation_ud_stair;
else
des_plus.bits.dig = DFHack::designation_d_stair;
MCache->setDesignationAt(current+1,des_plus);
if(des.bits.dig == DFHack::designation_d_stair)
des.bits.dig = DFHack::designation_ud_stair;
else
des.bits.dig = DFHack::designation_u_stair;
}
}
if(des.bits.dig == DFHack::designation_no)
des.bits.dig = DFHack::designation_default;
MCache->setDesignationAt(current,des);
}
}
L->WriteAll();
delete L;
MCache->WriteAll();
delete MCache;
DF.Detach();
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;