Big Items refactor, made all the Accessor offsets optional.

develop
Petr Mrázek 2011-04-11 22:13:06 +02:00
parent 77f0885d9e
commit 212500ee00
11 changed files with 293 additions and 390 deletions

@ -1,7 +1,7 @@
<?xml version="1.0"?>
<DFHack>
<Base name="DF40d.xx">
<Offsets>
<Base name="DF40d.xx">
<Offsets>
<Group name="vector" description="An STL vector.">
<HexValue name="sizeof" description="The total size in bytes." />
<Offset name="start" description="The offset where the actual start/end/alloc_end triplet is." />
@ -31,16 +31,16 @@
<Offset name="second_words" description="Array of 7 indexes into the language vectors."/>
</Group>
</Offsets>
</Base>
<Version name="40d" base="DF40d.xx" os="windows">
<MD5 value="2c686c26307dcccd7c36cc79737ebe4f" />
<PETimeStamp value="0x48C330DF" />
<Offsets>
</Base>
<Version name="40d" base="DF40d.xx" os="windows">
<MD5 value="2c686c26307dcccd7c36cc79737ebe4f" />
<PETimeStamp value="0x48C330DF" />
<Offsets>
<Group name="vector">
<HexValue name="sizeof" value="0x10" />
<Offset name="start" value="0x4" />
<!--
Maybe (fits offsets):
Maybe (fits offsets):
Vector layout in MSVC 8:
DWORD Allocator?
DWORD Start
@ -61,8 +61,8 @@
<Offset name="nick" value="0x1C" />
<Offset name="second_words" value="0x38" />
</Group>
</Offsets>
</Version>
</Offsets>
</Version>
<Base name="DF2010">
<Traits>
<Trait name="Nervousness" id="0" level_5="Is a nervous wreck" level_4="Is always tense and jittery" level_3="Is often nervous" level_2="Has a calm demeanor" level_1="Has a very calm demeanor" level_0="Has an incredibly calm demeanor" />
@ -1916,33 +1916,12 @@
<Address name="language_vector" value="0x016e553c"/>
<Address name="translation_vector" value="0x016e551c"/>
</Group>
<!--
<Group name="Vegetation" valid="false">
<Address name="vector"/>
<Offset name="tree_desc_offset" valid="true"/>
</Group>
-->
<Group name="Items" valid="false">
<!-- most of those seem completely unused! -->
<Address name="items_vector" />
List of offsets in the VTable :
<Offset name="item_type_accessor" />
<Offset name="item_subtype_accessor" />
<Offset name="item_subindex_accessor" />
<Offset name="item_index_accessor" />
<Offset name="item_quality_accessor" />
<Offset name="item_improvement_vector" />
<Offset name="item_improvement_subindex" />
<Offset name="item_improvement_index" />
<Offset name="item_improvement_quality" />
<Offset name="item_type_accessor" /> (in the vtable)
</Group>
<Group name="Items" valid="false" />
<Group name="World" valid="false">
<Address name="current_tick" description="Current time of the year" />
<Address name="current_year" description="Current year" />
<Address name="current_weather" value="0x14c9bb8" valid="true" />
</Group>
</Offsets>
</Version>
<Version name="v0.31.19 SDL" os="windows" base="v0.31.18 SDL">
@ -1966,10 +1945,6 @@
<Group name="creature">
<Group name="advanced">
<!--
<Offset name="pregnancy" value="0x214" /> maybe?
<Offset name="pregnancy_ptr" value="0x218" /> maybe?
-->
<Offset name="birth_year" value="0x224" />
<Offset name="birth_time" value="0x228" />
<Offset name="inventory_vector" value="0x288" />
@ -1986,15 +1961,6 @@
</Group>
<Group name="job" valid="false">
<Offset name="id" valid="true" />
<Offset name="materials_vector" /> MISSING!
<Offset name="type" /> MISSING!
<Group name="material">
<Offset name="flags" /> MISSING!
<Offset name="maintype" /> MISSING!
<Offset name="sectype1" /> MISSING!
<Offset name="sectype2" /> MISSING!
<Offset name="sectype3" /> MISSING!
</Group>
</Group>
</Group>
<Group name="Maps" valid="true">
@ -2076,22 +2042,6 @@
<Address name="language_vector" value="0x0171ea94"/>
<Address name="translation_vector" value="0x0171eab4"/>
</Group>
<!--
<Group name="Items" valid="false">
<Address name="items_vector" />
List of offsets in the VTable :
<Offset name="item_type_accessor" />
<Offset name="item_subtype_accessor" />
<Offset name="item_subindex_accessor" />
<Offset name="item_index_accessor" />
<Offset name="item_quality_accessor" />
<Offset name="item_improvement_vector" />
<Offset name="item_improvement_subindex" />
<Offset name="item_improvement_index" />
<Offset name="item_improvement_quality" />
<Offset name="item_type_accessor" /> (in the vtable)
</Group>
-->
</Offsets>
</Version>
<Version name="v0.31.20 SDL" os="windows" base="v0.31.19 SDL" rebase="0x6000" >
@ -2181,11 +2131,6 @@
</Group>
<Group name="Maps">
<Group name="block">
<!--
<Offset name="vein_vector" value="0x8" />
<Offset name="feature_local" value="0x24" />
<Offset name="feature_global" value="0x28" />
-->
<Offset name="mystery_offset" value="0x2C" />
<Offset name="vegetation_vector" value="0x64" />
<Offset name="type" value="0x7e" />

