Veinlook uses Map features

develop
Petr Mrázek 2010-04-24 01:50:04 +02:00
parent 8156469825
commit 340b0cf91c
3 changed files with 215 additions and 135 deletions

@ -38,7 +38,7 @@ namespace DFHack
e_feature type;
int16_t main_material;
int32_t sub_material;
bool discovered; // maybe, placeholder. should work for rivers in adventure mode
bool discovered; // placeholder.
uint32_t origin;
};

@ -55,135 +55,12 @@ struct Maps::Private
bool Inited;
bool Started;
vector <t_feature> global_features;
// map between feature address and the read object
map <uint32_t, t_feature> local_feature_store;
// map between mangled coords and pointer to feature
map <planecoord, vector<t_feature *> > local_features;
vector<uint16_t> v_geology[eBiomeCount];
};
bool Maps::ReadLocalFeatures( std::map <planecoord, std::vector<t_feature *> > & local_features )
{
Process * p = d->owner;
memory_info * mem = p->getDescriptor();
// deref pointer to the humongo-structure
uint32_t base = p->readDWord(mem->getAddress("local_feature_start_ptr"));
uint32_t sizeof_vec = mem->getHexValue("sizeof_vector");
const uint32_t sizeof_elem = 16;
const uint32_t offset_elem = 4;
local_features.clear();
for(uint blockX = 0; blockX < d->x_block_count; blockX ++)
for(uint blockY = 0; blockY < d->x_block_count; blockY ++)
{
//uint64_t block48_x = blockX / 3 + d->regionX;
//uint16_t region_x_plus8 = ( block48_x + 8 ) / 16;
// region X coord offset by 8 big blocks (48x48 tiles)
uint16_t region_x_plus8 = ( blockX / 3 + d->regionX + 8 ) / 16;
// plain region Y coord
uint64_t region_y_local = ( blockY / 3 + d->regionY ) / 16;
// this is just a few pointers to arrays of 16B (4 DWORD) structs
uint32_t array_elem = p->readDWord(base + (region_x_plus8 / 16) * 4);
// 16B structs, second DWORD of the struct is a pointer
uint32_t wtf = p->readDWord(array_elem + ( sizeof_elem * (region_y_local/16)) + offset_elem);
if(wtf)
{
// wtf + sizeof(vector<ptr>) * crap;
uint32_t feat_vector = wtf + sizeof_vec * (16 * (region_x_plus8 % 16) + (region_y_local % 16));
DfVector<uint32_t> p_features(p, feat_vector);
uint size = p_features.size();
planecoord pc;
pc.dim.x = blockX;
pc.dim.y = blockY;
std::vector<t_feature *> tempvec;
for(uint i = 0; i < size; i++)
{
uint32_t cur_ptr = p_features[i];
map <uint32_t, t_feature>::iterator it;
it = d->local_feature_store.find(cur_ptr);
// do we already have the feature?
if(it != d->local_feature_store.end())
{
// push pointer to existing feature
tempvec.push_back(&((*it).second));
}
// no?
else
{
// create, add to store
t_feature tftemp;
tftemp.discovered = p->readDWord(cur_ptr + 4);
tftemp.origin = cur_ptr;
string name = p->readClassName(p->readDWord( cur_ptr ));
if(name == "feature_init_deep_special_tubest")
{
tftemp.main_material = p->readWord( cur_ptr + 0x30 );
tftemp.sub_material = p->readDWord( cur_ptr + 0x34 );
tftemp.type = feature_Adamantine_Tube;
}
else
{
tftemp.main_material = -1;
tftemp.sub_material = -1;
tftemp.type = feature_Other;
}
d->local_feature_store[cur_ptr] = tftemp;
// push pointer
tempvec.push_back(&(d->local_feature_store[cur_ptr]));
}
}
local_features[pc] = tempvec;
}
}
return true;
}
bool Maps::ReadGlobalFeatures( std::vector <t_feature> & features)
{
Process * p = d->owner;
memory_info * mem = p->getDescriptor();
uint32_t global_feature_vector = mem->getAddress("global_feature_vector");
uint32_t global_feature_funcptr = mem->getOffset("global_feature_funcptr_");
DfVector<uint32_t> p_features (p,global_feature_vector);
features.clear();
uint size = p_features.size();
features.reserve(size);
for(uint i = 0; i < size; i++)
{
t_feature temp;
uint32_t feat_ptr = p->readDWord(p_features[i] + global_feature_funcptr );
temp.origin = feat_ptr;
temp.discovered = p->readDWord( feat_ptr + 4 ); // maybe, placeholder
// FIXME: use the memory_info cache mechanisms
string name = p->readClassName(p->readDWord( feat_ptr));
if(name == "feature_init_underworld_from_layerst")
{
temp.main_material = p->readWord( feat_ptr + 0x34 );
temp.sub_material = p->readDWord( feat_ptr + 0x38 );
temp.type = feature_Underworld;
}
else
{
temp.main_material = -1;
temp.sub_material = -1;
temp.type = feature_Other;
}
features.push_back(temp);
}
return true;
}
Maps::Maps(APIPrivate* _d)
{
d = new Private;
@ -320,8 +197,10 @@ void Maps::getSize (uint32_t& x, uint32_t& y, uint32_t& z)
z = d->z_block_count;
}
// invalidates local and global features!
bool Maps::Finish()
{
d->local_feature_store.clear();
if (d->block != NULL)
{
delete [] d->block;
@ -774,3 +653,128 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
}
return true;
}
bool Maps::ReadLocalFeatures( std::map <planecoord, std::vector<t_feature *> > & local_features )
{
Process * p = d->owner;
memory_info * mem = p->getDescriptor();
// deref pointer to the humongo-structure
uint32_t base = p->readDWord(mem->getAddress("local_feature_start_ptr"));
uint32_t sizeof_vec = mem->getHexValue("sizeof_vector");
const uint32_t sizeof_elem = 16;
const uint32_t offset_elem = 4;
const uint32_t main_mat_offset = 0x30;
const uint32_t sub_mat_offset = 0x34;
local_features.clear();
for(uint blockX = 0; blockX < d->x_block_count; blockX ++)
for(uint blockY = 0; blockY < d->x_block_count; blockY ++)
{
//uint64_t block48_x = blockX / 3 + d->regionX;
//uint16_t region_x_plus8 = ( block48_x + 8 ) / 16;
// region X coord offset by 8 big blocks (48x48 tiles)
uint16_t region_x_plus8 = ( blockX / 3 + d->regionX + 8 ) / 16;
// plain region Y coord
uint64_t region_y_local = ( blockY / 3 + d->regionY ) / 16;
// this is just a few pointers to arrays of 16B (4 DWORD) structs
uint32_t array_elem = p->readDWord(base + (region_x_plus8 / 16) * 4);
// 16B structs, second DWORD of the struct is a pointer
uint32_t wtf = p->readDWord(array_elem + ( sizeof_elem * (region_y_local/16)) + offset_elem);
if(wtf)
{
// wtf + sizeof(vector<ptr>) * crap;
uint32_t feat_vector = wtf + sizeof_vec * (16 * (region_x_plus8 % 16) + (region_y_local % 16));
DfVector<uint32_t> p_features(p, feat_vector);
uint size = p_features.size();
planecoord pc;
pc.dim.x = blockX;
pc.dim.y = blockY;
std::vector<t_feature *> tempvec;
for(uint i = 0; i < size; i++)
{
uint32_t cur_ptr = p_features[i];
map <uint32_t, t_feature>::iterator it;
it = d->local_feature_store.find(cur_ptr);
// do we already have the feature?
if(it != d->local_feature_store.end())
{
// push pointer to existing feature
tempvec.push_back(&((*it).second));
}
// no?
else
{
// create, add to store
t_feature tftemp;
tftemp.discovered = false; //= p->readDWord(cur_ptr + 4);
tftemp.origin = cur_ptr;
string name = p->readClassName(p->readDWord( cur_ptr ));
if(name == "feature_init_deep_special_tubest")
{
tftemp.main_material = p->readWord( cur_ptr + main_mat_offset );
tftemp.sub_material = p->readDWord( cur_ptr + sub_mat_offset );
tftemp.type = feature_Adamantine_Tube;
}
else
{
tftemp.main_material = -1;
tftemp.sub_material = -1;
tftemp.type = feature_Other;
}
d->local_feature_store[cur_ptr] = tftemp;
// push pointer
tempvec.push_back(&(d->local_feature_store[cur_ptr]));
}
}
local_features[pc] = tempvec;
}
}
return true;
}
bool Maps::ReadGlobalFeatures( std::vector <t_feature> & features)
{
Process * p = d->owner;
memory_info * mem = p->getDescriptor();
uint32_t global_feature_vector = mem->getAddress("global_feature_vector");
uint32_t global_feature_funcptr = mem->getOffset("global_feature_funcptr_");
const uint32_t main_mat_offset = 0x34;
const uint32_t sub_mat_offset = 0x38;
DfVector<uint32_t> p_features (p,global_feature_vector);
features.clear();
uint size = p_features.size();
features.reserve(size);
for(uint i = 0; i < size; i++)
{
t_feature temp;
uint32_t feat_ptr = p->readDWord(p_features[i] + global_feature_funcptr );
temp.origin = feat_ptr;
//temp.discovered = p->readDWord( feat_ptr + 4 ); // maybe, placeholder
temp.discovered = false;
// FIXME: use the memory_info cache mechanisms
string name = p->readClassName(p->readDWord( feat_ptr));
if(name == "feature_init_underworld_from_layerst")
{
temp.main_material = p->readWord( feat_ptr + main_mat_offset );
temp.sub_material = p->readDWord( feat_ptr + sub_mat_offset );
temp.type = feature_Underworld;
}
else
{
temp.main_material = -1;
temp.sub_material = -1;
temp.type = feature_Other;
}
features.push_back(temp);
}
return true;
}

