Conflicts:
	library/include/dfhack/DFProcess.h
develop
Petr Mrázek 2011-05-15 21:50:20 +02:00
commit 515f4952a9
16 changed files with 252 additions and 78 deletions

@ -382,6 +382,11 @@ void SHMProcess::readSTLVector(const uint32_t address, t_vecTriplet & triplet)
read(address + d->vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
void SHMProcess::writeSTLVector(const uint32_t address, t_vecTriplet & triplet)
{
write(address + d->vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
string SHMProcess::doReadClassName (uint32_t vptr)
{

@ -69,6 +69,7 @@ namespace {
bool forceresume();
void readSTLVector(const uint32_t address, t_vecTriplet & triplet);
void writeSTLVector(const uint32_t address, t_vecTriplet & triplet);
const std::string readSTLString (uint32_t offset);
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity);
size_t writeSTLString(const uint32_t address, const std::string writeString);
@ -152,6 +153,11 @@ void WineProcess::readSTLVector(const uint32_t address, t_vecTriplet & triplet)
read(address + vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
void WineProcess::writeSTLVector(const uint32_t address, t_vecTriplet & triplet)
{
write(address + vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
size_t WineProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
return stl.readSTLString(offset, buffer, bufcapacity);

@ -68,6 +68,7 @@ namespace {
bool forceresume();
void readSTLVector(const uint32_t address, t_vecTriplet & triplet);
void writeSTLVector(const uint32_t address, t_vecTriplet & triplet);
const std::string readSTLString (uint32_t offset);
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity);
size_t writeSTLString(const uint32_t address, const std::string writeString);
@ -178,6 +179,11 @@ void NormalProcess::readSTLVector(const uint32_t address, t_vecTriplet & triplet
read(address + vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
void NormalProcess::writeSTLVector(const uint32_t address, t_vecTriplet & triplet)
{
write(address + vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
const string NormalProcess::readSTLString (uint32_t offset)
{
_Rep_base header;

@ -394,6 +394,11 @@ void SHMProcess::readSTLVector(const uint32_t address, t_vecTriplet & triplet)
read(address + d->vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
void SHMProcess::writeSTLVector(const uint32_t address, t_vecTriplet & triplet)
{
write(address + d->vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
string SHMProcess::doReadClassName (uint32_t vptr)
{
int rtti = Process::readDWord(vptr - 0x4);

@ -85,6 +85,7 @@ namespace
void write(uint32_t address, uint32_t length, uint8_t* buffer);
void readSTLVector(const uint32_t address, t_vecTriplet & triplet);
void writeSTLVector(const uint32_t address, t_vecTriplet & triplet);
const std::string readSTLString (uint32_t offset);
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity);
size_t writeSTLString(const uint32_t address, const std::string writeString);
@ -575,6 +576,11 @@ void NormalProcess::readSTLVector(const uint32_t address, t_vecTriplet & triplet
read(address + vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
void NormalProcess::writeSTLVector(const uint32_t address, t_vecTriplet & triplet)
{
write(address + vector_start, sizeof(triplet), (uint8_t *) &triplet);
}
size_t NormalProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
return stl.readSTLString(offset, buffer, bufcapacity);

@ -182,6 +182,7 @@ namespace DFHack
/// read a STL vector
virtual void readSTLVector(const uint32_t address, t_vecTriplet & triplet) = 0;
virtual void writeSTLVector(const uint32_t address, t_vecTriplet & triplet) = 0;
/// get class name of an object with rtti/type info
virtual std::string doReadClassName(uint32_t vptr) = 0;
@ -225,21 +226,19 @@ namespace DFHack
};
class DFHACK_EXPORT ClassNameCheck
{
{
std::string name;
uint32_t vptr;
mutable uint32_t vptr;
public:
ClassNameCheck() : vptr(0) {};
ClassNameCheck(std::string _name) : name(_name), vptr(0) {};
ClassNameCheck &operator= (const ClassNameCheck &b)
{
{
name = b.name; vptr = b.vptr; return *this;
};
bool operator() (Process *p, uint32_t ptr)
{
if(vptr == 0)
if (p->readClassName(ptr) == name)
vptr = ptr;
}
bool operator() (Process *p, uint32_t ptr) const {
if (vptr == 0 && p->readClassName(ptr) == name)
vptr = ptr;
return (vptr && vptr == ptr);
};
};

@ -31,18 +31,30 @@ distribution.
#include "DFExport.h"
#include "VersionInfo.h"
#include "DFProcess.h"
#include <string.h>
namespace DFHack
{
template <class T>
class DFHACK_EXPORT DfVector
{
private:
Process *_p;
uint32_t _address;
t_vecTriplet t;
uint32_t _size;// vector size
T * data; // cached data
bool isMetadataInSync()
{
t_vecTriplet t2;
_p->readSTLVector(_address,t2);
return (t2.start == t.start || t2.end == t.end || t2.alloc_end == t.alloc_end);
}
public:
DfVector(Process * p, uint32_t address)
DfVector(Process *p, uint32_t address) : _p(p), _address(address)
{
p->readSTLVector(address,t);
uint32_t byte_size = t.end - t.start;
@ -60,18 +72,43 @@ namespace DFHack
delete [] data;
};
// get offset of the specified index
inline T& operator[] (uint32_t index)
inline const T& operator[] (uint32_t index)
{
// FIXME: vector out of bounds exception
//assert(index < size);
return data[index];
};
// get offset of the specified index
inline T& at (uint32_t index)
inline const T& at (uint32_t index)
{
//assert(index < size);
return data[index];
};
// update value at index
bool set(uint32_t index, T value)
{
if (index >= _size)
return false;
data[index] = value;
_p->write(t.start + sizeof(T)*index, sizeof(T), (uint8_t *)&data[index]);
return true;
}
// remove value
bool remove(uint32_t index)
{
if (index >= _size || !isMetadataInSync())
return false;
// Remove the item
_size--;
t.end -= sizeof(T);
int tail = (_size-index)*sizeof(T);
memmove(&data[index], &data[index+1], tail);
// Write back the data
if (tail)
_p->write(t.start + sizeof(T)*index, tail, (uint8_t *)&data[index]);
_p->writeSTLVector(_address,t);
return true;
}
// get vector size
inline uint32_t size ()
{

@ -347,6 +347,11 @@ namespace DFHack
void CopyNameTo(t_creature &creature, uint32_t address);
protected:
friend class Items;
bool RemoveOwnedItemIdx(const uint32_t index, int32_t id);
bool RemoveOwnedItemPtr(const uint32_t index, int32_t id);
private:
struct Private;
Private *d;

@ -14,6 +14,7 @@ namespace DFHack
class Context;
class DFContextShared;
class Creatures;
//From http://dwarffortresswiki.net/index.php/User:Rick/Memory_research
//They all seem to be valid on 40d as well
@ -129,10 +130,20 @@ public:
bool readItem(uint32_t itemptr, dfh_item & item);
/// write item base (position and flags only = t_item part of dfh_item)
bool writeItem(const dfh_item & item);
/// who owns this item we already read?
int32_t getItemOwnerID(const dfh_item & item);
/// dump offsets used by accessors to a string
std::string dumpAccessors(const dfh_item & item);
/// who owns this item we already read?
int32_t getItemOwnerID(const dfh_item & item);
/// which item is it contained in?
int32_t getItemContainerID(const dfh_item & item);
/// which items does it contain?
bool getContainedItems(const dfh_item & item, std::vector<int32_t> &items);
/// wipe out the owner records
bool removeItemOwner(dfh_item &item, Creatures *creatures);
bool readItemRefs(const dfh_item &item, const ClassNameCheck &classname, std::vector<int32_t> &values);
private:
class Private;
Private* d;

@ -722,6 +722,30 @@ bool Creatures::ReadOwnedItemsPtr(const uint32_t temp, std::vector<int32_t> & it
return true;
}
bool Creatures::RemoveOwnedItemIdx(const uint32_t index, int32_t id)
{
if(!d->Started || !d->Ft_owned_items) return false;
uint32_t temp = d->p_cre->at (index);
return this->RemoveOwnedItemPtr(temp, id);
}
bool Creatures::RemoveOwnedItemPtr(const uint32_t temp, int32_t id)
{
if(!d->Started || !d->Ft_owned_items) return false;
Process * p = d->owner;
DfVector <int32_t> citem(p, temp + d->creatures.owned_items_offset);
for (unsigned i = 0; i < citem.size(); i++) {
if (citem[i] != id)
continue;
if (!citem.remove(i--))
return false;
}
return true;
}
void Creatures::CopyNameTo(t_creature &creature, uint32_t address)
{
Private::t_offsets &offs = d->creatures;

@ -38,6 +38,7 @@ using namespace std;
#include "dfhack/DFVector.h"
#include "dfhack/modules/Materials.h"
#include "dfhack/modules/Items.h"
#include "dfhack/modules/Creatures.h"
#include "ModuleFactory.h"
using namespace DFHack;
@ -426,10 +427,11 @@ class Items::Private
std::map<uint32_t, ItemDesc *> descVTable;
std::map<int32_t, uint32_t> idLookupTable;
uint32_t refVectorOffset;
uint32_t refIDOffset;
uint32_t idFieldOffset;
uint32_t itemVectorAddress;
ClassNameCheck isOwnerRefClass;
ClassNameCheck isContainerRefClass;
ClassNameCheck isContainsRefClass;
};
Items::Items(DFContextShared * d_)
@ -437,12 +439,15 @@ Items::Items(DFContextShared * d_)
d = new Private;
d->d = d_;
d->owner = d_->p;
d->refVectorOffset = d->refIDOffset = 0;
d->isOwnerRefClass = ClassNameCheck("general_ref_unit_itemownerst");
d->isContainerRefClass = ClassNameCheck("general_ref_contained_in_itemst");
d->isContainsRefClass = ClassNameCheck("general_ref_contains_itemst");
DFHack::OffsetGroup* itemGroup = d_->offset_descriptor->getGroup("Items");
d->itemVectorAddress = itemGroup->getAddress("items_vector");
d->idFieldOffset = itemGroup->getOffset("id");
d->refVectorOffset = itemGroup->getOffset("item_ref_vector");
}
bool Items::Start()
@ -538,27 +543,65 @@ void Items::setItemFlags(uint32_t itemptr, t_itemflags new_flags)
*/
int32_t Items::getItemOwnerID(const DFHack::dfh_item &item)
{
if (!d->refVectorOffset)
std::vector<int32_t> vals;
if (readItemRefs(item, d->isOwnerRefClass, vals))
return vals[0];
else
return -1;
}
int32_t Items::getItemContainerID(const DFHack::dfh_item &item)
{
std::vector<int32_t> vals;
if (readItemRefs(item, d->isContainerRefClass, vals))
return vals[0];
else
return -1;
}
bool Items::getContainedItems(const DFHack::dfh_item &item, std::vector<int32_t> &items)
{
return readItemRefs(item, d->isContainsRefClass, items);
}
bool Items::readItemRefs(const dfh_item &item, const ClassNameCheck &classname, std::vector<int32_t> &values)
{
DFHack::DfVector<uint32_t> p_refs(d->owner, item.origin + d->refVectorOffset);
values.clear();
for (uint32_t i=0; i<p_refs.size(); i++)
{
OffsetGroup * Items = d->owner->getDescriptor()->getGroup("Items");
d->refVectorOffset = Items->getOffset("item_ref_vector");
d->refIDOffset = Items->getOffset("owner_ref_id_field");
uint32_t vtbl = d->owner->readDWord(p_refs[i]);
if (classname(d->owner, vtbl))
values.push_back(int32_t(d->owner->readDWord(p_refs[i] + 4)));
}
return !values.empty();
}
bool Items::removeItemOwner(dfh_item &item, Creatures *creatures)
{
DFHack::DfVector<uint32_t> p_refs(d->owner, item.origin + d->refVectorOffset);
uint32_t size = p_refs.size();
for (uint32_t i=0;i<size;i++)
for (uint32_t i=0; i<p_refs.size(); i++)
{
uint32_t curRef = p_refs[i];
uint32_t vtbl = d->owner->readDWord(curRef);
uint32_t vtbl = d->owner->readDWord(p_refs[i]);
if (!d->isOwnerRefClass(d->owner, vtbl)) continue;
return d->owner->readDWord(curRef + d->refIDOffset);
int32_t oid = d->owner->readDWord(p_refs[i]+4);
int32_t ix = creatures->FindIndexById(oid);
if (ix < 0 || !creatures->RemoveOwnedItemIdx(ix, item.id))
return false;
if (!p_refs.remove(i--))
return false;
}
return -1;
item.base.flags.owned = 0;
return true;
}
std::string Items::getItemClass(const dfh_item & item)

@ -73,6 +73,7 @@ namespace DFHack
size_t writeSTLString(const uint32_t address, const std::string writeString);
void readSTLVector(const uint32_t address, t_vecTriplet & triplet);
void writeSTLVector(const uint32_t address, t_vecTriplet & triplet);
// get class name of an object with rtti/type info
std::string doReadClassName(uint32_t vptr);

@ -14,8 +14,28 @@ using namespace std;
#include <DFHack.h>
#include <dfhack/DFVector.h>
int main ()
int main (int argc, char *argv[])
{
bool print_refs = false;
bool print_hex = false;
bool print_acc = false;
for(int i = 1; i < argc; i++)
{
char *arg = argv[i];
if (arg[0] != '-')
continue;
for (; *arg; arg++) {
switch (arg[0]) {
case 'r': print_refs = true; break;
case 'x': print_hex = true; break;
case 'a': print_acc = true; break;
}
}
}
DFHack::Process * p;
unsigned int i,j;
DFHack::ContextManager DFMgr("Memory.xml");
@ -45,54 +65,54 @@ int main ()
p = DF->getProcess();
int32_t x,y,z;
Gui->getCursorCoords(x,y,z);
std::vector<uint32_t> p_items;
Items->readItemVector(p_items);
uint32_t size = p_items.size();
// FIXME: tools should never be exposed to DFHack internals!
DFHack::OffsetGroup* itemGroup = mem->getGroup("Items");
DFHack::DfVector <uint32_t> p_items (p, itemGroup->getAddress("items_vector"));
uint32_t size = p_items.size();
uint32_t ref_vector = itemGroup->getOffset("item_ref_vector");
for(int i = 0; i < size; i++)
{
DFHack::dfh_item itm;
memset(&itm, 0, sizeof(DFHack::dfh_item));
Items->readItem(p_items[i],itm);
if(x != -30000)
{
if(itm.base.x == x
&& itm.base.y == y
&& itm.base.z == z
&& itm.base.flags.on_ground
&& !itm.base.flags.in_chest
&& !itm.base.flags.in_inventory
&& !itm.base.flags.in_building
)
{
printf(
"%5d: %08x %6d %08x (%d,%d,%d) #%08x [%d] %s - %s. Stack: %d\n",
i, itm.origin, itm.id, itm.base.flags.whole,
itm.base.x, itm.base.y, itm.base.z,
itm.base.vtable,
itm.wear_level,
Items->getItemClass(itm.matdesc.itemType).c_str(),
Items->getItemDescription(itm, Materials).c_str(),
itm.quantity
);
hexdump(DF,p_items[i],0x300);
cout << Items->dumpAccessors(itm) << endl;
if (x != -30000
&& !(itm.base.x == x && itm.base.y == y && itm.base.z == z
&& itm.base.flags.on_ground
&& !itm.base.flags.in_chest
&& !itm.base.flags.in_inventory
&& !itm.base.flags.in_building))
continue;
printf(
"%5d: %08x %6d %08x (%d,%d,%d) #%08x [%d] *%d %s - %s\n",
i, itm.origin, itm.id, itm.base.flags.whole,
itm.base.x, itm.base.y, itm.base.z,
itm.base.vtable,
itm.wear_level,
itm.quantity,
Items->getItemClass(itm.matdesc.itemType).c_str(),
Items->getItemDescription(itm, Materials).c_str()
);
if (print_hex)
hexdump(DF,p_items[i],0x300);
if (print_acc)
cout << Items->dumpAccessors(itm) << endl;
if (print_refs) {
DFHack::DfVector<uint32_t> p_refs(p, itm.origin + ref_vector);
for (int j = 0; j < p_refs.size(); j++) {
uint32_t vptr = p->readDWord(p_refs[j]);
uint32_t val = p->readDWord(p_refs[j]+4);
printf("\t-> %d \t%s\n", int(val), p->readClassName(vptr).c_str());
}
}
else
{
printf(
"%5d: %08x %6d %08x (%d,%d,%d) #%08x [%d] %s - %s. Stack: %d\n",
i, itm.origin, itm.id, itm.base.flags.whole,
itm.base.x, itm.base.y, itm.base.z,
itm.base.vtable,
itm.wear_level,
Items->getItemClass(itm.matdesc.itemType).c_str(),
Items->getItemDescription(itm, Materials).c_str(),
itm.quantity
);
}
}
/*
printf("type\tvtable\tname\tquality\tdecorate\n");

@ -92,14 +92,21 @@ int main (int argc, char *argv[])
DFHack::dfh_item itm;
Items->readItem(curItem, itm);
if (!itm.base.flags.owned)
continue;
std::string name = Items->getItemClass(itm.matdesc.itemType);
bool confiscate = false;
bool dump = false;
if (!itm.base.flags.owned) {
int32_t owner = Items->getItemOwnerID(itm);
if (owner >= 0) {
printf("Fixing a misflagged item: ");
confiscate = true;
}
else
continue;
}
std::string name = Items->getItemClass(itm.matdesc.itemType);
if (itm.base.flags.rotten)
{
printf("Confiscating a rotten item: \t");
@ -131,12 +138,14 @@ int main (int argc, char *argv[])
if (confiscate)
{
itm.base.flags.owned = 0;
if (dump)
itm.base.flags.dump = 1;
if (!dry_run) {
if (!Items->removeItemOwner(itm, Creatures))
printf("(unsuccessfully) ");
if (dump)
itm.base.flags.dump = 1;
if (!dry_run)
Items->writeItem(itm);
}
printf(
"%s (wear %d)",

@ -96,6 +96,5 @@ int main(int argc, char *argv[])
std::cout << " Press any key to finish.";
std::cin.ignore();
}
std::cout << std::endl;
return 0;
}

@ -105,8 +105,6 @@ int main(int argc, char *argv[])
veg->Read(i,p);
if(all_shrubs && p.sdata.is_shrub || all_trees && !p.sdata.is_shrub)
{
//p.sdata.temperature_1 = 0;
//p.sdata.temperature_2 = 0;
if (immolate)
p.sdata.is_burning = true;
p.sdata.hitpoints = 0;