@ -319,6 +319,17 @@ uint32_t OffsetGroup::getAddress (const string & key)
throw Error::MissingMemoryDefinition("address", getFullName() + key);
}
// Get named offset, return bool instead of throwing exceptions
bool OffsetGroup::getSafeAddress (const string & key, uint32_t & out)
{
uint32_Iter iter = OGd->addresses.find(key);
if(iter != OGd->addresses.end() && (*iter).second.first == IS_VALID)
{
out = (*iter).second.second;
return true;
}
return false;
}
// Get named offset
int32_t OffsetGroup::getOffset (const string & key)
@ -335,6 +346,18 @@ int32_t OffsetGroup::getOffset (const string & key)
throw Error::MissingMemoryDefinition("offset", getFullName() + key);
}
// Get named offset, return bool instead of throwing exceptions
bool OffsetGroup::getSafeOffset (const string & key, int32_t & out)
{
int32_Iter iter = OGd->offsets.find(key);
if(iter != OGd->offsets.end() && (*iter).second.first == IS_VALID)
{
out = (*iter).second.second;
return true;
}
return false;
}
// Get named numerical value
uint32_t OffsetGroup::getHexValue (const string & key)

@ -37,9 +37,9 @@ extern "C" {
DFHACK_EXPORT int Items_Start(DFHackObject* items);
DFHACK_EXPORT int Items_Finish(DFHackObject* items);
DFHACK_EXPORT char* Items_getItemDescription(DFHackObject* items, uint32_t itemptr, DFHackObject* mats);
DFHACK_EXPORT char* Items_getItemDescription(DFHackObject* items, dfh_item* item, DFHackObject* mats);
DFHACK_EXPORT char* Items_getItemClass(DFHackObject* items, int32_t index);
DFHACK_EXPORT int Items_getItemData(DFHackObject* items, uint32_t itemptr, t_item* item);
DFHACK_EXPORT int Items_getItemData(DFHackObject* items, uint32_t itemptr, dfh_item* item);
#ifdef __cplusplus
}

