Making Items a bit more sane. It's still using Accessors though.

develop
Petr Mrázek 2011-07-20 10:41:13 +02:00
parent 00cf7bc39e
commit 0defcc9889
8 changed files with 201 additions and 256 deletions

@ -27,6 +27,7 @@ distribution.
namespace DFHack
{
/// very generic representation of a virtual class... just the pointer to the vtable.
/// this is intended for instances where wrapping the classes properly hasn't been done yet.
struct t_virtual
{
void * vptr;

@ -32,7 +32,9 @@ distribution.
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "dfhack/Types.h"
#include "dfhack/Virtual.h"
#include "dfhack/modules/Materials.h"
#include "dfhack/Process.h"
/**
* \defgroup grp_items Items module and its types
* @ingroup grp_modules
@ -97,17 +99,31 @@ union t_itemflags
};
};
/**
* Describes relationship of an item with other objects
* \ingroup grp_items
*/
struct t_itemref : public t_virtual
{
int32_t value;
};
/**
* Basic item data, read as a single chunk
* \ingroup grp_items
*/
struct t_item
struct t_item : public t_virtual
{
uint32_t vtable;
int16_t x;
int16_t y;
int16_t z;
t_itemflags flags;
// vptr 0x0 + 4
int16_t x; // 0x4 + 2
int16_t y; // 0x6 + 2
int16_t z; // 0x8 + 2
// 2B padding 0xA + 2
t_itemflags flags; // 0xC + 4
uint32_t unk1; // 0x10 + 4
uint32_t id; // 0x14 + 4
std::vector<void *> unk2;// usage is pretty rare
std::vector<t_itemref *> itemrefs;
};
/**
@ -116,13 +132,11 @@ struct t_item
*/
struct dfh_item
{
int32_t id;
t_item base;
t_item * base;
t_material matdesc;
int32_t quantity;
int32_t quality;
int16_t wear_level;
uint32_t origin;
};
/**
@ -148,8 +162,8 @@ public:
bool Start();
bool Finish();
bool readItemVector(std::vector<uint32_t> &items);
uint32_t findItemByID(int32_t id);
bool readItemVector(std::vector<t_item *> &items);
t_item * findItemByID(int32_t id);
/// get a string describing an item
std::string getItemDescription(const dfh_item & item, Materials * Materials);
@ -157,7 +171,7 @@ public:
std::string getItemClass(int32_t index);
std::string getItemClass(const dfh_item & item);
/// read an item, including the extra attributes
bool readItem(uint32_t itemptr, dfh_item & item);
bool readItem(t_item * itembase, dfh_item & item);
/// write item base (position and flags only = t_item part of dfh_item)
bool writeItem(const dfh_item & item);
/// dump offsets used by accessors to a string

@ -31,6 +31,7 @@ distribution.
*/
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "dfhack/Types.h"
namespace DFHack
{
class DFContextShared;

@ -72,7 +72,7 @@ public:
Accessor(uint32_t function, Process * p);
Accessor(accessor_type type, int32_t constant, uint32_t offset1, uint32_t offset2, uint32_t dataWidth, Process * p);
std::string dump();
int32_t getValue(uint32_t objectPtr);
int32_t getValue(t_item * objectPtr);
bool isConstant();
};
class ItemImprovementDesc
@ -101,11 +101,11 @@ private:
bool hasDecoration;
int idFieldOffset;
public:
ItemDesc(uint32_t VTable, Process * p);
bool readItem(uint32_t itemptr, dfh_item & item);
ItemDesc(void * VTable, Process * p);
bool readItem(t_item * itemptr, dfh_item & item);
std::string dumpAccessors();
std::string className;
uint32_t vtable;
void * vtable;
uint32_t mainType;
std::vector<ItemImprovementDesc> improvement;
};
@ -306,7 +306,7 @@ string Accessor::dump()
return sstr.str();
}
int32_t Accessor::getValue(uint32_t objectPtr)
int32_t Accessor::getValue(t_item * objectPtr)
{
int32_t offset = this->offset1;
@ -316,18 +316,18 @@ int32_t Accessor::getValue(uint32_t objectPtr)
return this->constant;
break;
case ACCESSOR_DOUBLE_INDIRECT:
objectPtr = p->readDWord(objectPtr + this->offset1);
objectPtr = (t_item *) p->readDWord((uint32_t)objectPtr + this->offset1);
offset = this->offset2;
// fallthrough
case ACCESSOR_INDIRECT:
switch(this->dataWidth)
{
case Data32:
return p->readDWord(objectPtr + offset);
return p->readDWord((uint32_t)objectPtr + offset);
case DataSigned16:
return (int16_t) p->readWord(objectPtr + offset);
return (int16_t) p->readWord((uint32_t)objectPtr + offset);
case DataUnsigned16:
return (uint16_t) p->readWord(objectPtr + offset);
return (uint16_t) p->readWord((uint32_t)objectPtr + offset);
default:
return -1;
}
@ -338,12 +338,12 @@ int32_t Accessor::getValue(uint32_t objectPtr)
}
// FIXME: turn into a proper factory with caching
Accessor * buildAccessor (OffsetGroup * I, Process * p, const char * name, uint32_t vtable)
Accessor * buildAccessor (OffsetGroup * I, Process * p, const char * name, void * vtable)
{
int32_t offset;
if(I->getSafeOffset(name,offset))
{
return new Accessor( p->readDWord( vtable + offset ), p);
return new Accessor( p->readDWord( (uint32_t)vtable + offset ), p);
}
else
{
@ -352,7 +352,7 @@ Accessor * buildAccessor (OffsetGroup * I, Process * p, const char * name, uint3
}
}
ItemDesc::ItemDesc(uint32_t VTable, Process *p)
ItemDesc::ItemDesc(void * VTable, Process *p)
{
OffsetGroup * Items = p->getDescriptor()->getGroup("Items");
@ -400,17 +400,15 @@ string ItemDesc::dumpAccessors()
}
bool ItemDesc::readItem(uint32_t itemptr, DFHack::dfh_item &item)
bool ItemDesc::readItem(t_item * itemptr, DFHack::dfh_item &item)
{
item.id = p->readDWord(itemptr+idFieldOffset);
p->read(itemptr, sizeof(t_item), (uint8_t*)&item.base);
item.base = itemptr;
item.matdesc.itemType = AMainType->getValue(itemptr);
item.matdesc.subType = ASubType->getValue(itemptr);
item.matdesc.subIndex = ASubIndex->getValue(itemptr);
item.matdesc.index = AIndex->getValue(itemptr);
item.quality = AQuality->getValue(itemptr);
item.quantity = AQuantity->getValue(itemptr);
item.origin = itemptr;
// FIXME: use templates. seriously.
// Note: this accessor returns a 32-bit value with the higher
// half sometimes containing garbage, so the cast is essential:
@ -424,8 +422,8 @@ class Items::Private
DFContextShared *d;
Process * owner;
std::map<int32_t, ItemDesc *> descType;
std::map<uint32_t, ItemDesc *> descVTable;
std::map<int32_t, uint32_t> idLookupTable;
std::map<void *, ItemDesc *> descVTable;
std::map<int32_t, t_item *> idLookupTable;
uint32_t refVectorOffset;
uint32_t idFieldOffset;
uint32_t itemVectorAddress;
@ -461,29 +459,31 @@ bool Items::Finish()
return true;
}
bool Items::readItemVector(std::vector<uint32_t> &items)
bool Items::readItemVector(std::vector<t_item *> &items)
{
DFHack::DfVector <uint32_t> p_items(d->itemVectorAddress);
std::vector <t_item *> *p_items = (std::vector <t_item *> *) d->itemVectorAddress;
d->idLookupTable.clear();
items.resize(p_items.size());
items.resize(p_items->size());
for (unsigned i = 0; i < p_items.size(); i++) {
uint32_t ptr = p_items[i];
for (unsigned i = 0; i < p_items->size(); i++)
{
t_item * ptr = p_items->at(i);
items[i] = ptr;
d->idLookupTable[d->owner->readDWord(ptr + d->idFieldOffset)] = ptr;
d->idLookupTable[ptr->id] = ptr;
}
return true;
}
uint32_t Items::findItemByID(int32_t id)
t_item * Items::findItemByID(int32_t id)
{
if (id < 0)
return 0;
if (d->idLookupTable.empty()) {
std::vector<uint32_t> tmp;
if (d->idLookupTable.empty())
{
std::vector<t_item *> tmp;
readItemVector(tmp);
}
@ -493,7 +493,7 @@ uint32_t Items::findItemByID(int32_t id)
Items::~Items()
{
Finish();
std::map<uint32_t, ItemDesc *>::iterator it;
std::map<void *, ItemDesc *>::iterator it;
it = d->descVTable.begin();
while (it != d->descVTable.end())
{
@ -505,13 +505,13 @@ Items::~Items()
delete d;
}
bool Items::readItem(uint32_t itemptr, DFHack::dfh_item &item)
bool Items::readItem(t_item * itembase, DFHack::dfh_item &item)
{
std::map<uint32_t, ItemDesc *>::iterator it;
std::map<void *, ItemDesc *>::iterator it;
Process * p = d->owner;
ItemDesc * desc;
uint32_t vtable = p->readDWord(itemptr);
void * vtable = itembase->vptr;
it = d->descVTable.find(vtable);
if(it == d->descVTable.end())
{
@ -522,25 +522,9 @@ bool Items::readItem(uint32_t itemptr, DFHack::dfh_item &item)
else
desc = it->second;
return desc->readItem(itemptr, item);
}
bool Items::writeItem(const DFHack::dfh_item &item)
{
if(item.origin)
{
d->owner->write(item.origin, sizeof(t_item),(uint8_t *)&(item.base));
return true;
}
return false;
return desc->readItem(itembase, item);
}
/*
void Items::setItemFlags(uint32_t itemptr, t_itemflags new_flags)
{
d->owner->writeDWord(itemptr + 0x0C, new_flags.whole);
}
*/
int32_t Items::getItemOwnerID(const DFHack::dfh_item &item)
{
std::vector<int32_t> vals;
@ -566,15 +550,13 @@ bool Items::getContainedItems(const DFHack::dfh_item &item, std::vector<int32_t>
bool Items::readItemRefs(const dfh_item &item, const ClassNameCheck &classname, std::vector<int32_t> &values)
{
DFHack::DfVector<uint32_t> p_refs(item.origin + d->refVectorOffset);
std::vector <t_itemref *> &p_refs = item.base->itemrefs;
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, (void *) vtbl))
values.push_back(int32_t(d->owner->readDWord(p_refs[i] + 4)));
if (classname(d->owner, p_refs[i]->vptr))
values.push_back(int32_t(p_refs[i]->value));
}
return !values.empty();
@ -582,30 +564,24 @@ bool Items::readItemRefs(const dfh_item &item, const ClassNameCheck &classname,
bool Items::removeItemOwner(dfh_item &item, Creatures *creatures)
{
DFHack::DfVector<uint32_t> p_refs(item.origin + d->refVectorOffset);
std::vector <t_itemref *> &p_refs = item.base->itemrefs;
for (uint32_t i=0; i<p_refs.size(); i++)
{
uint32_t vtbl = d->owner->readDWord(p_refs[i]);
if (!d->isOwnerRefClass(d->owner, (void *) vtbl)) continue;
if (!d->isOwnerRefClass(d->owner, p_refs[i]->vptr))
continue;
int32_t oid = d->owner->readDWord(p_refs[i]+4);
int32_t & oid = p_refs[i]->value;
int32_t ix = creatures->FindIndexById(oid);
if (ix < 0 || !creatures->RemoveOwnedItemIdx(ix, item.id))
{
cerr << "RemoveOwnedItemIdx: CREATURE " << ix << " ID " << item.id << " FAILED!" << endl;
return false;
}
if (!p_refs.remove(i--))
if (ix < 0 || !creatures->RemoveOwnedItemIdx(ix, item.base->id))
{
cerr << "p_refs.remove FAILED!" << endl;
cerr << "RemoveOwnedItemIdx: CREATURE " << ix << " ID " << item.base->id << " FAILED!" << endl;
return false;
}
p_refs.erase(p_refs.begin() + i--);
}
item.base.flags.owned = 0;
item.base->flags.owned = 0;
return true;
}
@ -674,7 +650,7 @@ std::string Items::getItemDescription(const dfh_item & item, Materials * Materia
/// dump offsets used by accessors of a valid item to a string
std::string Items::dumpAccessors(const dfh_item & item)
{
std::map< uint32_t, ItemDesc* >::const_iterator it = d->descVTable.find(item.base.vtable);
std::map< void *, ItemDesc* >::const_iterator it = d->descVTable.find(item.base->vptr);
if(it != d->descVTable.end())
return it->second->dumpAccessors();
return "crud";

@ -831,29 +831,36 @@ bool Maps::SortBlockEvents(uint32_t x, uint32_t y, uint32_t z, vector <t_vein *>
else
{
string cname = p->readClassName(type);
//string cname = typeid(*(blockevent *)temp).name();
//Core::getInstance().con.printerr("%s\n",cname.c_str());
if(!off.vein_ice_vptr && cname == "block_square_event_frozen_liquidst")
{
off.vein_ice_vptr = type;
Core::getInstance().con.printerr("%s %x\n",cname.c_str(), type);
goto retry;
}
else if(!off.vein_mineral_vptr &&cname == "block_square_event_mineralst")
{
off.vein_mineral_vptr = type;
Core::getInstance().con.printerr("%s %x\n",cname.c_str(), type);
goto retry;
}
else if(!off.vein_spatter_vptr && cname == "block_square_event_material_spatterst")
{
off.vein_spatter_vptr = type;
Core::getInstance().con.printerr("%s %x\n",cname.c_str(), type);
goto retry;
}
else if(!off.vein_grass_vptr && cname=="block_square_event_grassst")
{
off.vein_grass_vptr = type;
Core::getInstance().con.printerr("%s %x\n",cname.c_str(), type);
goto retry;
}
else if(!off.vein_worldconstruction_vptr && cname=="block_square_event_world_constructionst")
{
off.vein_worldconstruction_vptr = type;
Core::getInstance().con.printerr("%s %x\n",cname.c_str(), type);
goto retry;
}
#ifdef DEBUG

@ -125,3 +125,4 @@ DFHACK_PLUGIN(cleanmap cleanmap.cpp)
DFHACK_PLUGIN(weather weather.cpp)
DFHACK_PLUGIN(vdig vdig.cpp)
DFHACK_PLUGIN(colonies colonies.cpp)
DFHACK_PLUGIN(itemhacks itemhacks.cpp)

@ -0,0 +1,120 @@
#include <dfhack/Core.h>
#include <dfhack/Export.h>
#include <dfhack/PluginManager.h>
#include <dfhack/modules/Items.h>
#include <dfhack/modules/Gui.h>
#include <vector>
#include <string>
#include <string.h>
using std::vector;
using std::string;
using namespace DFHack;
DFhackCExport command_result df_dumpitems (Core * c, vector <string> & parameters);
DFhackCExport command_result df_itscanvec1 (Core * c, vector <string> & parameters);
DFhackCExport const char * plugin_name ( void )
{
return "itemhacks";
}
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands)
{
commands.clear();
commands.push_back(PluginCommand("dumpitems", "Dump items...", df_dumpitems));
commands.push_back(PluginCommand("itscanvec1", "Dump items that have the first vector valid.", df_itscanvec1));
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( Core * c )
{
return CR_OK;
}
DFhackCExport command_result df_itscanvec1 (Core * c, vector <string> & parameters)
{
c->Suspend();
DFHack::Items * Items = c->getItems();
Items->Start();
std::vector<t_item *> p_items;
Items->readItemVector(p_items);
for(int i = 0; i < p_items.size();i++)
{
t_item * itm = p_items[i];
if(itm->unk2.size())
{
c->con.print("Found %x, size %d\n",itm,itm->unk2.size());
}
}
c->Resume();
return CR_OK;
}
DFhackCExport command_result df_dumpitems (Core * c, vector <string> & parameters)
{
c->Suspend();
bool print_hex = false;
if(parameters.size() && parameters[0] == "hex")
print_hex = true;
DFHack::Materials * Materials = c->getMaterials();
Materials->ReadAllMaterials();
DFHack::Gui * Gui = c->getGui();
DFHack::Items * Items = c->getItems();
Items->Start();
int32_t x,y,z;
Gui->getCursorCoords(x,y,z);
std::vector<t_item *> p_items;
Items->readItemVector(p_items);
uint32_t size = p_items.size();
for(size_t 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
&& !(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;
c->con.print(
"%5d: addr:0x%08x %6d %08x (%d,%d,%d) vptr:0x%08x [%d] *%d %s - %s\n",
i, itm.base, itm.base->id, itm.base->flags.whole,
itm.base->x, itm.base->y, itm.base->z,
itm.base->vptr,
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)
c->con << Items->dumpAccessors(itm) << endl;
*/
/*
if (print_refs) {
DFHack::DfVector<uint32_t> p_refs(p, itm.origin + ref_vector);
for (size_t j = 0; j < p_refs.size(); j++) {
uint32_t vptr = p->readDWord(p_refs[j]);
uint32_t val = p->readDWord(p_refs[j]+4);
c->con.print("\t-> %d \t%s\n", int(val), p->readClassName(vptr).c_str());
}
}
*/
}
c->Resume();
return CR_OK;
}

@ -113,181 +113,6 @@ int main (int argc, char *argv[])
}
}
}
/*
printf("type\tvtable\tname\tquality\tdecorate\n");
for (i=0;i<size;i++)
{
uint32_t curItem = p_items[i];
uint32_t vtable = p->readDWord(p_items[i]);
uint32_t func0 = p->readDWord(vtable);
uint64_t funct0 = p->readQuad(func0);
uint32_t func1 = p->readDWord(vtable+0x238);
uint64_t funct1 = p->readQuad(func1);
uint32_t func2 = p->readDWord(vtable+0x288);
uint64_t funct2 = p->readQuad(func2);
uint32_t type = (funct0>>8)&0xffff;
uint32_t funcB = p->readDWord(vtable + 4);
uint32_t funcC = p->readDWord(vtable + 8);
uint32_t funcD = p->readDWord(vtable + 12);
uint64_t funcBt = p->readQuad(funcB);
uint64_t funcCt = p->readQuad(funcC);
uint64_t funcDt = p->readQuad(funcD);
int16_t typeB = -1;
int16_t typeC = -1;
int32_t typeD = -1;
uint32_t quality = 0;
bool hasDecorations;
string desc = p->readClassName(vtable);
DFHack::dfh_item itm;
Items->readItem(p_items[i], itm);
if ( (funct0&0xFFFFFFFFFF000000LL) != 0xCCCCC30000000000LL )
{
if (funct0 == 0xCCCCCCCCCCC3C033LL)
type = 0;
else
printf("bad type function address=%p", (void*)func0);
}
if (funct1 == 0xC300000092818B66LL)
quality = p->readWord(p_items[i]+0x92);
if (funct1 == 0xC300000082818B66LL)
quality = p->readWord(p_items[i]+0x82);
else if (funct1 == 0xCCCCCCCCCCC3C033LL)
quality = 0;
else
printf("bad quality function address=%p\n", (void*) func1);
if (funct2 == 0xCCCCCCCCCCC3C032LL)
hasDecorations = false;
else if (funct2 == 0xCCCCCCCCCCC301B0LL)
hasDecorations = true;
else
printf("bad decoration function address=%p\n", (void*) func2);
if (funcBt == 0xCCCCCCCCC3FFC883LL)
typeB = -1;
else
{
uint64_t funcBtEnd = p->readQuad(funcB+8);
if (
((funcBt&0xFFFFFFFF0000FFFFLL) == 0x8B6600000000818BLL) &&
((funcBtEnd&0xFFFFFFFFFFFF00FFLL) == 0xCCCCCCCCCCC30040LL) )
{
uint32_t off1 = (funcBt>>16) & 0xffff;
uint32_t off2 = (funcBtEnd>>8) & 0xff;
uint32_t pt1 = p->readDWord(p_items[i] + off1);
typeB = p->readWord(pt1 + off2);
}
else if ((funcBt&0xFFFFFF0000FFFFFFLL)==0xC300000000818B66LL)
{
uint32_t off1 = (funcBt>>24) & 0xffff;
typeB = p->readWord(p_items[i] + off1);
}
else if ( (funcBt&0x000000FF00FFFFFFLL) == 0x000000C300418B66LL )
{
uint32_t off1 = (funcBt>>24) & 0xff;
typeB = p->readWord(p_items[i] + off1);
}
else
printf("bad typeB func @%p\n", (void*) funcB);
}
if (funcCt == 0xCCCCCCCCC3FFC883LL)
typeC = -1;
else if ( (funcCt&0xFFFFFF0000FFFFFFLL) == 0xC300000000818B66LL )
{
uint32_t off1 = (funcCt>>24)&0xffff;
typeC = p->readWord(p_items[i] + off1);
}
else if ( (funcCt&0x000000FF00FFFFFFLL) == 0x000000C300418B66LL )
{
uint32_t off1 = (funcCt>>24) & 0xff;
typeC = p->readWord(p_items[i] + off1);
}
else if ( (funcCt&0x00000000FF00FFFFLL) == 0x00000000C300418BLL )
{
uint32_t off1 = (funcCt>>16) & 0xff;
typeC = p->readWord(p_items[i] + off1);
}
else
printf("bad typeC func @%p\n", (void*) funcC);
if (funcDt == 0xCCCCCCCCC3FFC883LL)
typeD = -1;
else if ( (funcDt&0xFFFFFFFF0000FFFFLL) == 0xCCC300000000818BLL )
{
uint32_t off1 = (funcDt>>16) & 0xffff;
typeD = p->readWord(p_items[i] + off1);
}
else if ( (funcDt&0xFFFFFF0000FFFFFFLL) == 0xC30000000081BF0FLL )
{
uint32_t off1 = (funcDt>>24) & 0xffff;
typeD = p->readWord(p_items[i] + off1);
}
else if ( (funcDt&0x000000FF00FFFFFFLL) == 0x000000C30041BF0FLL )
{
uint32_t off1 = (funcDt>>24) & 0xff;
typeD = p->readWord(p_items[i] + off1);
}
else if ( (funcDt&0x000000FF00FFFFFFLL) == 0x000000C300418B66LL )
{
uint32_t off1 = (funcDt>>24) & 0xff;
typeD = p->readWord(p_items[i] + off1);
}
else if ( (funcDt&0x00000000FF00FFFFLL) == 0x00000000C300418BLL )
{
uint32_t off1 = (funcDt>>16) & 0xff;
typeD = p->readDWord(p_items[i] + off1);
}
else
printf("bad typeD func @%p\n", (void*) funcD);
// printf("%p\t%.16LX\t", (void*) func2, funct2);
printf("%d\t%p\t%s\t%d\t[%d,%d,%d]", type, (void*)vtable, desc.c_str(), quality,
typeB, typeC, typeD);
printf("\t%s", Items->getItemDescription(p_items[i], Materials).c_str());
// printf("\t%p\t%.16LX", (void *) funcD, funcDt);
if( (type!=itm.matdesc.itemType) || (typeB!=itm.matdesc.subType) || (typeC!=itm.matdesc.subIndex) || (typeD!=itm.matdesc.index) || (quality!=itm.quality) )
printf("\tbad[%d,%d,%d,%d]", itm.matdesc.itemType, itm.matdesc.subType, itm.matdesc.subIndex, itm.matdesc.index);
if (hasDecorations)
{
bool sep = false;
printf("\tdeco=[");
uint32_t decStart = p->readDWord(p_items[i] + 0x90); // 0xAC pre .13
uint32_t decEnd = p->readDWord(p_items[i] + 0x94); // 0xB0 pre .13
if (decStart != decEnd)
{
for (j=decStart;j<decEnd;j+=4)
{
uint32_t decoration = p->readDWord(j);
uint32_t dvtable = p->readDWord(decoration);
string ddesc = p->readClassName(dvtable);
uint32_t dtypefunc = p->readDWord(dvtable + 20);
uint64_t dtypefunct = p->readQuad(dtypefunc);
uint32_t dtypeC = p->readWord(decoration + 0x4);
uint32_t dtypeD = p->readDWord(decoration + 0x8);
uint32_t dtype = 0;
uint32_t dqual = p->readWord(decoration + 20);
if ( (dtypefunct&0xFFFFFFFFFFFF00FFLL) == 0xCCCCC300000000B8LL)
dtype = (dtypefunct>>8)&0xfffffff;
else if ( dtypefunct == 0xCCCCCCCCCCC3C033LL)
dtype = 0;
else
printf("bad decoration type function, address=%p\n", (void*) dtypefunc);
if (sep)
printf(",");
//printf("%s[t=%d,q=%d,%s{%d,%d}]", ddesc.c_str(), dtype, dqual, getMatDesc(-1, dtypeC, dtypeD).c_str(), dtypeC, dtypeD);
sep = true;
}
}
printf("]");
}
printf("\n");
}
*/
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();