API changes: InitRead* methods made safer - they now return false on error

develop
Petr Mrázek 2010-02-11 21:08:39 +00:00
parent ae8eada92e
commit 63f82cd580
10 changed files with 212 additions and 169 deletions

@ -639,14 +639,21 @@ bool API::ReadGeology (vector < vector <uint16_t> >& assign)
// returns number of buildings, expects v_buildingtypes that will later map t_building.type to its name
uint32_t API::InitReadBuildings (vector <string> &v_buildingtypes)
bool API::InitReadBuildings ( uint32_t& numbuildings )
{
d->buildingsInited = true;
int buildings = d->offset_descriptor->getAddress ("buildings");
assert (buildings);
d->p_bld = new DfVector (d->dm->readVector (buildings, 4));
d->offset_descriptor->copyBuildings (v_buildingtypes);
return d->p_bld->getSize();
if(buildings)
{
d->buildingsInited = true;
d->p_bld = new DfVector (d->dm->readVector (buildings, 4));
return true;
}
else
{
d->buildingsInited = false;
numbuildings = 0;
return false;
}
}
@ -691,14 +698,22 @@ void API::FinishReadBuildings()
//TODO: maybe do construction reading differently - this could go slow with many of them.
// returns number of constructions, prepares a vector, returns total number of constructions
uint32_t API::InitReadConstructions()
bool API::InitReadConstructions(uint32_t & numconstructions)
{
d->constructionsInited = true;
int constructions = d->offset_descriptor->getAddress ("constructions");
assert (constructions);
d->p_cons = new DfVector (d->dm->readVector (constructions, 4));
return d->p_cons->getSize();
if(constructions)
{
d->p_cons = new DfVector (d->dm->readVector (constructions, 4));
d->constructionsInited = true;
numconstructions = d->p_cons->getSize();
return true;
}
else
{
d->constructionsInited = false;
numconstructions = 0;
return false;
}
}
@ -731,14 +746,23 @@ void API::FinishReadConstructions()
}
uint32_t API::InitReadVegetation()
bool API::InitReadVegetation(uint32_t & numplants)
{
d->vegetationInited = true;
int vegetation = d->offset_descriptor->getAddress ("vegetation");
d->tree_offset = d->offset_descriptor->getOffset ("tree_desc_offset");
assert (vegetation && d->tree_offset);
d->p_veg = new DfVector (d->dm->readVector (vegetation, 4));
return d->p_veg->getSize();
if(vegetation && d->tree_offset)
{
d->vegetationInited = true;
d->p_veg = new DfVector (d->dm->readVector (vegetation, 4));
numplants = d->p_veg->getSize();
return true;
}
else
{
d->vegetationInited = false;
numplants = 0;
return false;
}
}
@ -764,7 +788,7 @@ void API::FinishReadVegetation()
}
uint32_t API::InitReadCreatures()
bool API::InitReadCreatures( uint32_t numcreatures )
{
memory_info * minfo = d->offset_descriptor;
int creatures = d->offset_descriptor->getAddress ("creatures");
@ -818,18 +842,14 @@ uint32_t API::InitReadCreatures()
{
d->p_cre = new DfVector (d->dm->readVector (creatures, 4));
//InitReadNameTables();
//if(d->InitReadNameTables())
//{
d->creaturesInited = true;
return d->p_cre->getSize();
//}
//else
//{
// return false;
//}
numcreatures = d->p_cre->getSize();
return false;
}
else
{
d->creaturesInited = false;
numcreatures = 0;
return false;
}
}
@ -968,35 +988,44 @@ void API::WriteLabors(const uint32_t &index, uint8_t labors[NUM_CREATURE_LABORS]
WriteRaw(temp + d->creature_labors_offset, NUM_CREATURE_LABORS, labors);
}
void API::InitReadNameTables (map< string, vector<string> > & nameTable)
bool API::InitReadNameTables (map< string, vector<string> > & nameTable)
{
int genericAddress = d->offset_descriptor->getAddress ("language_vector");
int transAddress = d->offset_descriptor->getAddress ("translation_vector");
int word_table_offset = d->offset_descriptor->getOffset ("word_table");
DfVector genericVec (d->dm->readVector (genericAddress, 4));
DfVector transVec (d->dm->readVector (transAddress, 4));
for (uint32_t i = 0;i < genericVec.getSize();i++)
if(genericAddress && transAddress && word_table_offset)
{
uint32_t genericNamePtr = * (uint32_t *) genericVec.at (i);
string genericName = d->dm->readSTLString (genericNamePtr);
nameTable["GENERIC"].push_back (genericName);
}
DfVector genericVec (d->dm->readVector (genericAddress, 4));
DfVector transVec (d->dm->readVector (transAddress, 4));
for (uint32_t i = 0; i < transVec.getSize();i++)
{
uint32_t transPtr = * (uint32_t *) transVec.at (i);
string transName = d->dm->readSTLString (transPtr);
DfVector trans_names_vec (d->dm->readVector (transPtr + word_table_offset, 4));
for (uint32_t j = 0;j < trans_names_vec.getSize();j++)
for (uint32_t i = 0;i < genericVec.getSize();i++)
{
uint32_t genericNamePtr = * (uint32_t *) genericVec.at (i);
string genericName = d->dm->readSTLString (genericNamePtr);
nameTable["GENERIC"].push_back (genericName);
}
for (uint32_t i = 0; i < transVec.getSize();i++)
{
uint32_t transNamePtr = * (uint32_t *) trans_names_vec.at (j);
string name = d->dm->readSTLString (transNamePtr);
nameTable[transName].push_back (name);
uint32_t transPtr = * (uint32_t *) transVec.at (i);
string transName = d->dm->readSTLString (transPtr);
DfVector trans_names_vec (d->dm->readVector (transPtr + word_table_offset, 4));
for (uint32_t j = 0;j < trans_names_vec.getSize();j++)
{
uint32_t transNamePtr = * (uint32_t *) trans_names_vec.at (j);
string name = d->dm->readSTLString (transNamePtr);
nameTable[transName].push_back (name);
}
}
d->nameTablesInited = true;
return true;
}
else
{
d->nameTablesInited = false;
return false;
}
d->nameTablesInited = true;
}
string API::TranslateName (const t_lastname & last, const map<string, vector<string> > & nameTable, const string & language)
@ -1230,6 +1259,16 @@ bool API::getWindowSize (int32_t &width, int32_t &height)
return true;
}
bool API::getClassIDMapping (vector <string>& objecttypes)
{
if(isAttached())
{
d->offset_descriptor->getClassIDMapping(objecttypes);
return true;
}
return false;
}
memory_info API::getMemoryInfo()
{
return *d->offset_descriptor;
@ -1244,19 +1283,24 @@ DFWindow * API::getWindow()
return d->p->getWindow();
}
uint32_t API::InitReadItems()
bool API::InitReadItems(uint32_t & numitems)
{
int items = d->offset_descriptor->getAddress ("items");
assert (items);
//cerr << hex << items;
d->item_material_offset = d->offset_descriptor->getOffset ("item_materials");
assert (d->item_material_offset);
d->p_itm = new DfVector (d->dm->readVector (items, 4));
d->itemsInited = true;
return d->p_itm->getSize();
if(items && d->item_material_offset)
{
d->p_itm = new DfVector (d->dm->readVector (items, 4));
d->itemsInited = true;
numitems = d->p_itm->getSize();
return true;
}
else
{
d->itemsInited = false;
numitems = 0;
return false;
}
}
bool API::ReadItem (const uint32_t &index, t_item & item)
{

@ -147,19 +147,19 @@ namespace DFHack
/**
* Buildings, constructions, plants, all pretty straighforward. InitReadBuildings returns all the building types as a mapping between a numeric values and strings
*/
uint32_t InitReadConstructions();
bool InitReadConstructions( uint32_t & numconstructions );
bool ReadConstruction(const int32_t &index, t_construction & construction);
void FinishReadConstructions();
uint32_t InitReadBuildings(vector <string> &v_buildingtypes);
bool InitReadBuildings ( uint32_t& numbuildings );
bool ReadBuilding(const int32_t &index, t_building & building);
void FinishReadBuildings();
uint32_t InitReadVegetation();
bool InitReadVegetation( uint32_t & numplants );
bool ReadVegetation(const int32_t &index, t_tree_desc & shrubbery);
void FinishReadVegetation();
uint32_t InitReadCreatures();
bool InitReadCreatures( uint32_t numcreatures );
/// returns index of creature actually read or -1 if no creature can be found
int32_t ReadCreatureInBox(int32_t index, t_creature & furball,
const uint16_t &x1, const uint16_t &y1,const uint16_t &z1,
@ -198,7 +198,7 @@ namespace DFHack
vector<t_trait> getTraits(const uint32_t &index);
vector<t_labor> getLabors(const uint32_t &index);
*/
void InitReadNameTables(map< string, vector< string > > & nameTable);
bool InitReadNameTables (map< string, vector<string> > & nameTable);
void FinishReadNameTables();
string TranslateName(const t_lastname & last, const map< string, vector< string > > &nameTable,const string & language="GENERIC");
@ -206,10 +206,13 @@ namespace DFHack
void WriteLabors(const uint32_t &index, uint8_t labors[NUM_CREATURE_LABORS]);
uint32_t InitReadItems();
bool InitReadItems(uint32_t & numitems);
bool ReadItem(const uint32_t &index, t_item & item);
void FinishReadItems();
// wrapper for meminfo method of the same name
bool getClassIDMapping (vector <string>& objecttypes);
memory_info getMemoryInfo();
Process * getProcess();
DFWindow * getWindow();

@ -329,11 +329,11 @@ bool memory_info::resolveClassId(uint32_t address, int32_t & classid)
}
// Flatten vtables into a index<->name mapping
void memory_info::copyBuildings(vector<string> & v_buildingtypes)
void memory_info::getClassIDMapping(vector<string> & v_ClassID2ObjName)
{
for(uint32_t i = 0;i< classes.size();i++)
{
v_buildingtypes.push_back(classes[i].classname);
v_ClassID2ObjName.push_back(classes[i].classname);
if(!classes[i].is_multiclass)
{
continue;
@ -341,7 +341,7 @@ void memory_info::copyBuildings(vector<string> & v_buildingtypes)
vector <t_type>& vec = classsubtypes[classes[i].multi_index];
for (uint32_t k = 0; k < vec.size();k++)
{
v_buildingtypes.push_back(vec[k].classname);
v_ClassID2ObjName.push_back(vec[k].classname);
}
}
}

@ -117,7 +117,7 @@ namespace DFHack
// ALERT: uses memory reading directly
bool resolveClassId(const uint32_t address, int32_t & classid);
void copyBuildings(vector<string> & v_buildingtypes);
void getClassIDMapping(vector<string> & v_ClassID2ObjName);
void flush();

@ -136,30 +136,43 @@ int main (int argc,const char* argv[])
return 1;
}
vector <string> buildingtypes;
uint32_t numBuildings = DF.InitReadBuildings(buildingtypes);
vector < uint32_t > addresses;
for(uint32_t i = 0; i < numBuildings; i++)
/*
* Get the object name/ID mapping
*/
vector <string> objecttypes;
DF.getClassIDMapping (objecttypes);
uint32_t numBuildings;
if(DF.InitReadBuildings(numBuildings))
{
DFHack::t_building temp;
DF.ReadBuilding(i, temp);
if(temp.type != 0xFFFFFFFF) // check if type isn't invalid
vector < uint32_t > addresses;
for(uint32_t i = 0; i < numBuildings; i++)
{
if(buildingtypes[temp.type] == argv[1])
DFHack::t_building temp;
DF.ReadBuilding(i, temp);
if(temp.type != 0xFFFFFFFF) // check if type isn't invalid
{
//cout << buildingtypes[temp.type] << " 0x" << hex << temp.origin << endl;
//hexdump(DF, temp.origin, 16);
addresses.push_back(temp.origin);
if(objecttypes[temp.type] == argv[1])
{
//cout << buildingtypes[temp.type] << " 0x" << hex << temp.origin << endl;
//hexdump(DF, temp.origin, 16);
addresses.push_back(temp.origin);
}
}
else
{
// couldn't translate type, print out the vtable
cout << "unknown vtable: " << temp.vtable << endl;
}
}
else
{
// couldn't translate type, print out the vtable
cout << "unknown vtable: " << temp.vtable << endl;
}
interleave_hex(DF,addresses,lines / 4);
DF.FinishReadBuildings();
}
else
{
cerr << "buildings not supported for this DF version" << endl;
}
interleave_hex(DF,addresses,lines / 4);
DF.FinishReadBuildings();
DF.Detach();
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;

@ -144,19 +144,16 @@ likeType printLike(DFHack::t_like like, const matGlosses & mat,const vector< vec
int main (void)
{
vector<DFHack::t_matgloss> creaturestypes;
// t_matglossPlant test;
DFHack::API DF("Memory.xml");
if(!DF.Attach())
{
cerr << "DF not found" << endl;
return 1;
}
vector <string> buildingtypes;
uint32_t numBuildings = DF.InitReadBuildings(buildingtypes);
//vector< vector <string> > all;
vector< vector <DFHack::t_itemType> > itemTypes;
DF.ReadItemTypes(itemTypes);
//DF.ReadAllMatgloss(all);
matGlosses mat;
DF.ReadPlantMatgloss(mat.plantMat);
DF.ReadWoodMatgloss(mat.woodMat);
@ -173,8 +170,17 @@ int main (void)
}
map<string, vector<string> > names;
DF.InitReadNameTables(names);
uint32_t numCreatures = DF.InitReadCreatures();
if(!DF.InitReadNameTables(names))
{
cerr << "Can't get name tables" << endl;
return 1;
}
uint32_t numCreatures;
if(!DF.InitReadCreatures(numCreatures))
{
cerr << "Can't get creatures" << endl;
return 1;
}
for(uint32_t i = 0; i < numCreatures; i++)
{
DFHack::t_creature temp;

@ -21,7 +21,7 @@ void print_bits ( T val, std::ostream& out )
val >>= 1;
}
}
vector <string> buildingtypes;
vector <string> objecttypes;
map<string, vector<string> > names;
uint32_t numCreatures;
vector<DFHack::t_matgloss> creaturestypes;
@ -176,7 +176,7 @@ bool waitTillScreenState(DFHack::API &DF, string screenState,bool EqualTo=true)
DF.Suspend();
DF.ReadViewScreen(current);
int tryCount = 0;
while(((EqualTo && buildingtypes[current.type] != screenState) || (!EqualTo && buildingtypes[current.type] == screenState)) && tryCount < 50)
while(((EqualTo && objecttypes[current.type] != screenState) || (!EqualTo && objecttypes[current.type] == screenState)) && tryCount < 50)
{
DF.Resume();
w->TypeSpecial(DFHack::WAIT,1,100);
@ -185,7 +185,7 @@ bool waitTillScreenState(DFHack::API &DF, string screenState,bool EqualTo=true)
tryCount++;
}
if(tryCount >= 50){
cerr << "Something went wrong, DF at " << buildingtypes[current.type] << endl;
cerr << "Something went wrong, DF at " << objecttypes[current.type] << endl;
return false;
}
DF.Resume();
@ -242,12 +242,12 @@ bool moveToBaseWindow(DFHack::API &DF)
DFHack::DFWindow * w = DF.getWindow();
DFHack::t_viewscreen current;
DF.ReadViewScreen(current);
while(buildingtypes[current.type] != string("viewscreen_dwarfmode"))
while(objecttypes[current.type] != string("viewscreen_dwarfmode"))
{
w->TypeSpecial(DFHack::F9); // cancel out of text input in names
// DF.TypeSpecial(DFHack::ENTER); // cancel out of text input in hotkeys
w->TypeSpecial(DFHack::SPACE); // should move up a level
if(!waitTillScreenState(DF,buildingtypes[current.type],false)) return false; // wait until screen changes from current
if(!waitTillScreenState(DF,objecttypes[current.type],false)) return false; // wait until screen changes from current
DF.ReadViewScreen(current);
}
if(DF.ReadMenuState() != 0){// if menu state != 0 then there is a menu, so escape it
@ -287,18 +287,22 @@ int main (void)
return 1;
}
DF.Suspend();
//Need buildingtypes for the viewscreen vtables, this really should not be just buildings, as viewscreen and items both use the same interface
uint32_t numBuildings = DF.InitReadBuildings(buildingtypes);
if(!DF.getClassIDMapping(objecttypes))
{
cerr << "Can't get type info" << endl;
return 1;
}
DFHack::memory_info mem = DF.getMemoryInfo();
// get stone matgloss mapping
if(!DF.ReadCreatureMatgloss(creaturestypes))
{
cerr << "Can't get the creature types." << endl;
return 1;
}
DF.InitReadNameTables(names);
numCreatures = DF.InitReadCreatures();
DF.InitReadCreatures(numCreatures);
DF.InitViewAndCursor();
printDwarves(DF);
DFHack::t_creature toChange;

@ -63,18 +63,18 @@ int main ()
return EXIT_FAILURE;
}
//FIXME: very counter-intuitive, fix the API. This returns a mapping from the internal ID to the object name
// internal IDs can be obtained by using resolveClassId
//FIXME: Proper error reporting/exceptions support is sorely needed
/*
* Get the object name/ID mapping
* Get some basics needed for full access
*/
vector <string> buildingtypes;
uint32_t numBuildings = DF.InitReadBuildings(buildingtypes);
proc = DF.getProcess();
meminfo = proc->getDescriptor();
/*
* Get the object name/ID mapping
*/
vector <string> objecttypes;
DF.getClassIDMapping (objecttypes);
//FIXME: work on the 'supported features' system required
/*
* Check availability of required addresses and offsets (doing custom stuff here)
@ -106,7 +106,7 @@ int main ()
if(!meminfo->resolveClassId (temp, type))
continue;
if(buildingtypes[type] == "item_trapparts")
if(objecttypes[type] == "item_trapparts")
{
proc->read (temp + item_material_offset, sizeof (DFHack::t_matglossPair), (uint8_t *) &item_40d_material);

@ -94,20 +94,13 @@ int main ()
DF.ReadCreatureMatgloss(mat.creatureMat);
DF.ForceResume();
vector <string> buildingtypes;
DF.InitReadBuildings(buildingtypes);
uint32_t numItems = DF.InitReadItems();
/*
map< string, map<string,vector<uint32_t> > > count;
for(uint32_t i=0; i< numItems; i++){
DFHack::t_item temp;
DF.ReadItem(i,temp);
// cout << int(temp.type) << endl;
count[buildingtypes[temp.type]][getMaterialType(temp,buildingtypes,mat)].push_back(i);
}
*/
vector <string> objecttypes;
DF.getClassIDMapping(objecttypes);
uint32_t numItems;
DF.InitReadItems(numItems);
DF.InitViewAndCursor();
cout << "q to quit, anything else to look up items at that location\n";
while(1)
{
@ -115,37 +108,14 @@ int main ()
DF.ForceResume();
getline (cin, input);
DF.Suspend();
uint32_t numItems = DF.InitReadItems();
//FIXME: why twice?
uint32_t numItems;
DF.InitReadItems(numItems);
if(input == "q")
{
break;
}
// else if(next == 'c'){
// cerr << "clearing similarity" << endl;
// similarity.clear();
// continue;
// }
// else if(next == 'p'){
// vector<bool> same(similarity[0].size(),true);
// for(int k =0; k < similarity.size(); k++){
// for(int j =0; j < similarity.size(); j++){
// if(k != j){
// for(int l =0; l < similarity[k].size(); l++){
// if(similarity[k][l] != similarity[j][l]){
// same[l] = false;
// }
// }
// }
// }
// }
// for(int itr =0; itr < same.size(); itr++){
// if(same[itr] == true && similarity[0][itr] != 0){
// cout << hex << itr << " " << hex << (int)similarity[0][itr] << endl;
// }
// }
// continue;
// }
int32_t x,y,z;
DF.getCursorCoords(x,y,z);
vector <DFHack::t_item> foundItems;
@ -162,15 +132,16 @@ int main ()
if(foundItems.size() == 0){
cerr << "No Items at x:" << x << " y:" << y << " z:" << z << endl;
}
else if(foundItems.size() == 1){
printItem(foundItems[0], buildingtypes,mat);
// similarity.push_back(foundItems[0].bytes);
else if(foundItems.size() == 1)
{
printItem(foundItems[0], objecttypes ,mat);
}
else{
else
{
cerr << "Please Select which item you want to display\n";
for(uint32_t j = 0; j < foundItems.size(); ++j)
{
cerr << j << " " << buildingtypes[foundItems[j].type] << endl;
cerr << j << " " << objecttypes[foundItems[j].type] << endl;
}
uint32_t value;
string input2;
@ -178,7 +149,8 @@ int main ()
getline(cin, input2);
ss.str(input2);
ss >> value;
while(value >= foundItems.size()){
while(value >= foundItems.size())
{
cerr << "invalid choice, please try again" << endl;
input2.clear();
ss.clear();
@ -186,8 +158,7 @@ int main ()
ss.str(input2);
ss >> value;
}
printItem(foundItems[value], buildingtypes,mat);
// similarity.push_back(foundItems[value].bytes);
printItem(foundItems[value], objecttypes ,mat);
}
DF.FinishReadItems();
}

@ -141,8 +141,10 @@ int main ()
{
DFHack::API DF ("Memory.xml");
cout << "This utility lets you mass-designate items by type and material." << endl <<"Like set on fire all MICROCLINE item_stone..." << endl
<< "Some unusual combinations might be untested and cause the program to crash..."<< endl << "so, watch your step and backup your fort" << endl;
cout << "This utility lets you mass-designate items by type and material." << endl
<< "Like set on fire all MICROCLINE item_stone..." << endl
<< "Some unusual combinations might be untested and cause the program to crash..."<< endl
<< "so, watch your step and backup your fort" << endl;
if(!DF.Attach())
{
cerr << "DF not found" << endl;
@ -156,11 +158,11 @@ int main ()
DF.ReadStoneMatgloss(mat.stoneMat);
DF.ReadMetalMatgloss(mat.metalMat);
DF.ReadCreatureMatgloss(mat.creatureMat);
//DF.ForceResume();
vector <string> buildingtypes;
DF.InitReadBuildings(buildingtypes);
uint32_t numItems = DF.InitReadItems();
vector <string> objecttypes;
DF.getClassIDMapping(objecttypes);
uint32_t numItems;
DF.InitReadItems(numItems);
map< string, map<string,vector<uint32_t> > > count;
int failedItems = 0;
map <string, int > bad_mat_items;
@ -170,22 +172,22 @@ int main ()
DF.ReadItem(i,temp);
if(temp.type != -1)
{
string material = getMaterialType(temp,buildingtypes,mat);
string material = getMaterialType(temp,objecttypes,mat);
if (material != "Invalid")
{
count[buildingtypes[temp.type]][material].push_back(i);
count[objecttypes[temp.type]][material].push_back(i);
}
else
{
if(bad_mat_items.count(buildingtypes[temp.type]))
if(bad_mat_items.count(objecttypes[temp.type]))
{
int tmp = bad_mat_items[buildingtypes[temp.type]];
int tmp = bad_mat_items[objecttypes[temp.type]];
tmp ++;
bad_mat_items[buildingtypes[temp.type]] = tmp;
bad_mat_items[objecttypes[temp.type]] = tmp;
}
else
{
bad_mat_items[buildingtypes[temp.type]] = 1;
bad_mat_items[objecttypes[temp.type]] = 1;
}
}
}
@ -243,7 +245,7 @@ int main ()
ss >> number2;
decideAgain:
cout << "Select a designation - (d)ump, (f)orbid, (m)melt, on fi(r)e :" << flush;
cout << "Select a designation - (d)ump, (f)orbid, (m)melt, set on fi(r)e :" << flush;
string designationType;
getline(cin,designationType);
DFHack::t_itemflags changeFlag = {0};
@ -259,7 +261,7 @@ int main ()
{
changeFlag.bits.melt = 1;
}
else if(designationType == "r" || designationType == "flame")
else if(designationType == "r" || designationType == "fire")
{
changeFlag.bits.on_fire = 1;
}