@ -106,73 +106,6 @@ struct t_name
bool has_name;
};
//raw
struct t_item_df40d
{
uint32_t vtable;
uint16_t x;
uint16_t y;
uint16_t z;
uint32_t flags;
uint32_t unk1;
uint32_t unk2;
uint32_t ID;
// not complete
};
//From http://dwarffortresswiki.net/index.php/User:Rick/Memory_research
//They all seem to be valid on 40d as well
struct naked_itemflags
{
unsigned int on_ground : 1; // 0000 0001 Item on ground
unsigned int in_job : 1; // 0000 0002 Item currently being used in a job
unsigned int u_ngrd1 : 1; // 0000 0004 unknown, unseen
unsigned int in_inventory : 1; // 0000 0008 Item in a creature or workshop inventory
unsigned int u_ngrd2 : 1; // 0000 0010 unknown, lost (artifact)?, unseen
unsigned int in_building : 1; // 0000 0020 Part of a building (including mechanisms, bodies in coffins)
unsigned int u_ngrd3 : 1; // 0000 0040 unknown, unseen
unsigned int dead_dwarf : 1; // 0000 0080 Dwarf's dead body or body part
unsigned int rotten : 1; // 0000 0100 Rotten food
unsigned int spider_web : 1; // 0000 0200 Thread in spider web
unsigned int construction : 1; // 0000 0400 Material used in construction
unsigned int u_ngrd5 : 1; // 0000 0800 unknown, unseen
unsigned int unk3 : 1; // 0000 1000 unknown, unseen
unsigned int u_ngrd6 : 1; // 0000 2000 unknown, unseen
unsigned int foreign : 1; // 0000 4000 Item is imported
unsigned int u_ngrd7 : 1; // 0000 8000 unknown, unseen
unsigned int owned : 1; // 0001 0000 Item is owned by a dwarf
unsigned int unk4 : 1; // 0002 0000 unknown, unseen
unsigned int artifact1 : 1; // 0004 0000 Artifact ?
unsigned int forbid : 1; // 0008 0000 Forbidden item
unsigned int unk5 : 1; // 0010 0000 unknown, unseen
unsigned int dump : 1; // 0020 0000 Designated for dumping
unsigned int on_fire: 1; // 0040 0000 Indicates if item is on fire, Will Set Item On Fire if Set!
unsigned int melt : 1; // 0080 0000 Designated for melting, if applicable
// 0100 0000 - 8000 0000
unsigned int hidden : 1; // 0100 0000 Hidden item
unsigned int in_chest : 1; // 0200 0000 Stored in chest/part of well?
unsigned int unk6 : 1; // 0400 0000 unknown, unseen
unsigned int artifact2 : 1; // 0800 0000 Artifact ?
unsigned int unk8 : 1; // 1000 0000 unknown, unseen
unsigned int unk9 : 1; // 2000 0000 unknown, set when viewing details
unsigned int unk10 : 1; // 4000 0000 unknown, unseen
unsigned int unk11 : 1; // 8000 0000 unknown, unseen
};
union t_itemflags
{
uint32_t whole;
naked_itemflags bits;
};
struct t_note
{
char symbol;
@ -197,7 +130,7 @@ struct t_settlement
int16_t local_y1;
int16_t local_y2;
};
struct t_attrib
{
uint32_t level;

@ -77,6 +77,9 @@ namespace DFHack
std::string getString (const std::string & key);
OffsetGroup * getGroup ( const std::string & name );
bool getSafeOffset (const std::string & key, int32_t & out);
bool getSafeAddress (const std::string & key, uint32_t & out);
void setOffset (const std::string& key, const std::string& value, const DFHack::INVAL_TYPE inval = IS_VALID);
void setOffsetValidity(const std::string& key, const DFHack::INVAL_TYPE inval = IS_VALID);
void setAddress (const std::string& key, const std::string& value, const DFHack::INVAL_TYPE inval = IS_VALID);

@ -3,7 +3,7 @@
#define CL_MOD_ITEMS
/*
* Creatures
* Items!
*/
#include "dfhack/DFExport.h"
#include "dfhack/DFModule.h"
@ -15,22 +15,92 @@ namespace DFHack
class Context;
class DFContextShared;
struct t_item_header
//From http://dwarffortresswiki.net/index.php/User:Rick/Memory_research
//They all seem to be valid on 40d as well
union t_itemflags
{
uint32_t whole;
struct
{
unsigned int on_ground : 1; // 0000 0001 Item on ground
unsigned int in_job : 1; // 0000 0002 Item currently being used in a job
unsigned int u_ngrd1 : 1; // 0000 0004 unknown, unseen
unsigned int in_inventory : 1; // 0000 0008 Item in a creature or workshop inventory
unsigned int u_ngrd2 : 1; // 0000 0010 unknown, lost (artifact)?, unseen
unsigned int in_building : 1; // 0000 0020 Part of a building (including mechanisms, bodies in coffins)
unsigned int u_ngrd3 : 1; // 0000 0040 unknown, unseen
unsigned int dead_dwarf : 1; // 0000 0080 Dwarf's dead body or body part
unsigned int rotten : 1; // 0000 0100 Rotten food
unsigned int spider_web : 1; // 0000 0200 Thread in spider web
unsigned int construction : 1; // 0000 0400 Material used in construction
unsigned int u_ngrd5 : 1; // 0000 0800 unknown, unseen
unsigned int unk3 : 1; // 0000 1000 unknown, unseen
unsigned int u_ngrd6 : 1; // 0000 2000 unknown, unseen
unsigned int foreign : 1; // 0000 4000 Item is imported
unsigned int u_ngrd7 : 1; // 0000 8000 unknown, unseen
unsigned int owned : 1; // 0001 0000 Item is owned by a dwarf
unsigned int unk4 : 1; // 0002 0000 unknown, unseen
unsigned int artifact1 : 1; // 0004 0000 Artifact ?
unsigned int forbid : 1; // 0008 0000 Forbidden item
unsigned int unk5 : 1; // 0010 0000 unknown, unseen
unsigned int dump : 1; // 0020 0000 Designated for dumping
unsigned int on_fire: 1; // 0040 0000 Indicates if item is on fire, Will Set Item On Fire if Set!
unsigned int melt : 1; // 0080 0000 Designated for melting, if applicable
// 0100 0000 - 8000 0000
unsigned int hidden : 1; // 0100 0000 Hidden item
unsigned int in_chest : 1; // 0200 0000 Stored in chest/part of well?
unsigned int unk6 : 1; // 0400 0000 unknown, unseen
unsigned int artifact2 : 1; // 0800 0000 Artifact ?
unsigned int unk8 : 1; // 1000 0000 unknown, unseen
unsigned int unk9 : 1; // 2000 0000 unknown, set when viewing details
unsigned int unk10 : 1; // 4000 0000 unknown, unseen
unsigned int unk11 : 1; // 8000 0000 unknown, unseen
};
};
struct t_item
{
uint32_t vtable;
int16_t x;
int16_t y;
int16_t z;
t_itemflags flags;
};
struct t_item
struct dfh_item
{
t_item_header header;
t_item base;
t_material matdesc;
int32_t quantity;
int32_t quality;
int16_t wear_level;
uint32_t origin;
};
/*
//raw
struct t_item_df40d
{
uint32_t vtable;
uint16_t x;
uint16_t y;
uint16_t z;
uint32_t flags;
uint32_t unk1;
uint32_t unk2;
uint32_t ID;
// not complete
};
*/
struct t_improvement
{
@ -45,11 +115,16 @@ public:
~Items();
bool Start();
bool Finish();
std::string getItemDescription(uint32_t itemptr, Materials * Materials);
/// get a string describing an item
std::string getItemDescription(const dfh_item & item, Materials * Materials);
/// get a short name for an item
std::string getItemClass(int32_t index);
bool getItemData(uint32_t itemptr, t_item & item);
int32_t getItemOwnerID(uint32_t itemptr);
void setItemFlags(uint32_t itemptr, t_itemflags new_flags);
/// read an item, including the extra attributes
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);
private:
class Private;
Private* d;

@ -95,7 +95,7 @@ private:
bool hasDecoration;
public:
ItemDesc(uint32_t VTable, Process * p);
bool getItem(uint32_t itemptr, t_item & item);
bool readItem(uint32_t itemptr, dfh_item & item);
std::string className;
uint32_t vtable;
uint32_t mainType;
@ -165,18 +165,22 @@ static bool match_MOV_MEM(uint32_t &ptr, uint64_t v, int in_reg, int &out_reg, i
}
else
return false;
return match_MEM_ACCESS(ptr, v, prefix, in_reg, out_reg, offset);
}
// FIXME: this is crazy
Accessor::Accessor(uint32_t function, Process *p)
{
this->p = p;
this->type = ACCESSOR_CONSTANT;
if(!p)
{
this->constant = 0;
return;
}
uint32_t ptr = function;
uint64_t v = p->readQuad(ptr);
int data_reg = -1;
uint64_t v = p->readQuad(ptr);
if (do_match(ptr, v, 2, 0xFFFF, 0xC033) ||
do_match(ptr, v, 2, 0xFFFF, 0xC031)) // XOR EAX, EAX
@ -214,7 +218,7 @@ Accessor::Accessor(uint32_t function, Process *p)
if (xsize == Data32)
{
v = p->readQuad(ptr);
if (match_MOV_MEM(ptr, v, data_reg, tmp, this->offset2, xsize)) {
data_reg = tmp;
this->type = ACCESSOR_DOUBLE_INDIRECT;
@ -223,9 +227,9 @@ Accessor::Accessor(uint32_t function, Process *p)
}
}
}
v = p->readQuad(ptr);
if (data_reg == 0 && do_match(ptr, v, 1, 0xFF, 0xC3)) // RET
return;
else
@ -275,44 +279,62 @@ 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)
{
int32_t offset;
if(I->getSafeOffset("item_type_accessor",offset))
return new Accessor( p->readDWord( vtable + offset ), p);
else
{
fprintf(stderr,"Missing offset for item accessor \"%s\"\n", name);
return new Accessor(-1,0); // dummy accessor. always returns -1
}
}
ItemDesc::ItemDesc(uint32_t VTable, Process *p)
{
int32_t funcOffsetA, funcOffsetB, funcOffsetC, funcOffsetD, funcOffsetQuality, funcOffsetWear;
OffsetGroup * Items = p->getDescriptor()->getGroup("Items");
uint32_t funcOffsetA = Items->getOffset("item_type_accessor");
uint32_t funcOffsetB = Items->getOffset("item_subtype_accessor");
uint32_t funcOffsetC = Items->getOffset("item_subindex_accessor");
uint32_t funcOffsetD = Items->getOffset("item_index_accessor");
uint32_t funcOffsetQuality = Items->getOffset("item_quality_accessor");
uint32_t funcOffsetWear = Items->getOffset("item_wear_accessor");
/*
* FIXME: and what about types, different sets of methods depending on class?
* what about more complex things than constants and integers?
* If this is to be generally useful, it needs much more power.
*/
AMainType = buildAccessor(Items, p, "item_type_accessor", VTable);
ASubType = buildAccessor(Items, p, "item_subtype_accessor", VTable);
ASubIndex = buildAccessor(Items, p, "item_subindex_accessor", VTable);
AIndex = buildAccessor(Items, p, "item_index_accessor", VTable);
AQuality = buildAccessor(Items, p, "item_quality_accessor", VTable);
AWear = buildAccessor(Items, p, "item_wear_accessor", VTable);
this->vtable = VTable;
this->p = p;
this->className = p->readClassName(VTable).substr(5);
this->className.resize(this->className.size()-2);
this->AMainType = new Accessor( p->readDWord( VTable + funcOffsetA ), p);
this->ASubType = new Accessor( p->readDWord( VTable + funcOffsetB ), p);
this->ASubIndex = new Accessor( p->readDWord( VTable + funcOffsetC ), p);
this->AIndex = new Accessor( p->readDWord( VTable + funcOffsetD ), p);
this->AQuality = new Accessor( p->readDWord( VTable + funcOffsetQuality ), p);
this->AWear = new Accessor( p->readDWord( VTable + funcOffsetWear ), p);
this->hasDecoration = false;
if(this->AMainType->isConstant())
this->mainType = this->AMainType->getValue(0);
if(AMainType->isConstant())
mainType = this->AMainType->getValue(0);
else
{
fprintf(stderr, "Bad item main type at function %p\n", (void*) p->readDWord( VTable + funcOffsetA ));
this->mainType = 0;
mainType = 0;
}
}
bool ItemDesc::getItem(uint32_t itemptr, DFHack::t_item &item)
bool ItemDesc::readItem(uint32_t itemptr, DFHack::dfh_item &item)
{
this->p->read(itemptr+4, sizeof(t_item_header), (uint8_t*)&item.header);
item.matdesc.itemType = this->AMainType->getValue(itemptr);
item.matdesc.subType = this->ASubType->getValue(itemptr);
item.matdesc.subIndex = this->ASubIndex->getValue(itemptr);
item.matdesc.index = this->AIndex->getValue(itemptr);
item.quality = this->AQuality->getValue(itemptr);
p->read(itemptr, sizeof(t_item), (uint8_t*)&item.base);
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 = 1; /* TODO */
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:
item.wear_level = (int16_t)this->AWear->getValue(itemptr);
@ -364,7 +386,7 @@ Items::~Items()
delete d;
}
bool Items::getItemData(uint32_t itemptr, DFHack::t_item &item)
bool Items::readItem(uint32_t itemptr, DFHack::dfh_item &item)
{
std::map<uint32_t, ItemDesc *>::iterator it;
Process * p = d->owner;
@ -381,15 +403,26 @@ bool Items::getItemData(uint32_t itemptr, DFHack::t_item &item)
else
desc = it->second;
return desc->getItem(itemptr, item);
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;
}
/*
void Items::setItemFlags(uint32_t itemptr, t_itemflags new_flags)
{
d->owner->writeDWord(itemptr + 0x0C, new_flags.whole);
}
int32_t Items::getItemOwnerID(uint32_t itemptr)
*/
int32_t Items::getItemOwnerID(const DFHack::dfh_item &item)
{
if (!d->refVectorOffset)
{
@ -398,7 +431,7 @@ int32_t Items::getItemOwnerID(uint32_t itemptr)
d->refIDOffset = Items->getOffset("owner_ref_id_field");
}
DFHack::DfVector<uint32_t> p_refs(d->owner, itemptr + d->refVectorOffset);
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++)
@ -450,8 +483,9 @@ std::string Items::getItemClass(int32_t index)
return out;
}
std::string Items::getItemDescription(uint32_t itemptr, Materials * Materials)
std::string Items::getItemDescription(const dfh_item & item, Materials * Materials)
{
/*
DFHack::t_item item;
std::string out;
@ -470,128 +504,7 @@ std::string Items::getItemDescription(uint32_t itemptr, Materials * Materials)
out.append(Materials->getDescription(item.matdesc));
out.append(" ");
out.append(this->getItemClass(item.matdesc.itemType));
return out;
}
// The OLD items code follows (40d era)
// TODO: merge with the current Items module
/*
bool API::InitReadItems(uint32_t & numitems)
{
try
{
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);
d->itemsInited = true;
numitems = d->p_itm->getSize();
return true;
}
catch (Error::AllMemdef&)
{
d->itemsInited = false;
numitems = 0;
throw;
}
}
bool API::getItemIndexesInBox(vector<uint32_t> &indexes,
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->itemsInited) return false;
indexes.clear();
uint32_t size = d->p_itm->getSize();
struct temp2{
uint16_t coords[3];
uint32_t flags;
};
temp2 temp2;
for(uint32_t i =0;i<size;i++){
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)
{
if (temp2.coords[1] >= y1 && temp2.coords[1] < y2)
{
if (temp2.coords[2] >= z1 && temp2.coords[2] < z2)
{
indexes.push_back(i);
}
}
}
}
}
return true;
}
bool API::ReadItem (const uint32_t index, t_item & item)
{
if (!d->itemsInited) return false;
t_item_df40d item_40d;
// read pointer from vector at position
uint32_t temp = d->p_itm->at (index);
//read building from memory
d->p->read (temp, sizeof (t_item_df40d), (uint8_t *) &item_40d);
// transform
int32_t type = -1;
d->offset_descriptor->resolveObjectToClassID (temp, type);
item.origin = temp;
item.vtable = item_40d.vtable;
item.x = item_40d.x;
item.y = item_40d.y;
item.z = item_40d.z;
item.type = type;
item.ID = item_40d.ID;
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
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);
//}
return true;
}
void API::FinishReadItems()
{
if(d->p_itm)
{
delete d->p_itm;
d->p_itm = NULL;
}
d->itemsInited = false;
}
*/
/*
bool API::ReadItemTypes(vector< vector< t_itemType > > & itemTypes)
{
memory_info * minfo = d->offset_descriptor;
int matgloss_address = minfo->getAddress("matgloss");
int matgloss_skip = minfo->getHexValue("matgloss_skip");
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);
vector< t_itemType > typesForVec;
for(uint32_t j =0; j<p_temp.getSize();j++)
{
t_itemType currType;
uint32_t temp = *(uint32_t *) p_temp[j];
// Mread(temp+40,sizeof(name),(uint8_t *) name);
d->p->readSTLString(temp+4,currType.id,128);
d->p->readSTLString(temp+item_type_name_offset,currType.name,128);
//stringsForVec.push_back(string(name));
typesForVec.push_back(currType);
}
itemTypes.push_back(typesForVec);
}
return true;
*/
//return out;
return getItemClass(item.matdesc.itemType);
}
*/

