Support printing refs in dfitemdump, and add methods for containers.

develop
Alexander Gavrilov 2011-05-12 20:30:42 +04:00
parent 77dda6faea
commit c7f4f8c281
4 changed files with 105 additions and 60 deletions

@ -226,14 +226,14 @@ 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) {
bool operator() (Process *p, uint32_t ptr) const {
if (vptr == 0 && p->readClassName(ptr) == name)
vptr = ptr;
return (vptr && vptr == ptr);

@ -129,10 +129,17 @@ 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);
bool readItemRefs(const dfh_item &item, const ClassNameCheck &classname, std::vector<int32_t> &values);
private:
class Private;
Private* d;

@ -426,10 +426,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 +438,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 +542,41 @@ void Items::setItemFlags(uint32_t itemptr, t_itemflags new_flags)
*/
int32_t Items::getItemOwnerID(const DFHack::dfh_item &item)
{
if (!d->refVectorOffset)
{
OffsetGroup * Items = d->owner->getDescriptor()->getGroup("Items");
d->refVectorOffset = Items->getOffset("item_ref_vector");
d->refIDOffset = Items->getOffset("owner_ref_id_field");
}
std::vector<int32_t> vals;
if (readItemRefs(item, d->isOwnerRefClass, vals))
return vals[0];
else
return -1;
}
DFHack::DfVector<uint32_t> p_refs(d->owner, item.origin + d->refVectorOffset);
uint32_t size = p_refs.size();
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;
}
for (uint32_t i=0;i<size;i++)
{
uint32_t curRef = p_refs[i];
uint32_t vtbl = d->owner->readDWord(curRef);
bool Items::getContainedItems(const DFHack::dfh_item &item, std::vector<int32_t> &items)
{
return readItemRefs(item, d->isContainsRefClass, items);
}
if (!d->isOwnerRefClass(d->owner, vtbl)) continue;
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);
return d->owner->readDWord(curRef + d->refIDOffset);
values.clear();
for (uint32_t i=0; i<p_refs.size(); i++)
{
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 -1;
return !values.empty();
}
std::string Items::getItemClass(const dfh_item & item)

@ -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");