Fix accessor mess I made. Added Accessor description dump to the dfitemdump tool and Items module.

develop
Petr Mrázek 2011-04-14 01:42:03 +02:00
parent 2aad508d2b
commit 1a8c27ce01
5 changed files with 164 additions and 42 deletions

@ -1769,6 +1769,7 @@
<Group name="job">
<Offset name="id" value="0x08" />
<Offset name="type" value="0x40" />
</Group>
</Group>
<Group name="Vegetation">
@ -1961,6 +1962,7 @@
</Group>
<Group name="job" valid="false">
<Offset name="id" valid="true" />
<Offset name="type" valid="true" />
</Group>
</Group>
<Group name="Maps" valid="true">

@ -125,6 +125,8 @@ public:
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);
private:
class Private;
Private* d;

@ -25,6 +25,7 @@ distribution.
#include "Internal.h"
#include <string>
#include <sstream>
#include <vector>
#include <cstdio>
#include <map>
@ -64,9 +65,11 @@ private:
int32_t offset2;
Process * p;
DataWidth dataWidth;
uint32_t method;
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);
bool isConstant();
};
@ -96,6 +99,7 @@ private:
public:
ItemDesc(uint32_t VTable, Process * p);
bool readItem(uint32_t itemptr, dfh_item & item);
std::string dumpAccessors();
std::string className;
uint32_t vtable;
uint32_t mainType;
@ -178,22 +182,22 @@ Accessor::Accessor(uint32_t function, Process *p)
this->constant = 0;
return;
}
uint32_t ptr = function;
method = function;
int data_reg = -1;
uint64_t v = p->readQuad(ptr);
uint64_t v = p->readQuad(method);
if (do_match(ptr, v, 2, 0xFFFF, 0xC033) ||
do_match(ptr, v, 2, 0xFFFF, 0xC031)) // XOR EAX, EAX
if (do_match(method, v, 2, 0xFFFF, 0xC033) ||
do_match(method, v, 2, 0xFFFF, 0xC031)) // XOR EAX, EAX
{
data_reg = 0;
this->constant = 0;
}
else if (do_match(ptr, v, 3, 0xFFFFFF, 0xFFC883)) // OR EAX, -1
else if (do_match(method, v, 3, 0xFFFFFF, 0xFFC883)) // OR EAX, -1
{
data_reg = 0;
this->constant = -1;
}
else if (do_match(ptr, v, 5, 0xFF, 0xB8)) // MOV EAX,imm
else if (do_match(method, v, 5, 0xFF, 0xB8)) // MOV EAX,imm
{
data_reg = 0;
this->constant = (v>>8) & 0xFFFFFFFF;
@ -204,22 +208,22 @@ Accessor::Accessor(uint32_t function, Process *p)
int ptr_reg = 1, tmp; // ECX
// MOV REG,[ESP+4]
if (do_match(ptr, v, 4, 0xFFFFC7FFU, 0x0424448B))
if (do_match(method, v, 4, 0xFFFFC7FFU, 0x0424448B))
{
ptr_reg = (v>>11)&7;
v = p->readQuad(ptr);
v = p->readQuad(method);
}
if (match_MOV_MEM(ptr, v, ptr_reg, tmp, this->offset1, xsize)) {
if (match_MOV_MEM(method, v, ptr_reg, tmp, this->offset1, xsize)) {
data_reg = tmp;
this->type = ACCESSOR_INDIRECT;
this->dataWidth = xsize;
if (xsize == Data32)
{
v = p->readQuad(ptr);
v = p->readQuad(method);
if (match_MOV_MEM(ptr, v, data_reg, tmp, this->offset2, xsize)) {
if (match_MOV_MEM(method, v, data_reg, tmp, this->offset2, xsize)) {
data_reg = tmp;
this->type = ACCESSOR_DOUBLE_INDIRECT;
this->dataWidth = xsize;
@ -228,9 +232,9 @@ Accessor::Accessor(uint32_t function, Process *p)
}
}
v = p->readQuad(ptr);
v = p->readQuad(method);
if (data_reg == 0 && do_match(ptr, v, 1, 0xFF, 0xC3)) // RET
if (data_reg == 0 && do_match(method, v, 1, 0xFF, 0xC3)) // RET
return;
else
{
@ -248,6 +252,55 @@ bool Accessor::isConstant()
return false;
}
string Accessor::dump()
{
stringstream sstr;
sstr << hex << "method @0x" << method << dec << " ";
switch(type)
{
case ACCESSOR_CONSTANT:
sstr << "Constant: " << dec << constant;
break;
case ACCESSOR_INDIRECT:
switch(dataWidth)
{
case Data32:
sstr << "int32_t ";
break;
case DataSigned16:
sstr << "int16_t ";
break;
case DataUnsigned16:
sstr << "uint16_t ";
break;
default:
sstr << "unknown ";
break;
}
sstr << hex << "[obj + 0x" << offset1 << " ]";
break;
case ACCESSOR_DOUBLE_INDIRECT:
switch(dataWidth)
{
case Data32:
sstr << "int32_t ";
break;
case DataSigned16:
sstr << "int16_t ";
break;
case DataUnsigned16:
sstr << "uint16_t ";
break;
default:
sstr << "unknown ";
break;
}
sstr << hex << "[ [obj + 0x" << offset1 << " ] + 0x" << offset2 << " ]";
break;
}
return sstr.str();
}
int32_t Accessor::getValue(uint32_t objectPtr)
{
int32_t offset = this->offset1;
@ -283,8 +336,10 @@ int32_t Accessor::getValue(uint32_t objectPtr)
Accessor * buildAccessor (OffsetGroup * I, Process * p, const char * name, uint32_t vtable)
{
int32_t offset;
if(I->getSafeOffset("item_type_accessor",offset))
if(I->getSafeOffset(name,offset))
{
return new Accessor( p->readDWord( vtable + offset ), p);
}
else
{
fprintf(stderr,"Missing offset for item accessor \"%s\"\n", name);
@ -324,6 +379,19 @@ ItemDesc::ItemDesc(uint32_t VTable, Process *p)
}
}
string ItemDesc::dumpAccessors()
{
std::stringstream outss;
outss << "MainType :" << AMainType->dump() << endl;
outss << "ASubType :" << ASubType->dump() << endl;
outss << "ASubIndex :" << ASubIndex->dump() << endl;
outss << "AIndex :" << AIndex->dump() << endl;
outss << "AQuality :" << AQuality->dump() << endl;
outss << "AWear :" << AWear->dump() << endl;
return outss.str();
}
bool ItemDesc::readItem(uint32_t itemptr, DFHack::dfh_item &item)
{
p->read(itemptr, sizeof(t_item), (uint8_t*)&item.base);
@ -485,19 +553,38 @@ std::string Items::getItemClass(int32_t index)
std::string Items::getItemDescription(const dfh_item & item, Materials * Materials)
{
std::string out;
std::stringstream outss;
switch(item.quality)
{
case 0: break;
case 1: out.append("Well crafted "); break;
case 2: out.append("Finely crafted "); break;
case 3: out.append("Superior quality "); break;
case 4: out.append("Exceptionnal "); break;
case 5: out.append("Masterful "); break;
default: out.append("Crazy quality "); break;
case 0:
outss << "Ordinary ";
break;
case 1:
outss << "Well crafted ";
break;
case 2:
outss << "Finely crafted ";
break;
case 3:
outss << "Superior quality ";
break;
case 4:
outss << "Exceptionnal ";
break;
case 5:
outss << "Masterful ";
break;
default: outss << "Crazy quality " << item.quality << " "; break;
}
out.append(Materials->getDescription(item.matdesc));
out.append(" ");
out.append(this->getItemClass(item.matdesc.itemType));
return out;
outss << Materials->getDescription(item.matdesc) << " " << getItemClass(item.matdesc.itemType);
return outss.str();
}
/// dump offsets used by accessors of a valid item to a string
std::string Items::dumpAccessors(const dfh_item & item)
{
uint32_t vtable = item.base.vtable;
std::map< uint32_t, ItemDesc* >::const_iterator it = d->descVTable.find(vtable);
ItemDesc * desc = it->second;
return desc->dumpAccessors();
}

@ -212,12 +212,20 @@ void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature)
cout << Materials->raceEx[creature.race].castes[creature.caste].ColorModifier[i].part << " ";
uint32_t color = Materials->raceEx[creature.race].castes[creature.caste].ColorModifier[i].colorlist[creature.color[i]];
if(color<Materials->color.size())
{
cout << Materials->color[color].name << "["
<< (unsigned int) (Materials->color[color].r*255) << ":"
<< (unsigned int) (Materials->color[color].v*255) << ":"
<< (unsigned int) (Materials->color[color].b*255) << "]";
else
<< (unsigned int) (Materials->color[color].r*255) << ":"
<< (unsigned int) (Materials->color[color].v*255) << ":"
<< (unsigned int) (Materials->color[color].b*255) << "]";
}
else if (color < Materials->alldesc.size())
{
cout << Materials->alldesc[color].id;
}
else
{
cout << "Unknown color " << color << endl;
}
if( Materials->raceEx[creature.race].castes[creature.caste].ColorModifier[i].startdate > 0 )
{
if( (Materials->raceEx[creature.race].castes[creature.caste].ColorModifier[i].startdate <= dayoflife) &&
@ -467,7 +475,7 @@ int main (int numargs, char ** args)
Materials->ReadPlantMaterials();
Materials->ReadCreatureTypes();
Materials->ReadCreatureTypesEx();
Materials->ReadDescriptorColors();
//Materials->ReadDescriptorColors();
if(!Tran->Start())
{

@ -10,7 +10,7 @@
#include <vector>
#include <cstring>
using namespace std;
#define DFHACK_WANT_MISCUTILS
#include <DFHack.h>
#include <dfhack/DFVector.h>
@ -35,13 +35,16 @@ int main ()
}
DFHack::Materials * Materials = DF->getMaterials();
Materials->ReadAllMaterials();
DFHack::Gui * Gui = DF->getGui();
DFHack::Items * Items = DF->getItems();
Items->Start();
DFHack::VersionInfo * mem = DF->getMemoryInfo();
p = DF->getProcess();
int32_t x,y,z;
Gui->getCursorCoords(x,y,z);
// 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"));
@ -52,15 +55,35 @@ int main ()
DFHack::dfh_item itm;
memset(&itm, 0, sizeof(DFHack::dfh_item));
Items->readItem(p_items[i],itm);
printf(
"%5d: %08x %08x (%d,%d,%d) #%08x [%d] %s - %s\n",
i, itm.origin, 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()
);
if(x != -30000)
{
if(itm.base.x == x && itm.base.y == y && itm.base.z == z)
{
printf(
"%5d: %08x %08x (%d,%d,%d) #%08x [%d] %s - %s\n",
i, itm.origin, 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()
);
hexdump(DF,p_items[i],0x100);
cout << Items->dumpAccessors(itm) << endl;
}
}
else
{
printf(
"%5d: %08x %08x (%d,%d,%d) #%08x [%d] %s - %s\n",
i, itm.origin, 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()
);
}
}
/*
printf("type\tvtable\tname\tquality\tdecorate\n");