@ -54,11 +54,11 @@ int Items_Finish(DFHackObject* items)
//FIXME: beware of bad null-termination! I haven't tested anything here, but it seems that it could be corrupting or truncating strings.
char* Items_getItemDescription(DFHackObject* items, uint32_t itemptr, DFHackObject* mats)
char* Items_getItemDescription(DFHackObject* items, dfh_item * item, DFHackObject* mats)
{
if(items != NULL && mats != NULL)
{
std::string desc = ((DFHack::Items*)items)->getItemDescription(itemptr, (DFHack::Materials*)mats);
std::string desc = ((DFHack::Items*)items)->getItemDescription(*item, (DFHack::Materials*)mats);
if(desc.size() > 0)
{
@ -112,11 +112,11 @@ char* Items_getItemClass(DFHackObject* items, int32_t index)
return NULL;
}
int Items_getItemData(DFHackObject* items, uint32_t itemptr, t_item* item)
int Items_getItemData(DFHackObject* items, uint32_t itemptr, dfh_item* item)
{
if(items != NULL)
{
return ((DFHack::Items*)items)->getItemData(itemptr, *item);
return ((DFHack::Items*)items)->readItem(itemptr, *item);
}
return -1;

@ -544,50 +544,50 @@ std::string Materials::getDescription(t_material & mat)
//type of material only so we know which vector to retrieve
std::string Materials::getType(t_material & mat)
{
if((mat.subIndex<419) || (mat.subIndex>618))
{
if((mat.subIndex<19) || (mat.subIndex>218))
{
if(mat.subIndex)
{
if(mat.subIndex>0x292)
{
return "unknown";
}
else
{
if(mat.subIndex>=this->other.size())
{
if(mat.subIndex<0)
return "any";
if(mat.subIndex>=this->raceEx.size())
return "unknown";
return "racex";
}
else
{
if (mat.index==-1)
return "other";
else
return "other derivate";
}
}
}
else
return "inorganic";
}
else
{
if (mat.index>=this->raceEx.size())
return "unknown";
return "racex extract";
}
}
else
{
return "organic";
}
if((mat.subIndex<419) || (mat.subIndex>618))
{
if((mat.subIndex<19) || (mat.subIndex>218))
{
if(mat.subIndex)
{
if(mat.subIndex>0x292)
{
return "unknown";
}
else
{
if(mat.subIndex>=this->other.size())
{
if(mat.subIndex<0)
return "any";
if(mat.subIndex>=this->raceEx.size())
return "unknown";
return "racex";
}
else
{
if (mat.index==-1)
return "other";
else
return "other derivate";
}
}
}
else
return "inorganic";
}
else
{
if (mat.index>=this->raceEx.size())
return "unknown";
return "racex extract";
}
}
else
{
return "organic";
}
}

@ -1,28 +1,19 @@
/*
* dumps vtables, items types and class name for all items in game
* best used this way : ./dfitemdump | sort -ug
* Simple, pretty item dump example.
*/
// THIS IS NOT A GOOD EXAMPLE!
// ... just look at all the magic numbers.
// I'm not fixing it though.
// ~px
#include <stdio.h>
#include <cstdio>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <climits>
#include <vector>
#include <cstring>
using namespace std;
#include <DFHack.h>
#include <dfhack/DFVector.h>
DFHack::Materials * Materials;
DFHack::Items * Items;
int main ()
{
DFHack::Process * p;
@ -42,17 +33,36 @@ int main ()
#endif
return 1;
}
DFHack::Materials * Materials = DF->getMaterials();
Materials->ReadAllMaterials();
DFHack::Items * Items = DF->getItems();
Items->Start();
DFHack::VersionInfo * mem = DF->getMemoryInfo();
Materials = DF->getMaterials();
Materials->ReadAllMaterials();
p = DF->getProcess();
// 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();
Items = DF->getItems();
for(int i = 0; i < size; i++)
{
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()
);
}
/*
printf("type\tvtable\tname\tquality\tdecorate\n");
for (i=0;i<size;i++)
{
@ -78,9 +88,9 @@ int main ()
uint32_t quality = 0;
bool hasDecorations;
string desc = p->readClassName(vtable);
DFHack::t_item itm;
DFHack::dfh_item itm;
Items->getItemData(p_items[i], itm);
Items->readItem(p_items[i], itm);
if ( (funct0&0xFFFFFFFFFF000000LL) != 0xCCCCC30000000000LL )
{
@ -226,7 +236,7 @@ int main ()
}
printf("\n");
}
*/
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();

@ -2,7 +2,7 @@
* Confiscates and dumps garbage owned by dwarfs.
*/
#include <stdio.h>
#include <cstdio>
#include <iostream>
#include <iomanip>
#include <sstream>
@ -88,16 +88,16 @@ int main (int argc, char *argv[])
for (i=0;i<size;i++)
{
uint32_t curItem = p_items[i];
DFHack::t_item itm;
Items->getItemData(curItem, itm);
DFHack::dfh_item itm;
Items->readItem(curItem, itm);
if (!itm.header.flags.bits.owned)
if (!itm.base.flags.owned)
continue;
bool confiscate = false;
bool dump = false;
if (itm.header.flags.bits.rotten)
if (itm.base.flags.rotten)
{
printf("Confiscating a rotten item: \t");
confiscate = true;
@ -108,7 +108,7 @@ int main (int argc, char *argv[])
confiscate = true;
dump = true;
}
else if (dump_scattered && itm.header.flags.bits.on_ground)
else if (dump_scattered && itm.base.flags.on_ground)
{
printf("Confiscating and dumping litter: \t");
confiscate = true;
@ -122,20 +122,20 @@ int main (int argc, char *argv[])
if (confiscate)
{
itm.header.flags.bits.owned = 0;
itm.base.flags.owned = 0;
if (dump)
itm.header.flags.bits.dump = 1;
itm.base.flags.dump = 1;
if (!dry_run)
Items->setItemFlags(curItem, itm.header.flags);
Items->writeItem(itm);
printf(
"%s (wear %d)",
Items->getItemDescription(curItem, Materials).c_str(),
Items->getItemDescription(itm, Materials).c_str(),
itm.wear_level
);
int32_t owner = Items->getItemOwnerID(curItem);
int32_t owner = Items->getItemOwnerID(itm);
int32_t owner_index = Creatures->FindIndexById(owner);
std::string info;
@ -153,17 +153,18 @@ int main (int argc, char *argv[])
}
printf("\n");
/* printf(
/*
printf(
"%5d: %08x %08x (%d,%d,%d) #%08x [%d] %s - %s %s\n",
i, curItem, itm.header.flags.whole,
itm.header.x, itm.header.y, itm.header.z,
p->readDWord(curItem),
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(curItem, Materials).c_str(),
Items->getItemDescription(itm, Materials).c_str(),
info.c_str()
);*/
);
*/
}
}