@ -281,6 +281,7 @@ void hexdump (DFHack::API& DF, uint32_t address, uint32_t length, int filenum)
// blockaddr = address of the block
// blockX, blockY = local map X and Y coords in 16x16 of the block
// printX, printX = where to print stuff on the screen
/*
void do_features(Process* p, uint32_t blockaddr, uint32_t blockX, uint32_t blockY, int printX, int printY, vector<DFHack::t_matgloss> &stonetypes)
{
memory_info* mem = p->getDescriptor();
@ -337,14 +338,6 @@ void do_features(Process* p, uint32_t blockaddr, uint32_t blockX, uint32_t block
gotoxy(printX,printY+6);
cprintf("local feature vector: 0x%x\n", feat_vector);
DfVector<uint32_t> p_features(p, feat_vector);
/*
for(int k = 0 ; k < p_features.size();k++)
{
printf("feature %d addr: 0x%x\n", k, p_features[k]);
string name = p->readClassName(p->readDWord( p_features[k] ));
cout << name << endl;
}
*/
gotoxy(printX,printY + 7);
cprintf("feature %d addr: 0x%x\n", idx, p_features[idx]);
if(idx >= p_features.size())
@ -418,8 +411,91 @@ void do_features(Process* p, uint32_t blockaddr, uint32_t blockX, uint32_t block
}
}
}
*/
void do_features(API& DF, mapblock40d * block, uint32_t blockX, uint32_t blockY, int printX, int printY, vector<DFHack::t_matgloss> &stonetypes)
{
Maps * Maps = DF.getMaps();
Process * p = DF.getProcess();
if(!Maps)
return;
vector<DFHack::t_feature> global_features;
std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> > local_features;
if(!Maps->ReadGlobalFeatures(global_features))
return;
if(!Maps->ReadLocalFeatures(local_features))
return;
planecoord pc;
pc.dim.x = blockX;
pc.dim.y = blockY;
int16_t idx =block->global_feature;
if(idx != -1)
{
t_feature &ftr =global_features[idx];
gotoxy(printX,printY);
cprintf( "global feature present: %d @ 0x%x\n", idx, ftr.origin);
if(ftr.discovered )
{
gotoxy(printX,printY+1);
cprintf("You've discovered it already!");
}
if(ftr.type == feature_Underworld)
{
char * matname = "unknown";
// is stone?
if(ftr.main_material == 0)
{
matname = stonetypes[ftr.sub_material].id;
}
gotoxy(printX,printY+2);
cprintf("Underworld, material %d/%d : %s", ftr.main_material, ftr.sub_material, matname);
}
else
{
gotoxy(printX,printY+2);
string name = p->readClassName(p->readDWord( ftr.origin ));
cprintf("%s", name.c_str());
}
}
idx =block->local_feature;
if(idx != -1)
{
vector <t_feature *> &ftrv = local_features[pc];
if(idx < ftrv.size())
{
t_feature & ftr = *ftrv[idx];
gotoxy(printX,printY + 4);
cprintf( "local feature present: %d @ 0x%x\n", idx, ftr.origin);
if(ftr.discovered )
{
gotoxy(printX,printY+ 5);
cprintf("You've discovered it already!");
}
if(ftr.type == feature_Adamantine_Tube)
{
char * matname = "unknown";
// is stone?
if(ftr.main_material == 0)
{
matname = stonetypes[ftr.sub_material].id;
}
gotoxy(printX,printY+6);
cprintf("Underworld, material %d/%d : %s", ftr.main_material, ftr.sub_material, matname);
}
else
{
gotoxy(printX,printY+6);
string name = p->readClassName(p->readDWord( ftr.origin ));
cprintf("%s", name.c_str());
}
}
else
{
gotoxy(printX,printY + 4);
cprintf( "local feature vector overflow: %d", idx);
}
}
}
main(int argc, char *argv[])
{
@ -677,7 +753,7 @@ main(int argc, char *argv[])
// extra processing of the block in the middle
if(i == 0 && j == 0)
{
do_features(p, Block->origin, cursorX, cursorY, 50,10, stonetypes);
do_features(DF, Block, cursorX, cursorY, 50,10, stonetypes);
// read veins
Maps->ReadVeins(cursorX+i,cursorY+j,cursorZ,&veinVector,&IceVeinVector,&splatter);