2010-05-02 03:27:16 -06:00
/*
www . sourceforge . net / projects / dfhack
Copyright ( c ) 2009 Petr Mr á zek ( peterix ) , Kenneth Ferland ( Impaler [ WrG ] ) , dorf
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any
damages arising from the use of this software .
Permission is granted to anyone to use this software for any
purpose , including commercial applications , and to alter it and
redistribute it freely , subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must
not claim that you wrote the original software . If you use this
software in a product , an acknowledgment in the product documentation
would be appreciated but is not required .
2. Altered source versions must be plainly marked as such , and
must not be misrepresented as being the original software .
3. This notice may not be removed or altered from any source
distribution .
*/
2010-05-26 04:24:45 -06:00
# include "Internal.h"
2011-04-10 02:19:15 -06:00
# include <string>
# include <vector>
# include <cstdio>
# include <map>
using namespace std ;
2010-05-26 04:24:45 -06:00
# include "ContextShared.h"
2010-05-25 22:48:23 -06:00
# include "dfhack/DFTypes.h"
2010-08-20 06:10:05 -06:00
# include "dfhack/VersionInfo.h"
2010-05-25 22:48:23 -06:00
# include "dfhack/DFProcess.h"
# include "dfhack/DFVector.h"
2010-05-26 00:42:09 -06:00
# include "dfhack/modules/Materials.h"
# include "dfhack/modules/Items.h"
2011-03-18 01:53:59 -06:00
# include "ModuleFactory.h"
2010-05-02 03:27:16 -06:00
using namespace DFHack ;
2011-03-18 01:53:59 -06:00
Module * DFHack : : createItems ( DFContextShared * d )
{
return new Items ( d ) ;
}
2010-06-24 23:11:26 -06:00
enum accessor_type { ACCESSOR_CONSTANT , ACCESSOR_INDIRECT , ACCESSOR_DOUBLE_INDIRECT } ;
/* this is used to store data about the way accessors work */
class DFHACK_EXPORT Accessor
2010-05-02 02:35:23 -06:00
{
2011-04-10 12:44:01 -06:00
public :
enum DataWidth {
Data32 = 0 ,
DataSigned16 ,
DataUnsigned16
} ;
2010-06-24 23:11:26 -06:00
private :
accessor_type type ;
int32_t constant ;
2011-04-10 11:51:21 -06:00
int32_t offset1 ;
int32_t offset2 ;
2010-06-24 23:11:26 -06:00
Process * p ;
2011-04-10 12:44:01 -06:00
DataWidth dataWidth ;
2010-06-24 23:11:26 -06:00
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 ) ;
int32_t getValue ( uint32_t objectPtr ) ;
bool isConstant ( ) ;
2010-05-02 03:27:16 -06:00
} ;
2010-06-24 23:11:26 -06:00
class DFHACK_EXPORT ItemImprovementDesc
2010-05-02 02:35:23 -06:00
{
2010-06-24 23:11:26 -06:00
private :
Accessor * AType ;
Process * p ;
public :
ItemImprovementDesc ( uint32_t VTable , Process * p ) ;
bool getImprovement ( uint32_t descptr , t_improvement & imp ) ;
uint32_t vtable ;
uint32_t maintype ;
} ;
class DFHACK_EXPORT ItemDesc
2010-05-02 02:35:23 -06:00
{
2010-06-24 23:11:26 -06:00
private :
Accessor * AMainType ;
Accessor * ASubType ;
Accessor * ASubIndex ;
Accessor * AIndex ;
Accessor * AQuality ;
2011-04-10 12:42:25 -06:00
Accessor * AWear ;
2010-06-24 23:11:26 -06:00
Process * p ;
bool hasDecoration ;
public :
ItemDesc ( uint32_t VTable , Process * p ) ;
bool getItem ( uint32_t itemptr , t_item & item ) ;
std : : string className ;
uint32_t vtable ;
uint32_t mainType ;
std : : vector < ItemImprovementDesc > improvement ;
} ;
2011-04-10 11:51:21 -06:00
inline bool do_match ( uint32_t & ptr , uint64_t val , int size , uint64_t mask , uint64_t check )
{
if ( ( val & mask ) = = check ) {
ptr + = size ;
return true ;
}
return false ;
}
static bool match_MEM_ACCESS ( uint32_t & ptr , uint64_t v , int isize , int in_reg , int & out_reg , int & offset )
{
// ESP & EBP are hairy
if ( in_reg = = 4 | | in_reg = = 5 )
return false ;
if ( ( v & 7 ) ! = in_reg )
return false ;
out_reg = ( v > > 3 ) & 7 ;
switch ( ( v > > 6 ) & 3 ) {
case 0 : // MOV REG2, [REG]
offset = 0 ;
ptr + = isize + 1 ;
return true ;
case 1 : // MOV REG2, [REG+offset8]
offset = ( signed char ) ( v > > 8 ) ;
ptr + = isize + 2 ;
return true ;
case 2 : // MOV REG2, [REG+offset32]
offset = ( signed int ) ( v > > 8 ) ;
ptr + = isize + 5 ;
return true ;
default :
return false ;
}
}
2011-04-10 12:44:01 -06:00
static bool match_MOV_MEM ( uint32_t & ptr , uint64_t v , int in_reg , int & out_reg , int & offset , Accessor : : DataWidth & size )
2011-04-10 11:51:21 -06:00
{
int prefix = 0 ;
2011-04-10 12:44:01 -06:00
size = Accessor : : Data32 ;
2011-04-10 11:51:21 -06:00
if ( ( v & 0xFF ) = = 0x8B ) { // MOV
v > > = 8 ;
prefix = 1 ;
}
else if ( ( v & 0xFFFF ) = = 0x8B66 ) { // MOV 16-bit
v > > = 16 ;
prefix = 2 ;
2011-04-10 12:44:01 -06:00
size = Accessor : : DataUnsigned16 ;
2011-04-10 11:51:21 -06:00
}
else if ( ( v & 0xFFFF ) = = 0xBF0F ) { // MOVSX
v > > = 16 ;
prefix = 2 ;
2011-04-10 12:44:01 -06:00
size = Accessor : : DataSigned16 ;
2011-04-10 11:51:21 -06:00
}
else if ( ( v & 0xFFFF ) = = 0xB70F ) { // MOVZ
v > > = 16 ;
prefix = 2 ;
2011-04-10 12:44:01 -06:00
size = Accessor : : DataUnsigned16 ;
2011-04-10 11:51:21 -06:00
}
else
return false ;
return match_MEM_ACCESS ( ptr , v , prefix , in_reg , out_reg , offset ) ;
}
2010-05-02 02:35:23 -06:00
2010-06-24 23:11:26 -06:00
// FIXME: this is crazy
2010-05-02 02:35:23 -06:00
Accessor : : Accessor ( uint32_t function , Process * p )
{
2010-06-24 23:11:26 -06:00
this - > p = p ;
this - > type = ACCESSOR_CONSTANT ;
2011-04-10 11:51:21 -06:00
uint32_t ptr = function ;
uint64_t v = p - > readQuad ( ptr ) ;
int data_reg = - 1 ;
if ( do_match ( ptr , v , 2 , 0xFFFF , 0xC033 ) | |
do_match ( ptr , v , 2 , 0xFFFF , 0xC031 ) ) // XOR EAX, EAX
2010-06-24 23:11:26 -06:00
{
2011-04-10 11:51:21 -06:00
data_reg = 0 ;
this - > constant = 0 ;
2010-06-24 23:11:26 -06:00
}
2011-04-10 11:51:21 -06:00
else if ( do_match ( ptr , v , 3 , 0xFFFFFF , 0xFFC883 ) ) // OR EAX, -1
2010-06-24 23:11:26 -06:00
{
2011-04-10 11:51:21 -06:00
data_reg = 0 ;
2010-06-24 23:11:26 -06:00
this - > constant = - 1 ;
}
2011-04-10 11:51:21 -06:00
else if ( do_match ( ptr , v , 5 , 0xFF , 0xB8 ) ) // MOV EAX,imm
2010-06-24 23:11:26 -06:00
{
2011-04-10 11:51:21 -06:00
data_reg = 0 ;
this - > constant = ( v > > 8 ) & 0xFFFFFFFF ;
2010-10-19 04:07:07 -06:00
}
2011-04-10 11:51:21 -06:00
else
2010-06-24 23:11:26 -06:00
{
2011-04-10 12:44:01 -06:00
DataWidth xsize ;
2011-04-10 11:51:21 -06:00
int ptr_reg = 1 , tmp ; // ECX
// MOV REG,[ESP+4]
if ( do_match ( ptr , v , 4 , 0xFFFFC7FFU , 0x0424448B ) )
2010-05-02 02:35:23 -06:00
{
2011-04-10 11:51:21 -06:00
ptr_reg = ( v > > 11 ) & 7 ;
v = p - > readQuad ( ptr ) ;
}
2011-04-10 12:44:01 -06:00
if ( match_MOV_MEM ( ptr , v , ptr_reg , tmp , this - > offset1 , xsize ) ) {
2011-04-10 11:51:21 -06:00
data_reg = tmp ;
this - > type = ACCESSOR_INDIRECT ;
2011-04-10 12:44:01 -06:00
this - > dataWidth = xsize ;
2011-04-10 11:51:21 -06:00
2011-04-10 12:44:01 -06:00
if ( xsize = = Data32 )
2011-04-10 11:51:21 -06:00
{
v = p - > readQuad ( ptr ) ;
2011-04-10 12:44:01 -06:00
if ( match_MOV_MEM ( ptr , v , data_reg , tmp , this - > offset2 , xsize ) ) {
2011-04-10 11:51:21 -06:00
data_reg = tmp ;
this - > type = ACCESSOR_DOUBLE_INDIRECT ;
2011-04-10 12:44:01 -06:00
this - > dataWidth = xsize ;
2011-04-10 11:51:21 -06:00
}
}
2010-06-24 23:11:26 -06:00
}
}
2011-04-10 11:51:21 -06:00
v = p - > readQuad ( ptr ) ;
if ( data_reg = = 0 & & do_match ( ptr , v , 1 , 0xFF , 0xC3 ) ) // RET
2010-10-19 04:07:07 -06:00
return ;
2011-04-10 11:51:21 -06:00
else
2010-06-24 23:11:26 -06:00
{
2011-04-10 11:51:21 -06:00
this - > type = ACCESSOR_CONSTANT ;
this - > constant = 0 ;
printf ( " bad accessor @0x%x \n " , function ) ;
2010-06-24 23:11:26 -06:00
}
2010-05-02 02:35:23 -06:00
}
2010-05-02 04:50:51 -06:00
bool Accessor : : isConstant ( )
2010-05-02 02:35:23 -06:00
{
2010-06-24 23:11:26 -06:00
if ( this - > type = = ACCESSOR_CONSTANT )
return true ;
else
return false ;
2010-05-02 04:50:51 -06:00
}
2010-05-02 03:27:16 -06:00
2010-05-02 04:50:51 -06:00
int32_t Accessor : : getValue ( uint32_t objectPtr )
{
2011-04-10 12:44:01 -06:00
int32_t offset = this - > offset1 ;
2010-06-24 23:11:26 -06:00
switch ( this - > type )
{
case ACCESSOR_CONSTANT :
return this - > constant ;
break ;
case ACCESSOR_DOUBLE_INDIRECT :
2011-04-10 12:44:01 -06:00
objectPtr = p - > readDWord ( objectPtr + this - > offset1 ) ;
offset = this - > offset2 ;
// fallthrough
case ACCESSOR_INDIRECT :
2010-06-24 23:11:26 -06:00
switch ( this - > dataWidth )
{
2011-04-10 12:44:01 -06:00
case Data32 :
return p - > readDWord ( objectPtr + offset ) ;
case DataSigned16 :
return ( int16_t ) p - > readWord ( objectPtr + offset ) ;
case DataUnsigned16 :
return ( uint16_t ) p - > readWord ( objectPtr + offset ) ;
2010-06-24 23:11:26 -06:00
default :
return - 1 ;
}
break ;
default :
return - 1 ;
}
2010-05-02 02:35:23 -06:00
}
ItemDesc : : ItemDesc ( uint32_t VTable , Process * p )
{
2010-08-29 16:08:17 -06:00
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 " ) ;
2011-04-10 12:42:25 -06:00
uint32_t funcOffsetWear = Items - > getOffset ( " item_wear_accessor " ) ;
2010-06-24 23:11:26 -06:00
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 ) ;
2011-04-10 12:42:25 -06:00
this - > AWear = new Accessor ( p - > readDWord ( VTable + funcOffsetWear ) , p ) ;
2010-06-24 23:11:26 -06:00
this - > hasDecoration = false ;
if ( this - > AMainType - > isConstant ( ) )
this - > mainType = this - > AMainType - > getValue ( 0 ) ;
else
{
fprintf ( stderr , " Bad item main type at function %p \n " , ( void * ) p - > readDWord ( VTable + funcOffsetA ) ) ;
this - > mainType = 0 ;
}
2010-05-02 02:35:23 -06:00
}
bool ItemDesc : : getItem ( uint32_t itemptr , DFHack : : t_item & item )
{
2011-04-10 12:42:25 -06:00
this - > p - > read ( itemptr + 4 , sizeof ( t_item_header ) , ( uint8_t * ) & item . header ) ;
2010-06-24 23:11:26 -06:00
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 ) ;
item . quantity = 1 ; /* TODO */
2011-04-10 12:42:25 -06:00
// 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 ) ;
2010-06-24 23:11:26 -06:00
return true ;
}
class Items : : Private
{
public :
DFContextShared * d ;
Process * owner ;
std : : map < int32_t , ItemDesc * > descType ;
std : : map < uint32_t , ItemDesc * > descVTable ;
2011-04-11 04:32:53 -06:00
uint32_t refVectorOffset ;
uint32_t refIDOffset ;
uint32_t ownerRefVTable ;
2010-06-24 23:11:26 -06:00
} ;
Items : : Items ( DFContextShared * d_ )
{
d = new Private ;
d - > d = d_ ;
d - > owner = d_ - > p ;
2011-04-11 04:32:53 -06:00
d - > ownerRefVTable = d - > refVectorOffset = d - > refIDOffset = 0 ;
2010-06-24 23:11:26 -06:00
}
2010-11-03 03:45:29 -06:00
bool Items : : Start ( )
{
return true ;
}
bool Items : : Finish ( )
{
return true ;
}
2010-06-24 23:11:26 -06:00
Items : : ~ Items ( )
{
Finish ( ) ;
std : : map < uint32_t , ItemDesc * > : : iterator it ;
it = d - > descVTable . begin ( ) ;
while ( it ! = d - > descVTable . end ( ) )
{
delete ( * it ) . second ;
2010-10-28 16:22:56 -06:00
+ + it ;
2010-06-24 23:11:26 -06:00
}
d - > descType . clear ( ) ;
d - > descVTable . clear ( ) ;
delete d ;
2010-05-02 02:35:23 -06:00
}
bool Items : : getItemData ( uint32_t itemptr , DFHack : : t_item & item )
{
2010-06-24 23:11:26 -06:00
std : : map < uint32_t , ItemDesc * > : : iterator it ;
Process * p = d - > owner ;
ItemDesc * desc ;
2010-05-02 02:35:23 -06:00
2010-11-03 03:45:29 -06:00
uint32_t vtable = p - > readDWord ( itemptr ) ;
it = d - > descVTable . find ( vtable ) ;
if ( it = = d - > descVTable . end ( ) )
2010-06-24 23:11:26 -06:00
{
desc = new ItemDesc ( vtable , p ) ;
d - > descVTable [ vtable ] = desc ;
d - > descType [ desc - > mainType ] = desc ;
}
else
desc = it - > second ;
2010-05-02 02:35:23 -06:00
2010-06-24 23:11:26 -06:00
return desc - > getItem ( itemptr , item ) ;
2010-05-02 02:35:23 -06:00
}
2011-04-10 12:42:25 -06:00
void Items : : setItemFlags ( uint32_t itemptr , t_itemflags new_flags )
{
d - > owner - > writeDWord ( itemptr + 0x0C , new_flags . whole ) ;
}
2011-04-11 04:32:53 -06:00
int32_t Items : : getItemOwnerID ( uint32_t itemptr )
{
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 " ) ;
}
DFHack : : DfVector < uint32_t > p_refs ( d - > owner , itemptr + d - > refVectorOffset ) ;
uint32_t size = p_refs . size ( ) ;
for ( uint32_t i = 0 ; i < size ; i + + )
{
uint32_t curRef = p_refs [ i ] ;
uint32_t vtbl = d - > owner - > readDWord ( curRef ) ;
if ( ! d - > ownerRefVTable )
{
std : : string className = d - > owner - > readClassName ( vtbl ) ;
if ( className = = " general_ref_unit_itemownerst " )
d - > ownerRefVTable = vtbl ;
else
continue ;
}
else if ( d - > ownerRefVTable ! = vtbl )
continue ;
return d - > owner - > readDWord ( curRef + d - > refIDOffset ) ;
}
return - 1 ;
}
2010-05-02 04:50:51 -06:00
std : : string Items : : getItemClass ( int32_t index )
{
2010-06-24 23:11:26 -06:00
std : : map < int32_t , ItemDesc * > : : iterator it ;
std : : string out ;
2010-05-02 04:50:51 -06:00
2010-06-24 23:11:26 -06:00
it = d - > descType . find ( index ) ;
2010-11-03 03:45:29 -06:00
if ( it = = d - > descType . end ( ) )
2010-06-24 23:11:26 -06:00
{
/* these are dummy values for mood decoding */
switch ( index )
{
case 0 : return " bar " ;
case 1 : return " cut gem " ;
case 2 : return " block " ;
case 3 : return " raw gem " ;
case 4 : return " raw stone " ;
case 5 : return " log " ;
case 54 : return " leather " ;
case 57 : return " cloth " ;
case - 1 : return " probably bone or shell, but I really don't know " ;
default : return " unknown " ;
}
}
out = it - > second - > className ;
return out ;
2010-05-02 04:50:51 -06:00
}
std : : string Items : : getItemDescription ( uint32_t itemptr , Materials * Materials )
2010-05-02 02:35:23 -06:00
{
2010-06-24 23:11:26 -06:00
DFHack : : t_item item ;
std : : string out ;
2010-05-02 02:35:23 -06:00
2010-06-24 23:11:26 -06:00
if ( ! this - > getItemData ( itemptr , item ) )
return " ?? " ;
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 ;
}
out . append ( Materials - > getDescription ( item . matdesc ) ) ;
out . append ( " " ) ;
out . append ( this - > getItemClass ( item . matdesc . itemType ) ) ;
return out ;
2010-05-10 04:58:54 -06:00
}
2011-02-16 11:29:16 -07:00
// 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 ;
}
*/