diff --git a/dfhack/include/DFTypes.h b/dfhack/include/DFTypes.h index f9d19c0dc..2afd1f4f5 100644 --- a/dfhack/include/DFTypes.h +++ b/dfhack/include/DFTypes.h @@ -31,41 +31,6 @@ distribution. namespace DFHack { -template -struct junk_fill -{ - uint8_t data[SIZE]; - /* - void Dump() - { - cout< +struct junk_fill +{ + uint8_t data[SIZE]; +}; + enum EFFECT_TYPE { EFF_MIASMA=0, @@ -88,6 +60,7 @@ enum EFFECT_TYPE EFF_BOILING, // uses matgloss EFF_OCEANWAVE }; + struct t_effect_df40d //size 40 { uint16_t type; diff --git a/dfhack/include/modules/Maps.h b/dfhack/include/modules/Maps.h index 7e4274cc4..d7056921a 100644 --- a/dfhack/include/modules/Maps.h +++ b/dfhack/include/modules/Maps.h @@ -25,6 +25,18 @@ namespace DFHack { uint32_t vtable; int16_t tiles[16][16]; + uint32_t address_of; // this is NOT part of the DF vein, but an address of the vein as seen by DFhack. + }; + + struct t_spattervein + { + uint32_t vtable; + uint16_t mat1; + uint16_t unk1; + uint32_t mat2; + uint16_t mat3; + uint8_t intensity[16][16]; + uint32_t address_of; // this is NOT part of the DF vein, but an address of the vein as seen by DFhack. }; enum e_traffic @@ -171,15 +183,14 @@ namespace DFHack typedef int16_t tiletypes40d [16][16]; typedef DFHack::t_designation designations40d [16][16]; - typedef DFHack::t_occupancy occupancies40d [16][16]; +// typedef DFHack::t_occupancy occupancies40d [16][16]; typedef uint8_t biome_indices40d [16]; typedef struct { tiletypes40d tiletypes; designations40d designation; - occupancies40d occupancy; - // really a '7', but I use 8 to make it neater :) +// occupancies40d occupancy; biome_indices40d biome_indices; uint32_t origin; // the address where it came from t_blockflags blockflags; @@ -265,10 +276,11 @@ namespace DFHack bool ReadDesignations(uint32_t blockx, uint32_t blocky, uint32_t blockz, designations40d *buffer); bool WriteDesignations (uint32_t blockx, uint32_t blocky, uint32_t blockz, designations40d *buffer); + /* /// read/write block occupancies bool ReadOccupancy(uint32_t blockx, uint32_t blocky, uint32_t blockz, occupancies40d *buffer); bool WriteOccupancy(uint32_t blockx, uint32_t blocky, uint32_t blockz, occupancies40d *buffer); - +*/ /// read/write the block dirty bit - this is used to mark a map block so that DF scans it for designated jobs like digging bool ReadDirtyBit(uint32_t blockx, uint32_t blocky, uint32_t blockz, bool &dirtybit); bool WriteDirtyBit(uint32_t blockx, uint32_t blocky, uint32_t blockz, bool dirtybit); @@ -281,7 +293,7 @@ namespace DFHack bool ReadRegionOffsets(uint32_t blockx, uint32_t blocky, uint32_t blockz, biome_indices40d *buffer); /// read aggregated veins of a block - bool ReadVeins(uint32_t blockx, uint32_t blocky, uint32_t blockz, std::vector & veins, std::vector & ices); + bool ReadVeins(uint32_t blockx, uint32_t blocky, uint32_t blockz, std::vector & veins, std::vector & ices, std::vector & splatter); private: struct Private; diff --git a/dfhack/modules/Maps.cpp b/dfhack/modules/Maps.cpp index 820cf9c6c..6f0a3cd53 100644 --- a/dfhack/modules/Maps.cpp +++ b/dfhack/modules/Maps.cpp @@ -325,7 +325,7 @@ bool Maps::ReadRegionOffsets (uint32_t x, uint32_t y, uint32_t z, biome_indices4 // veins of a block, expects empty vein vectors -bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector & veins, vector & ices) +bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector & veins, vector & ices, vector &splatter) { uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; veins.clear(); @@ -344,6 +344,7 @@ bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector & veins { t_vein v; t_frozenliquidvein fv; + t_spattervein sv; // read the vein pointer from the vector uint32_t temp = * (uint32_t *) p_veins[i]; @@ -361,9 +362,18 @@ try_again: { // read the ice vein data (dereference pointer) g_pProcess->read (temp, sizeof(t_frozenliquidvein), (uint8_t *) &fv); + fv.address_of = temp; // store it in the vector ices.push_back (fv); } + else if(type == off.vein_spatter_vptr) + { + // read the splatter vein data (dereference pointer) + g_pProcess->read (temp, sizeof(t_spattervein), (uint8_t *) &sv); + sv.address_of = temp; + // store it in the vector + splatter.push_back (sv); + } else if(g_pProcess->readClassName(type) == "block_square_event_frozen_liquid") { off.vein_ice_vptr = type; @@ -374,6 +384,11 @@ try_again: off.vein_mineral_vptr = type; goto try_again; } + else if(g_pProcess->readClassName(type) == "block_square_event_material_spatter") + { + off.vein_spatter_vptr = type; + goto try_again; + } } return true; } diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 7ec11cc62..226eafc97 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -61,6 +61,10 @@ TARGET_LINK_LIBRARIES(dfvecc dfhack) ADD_EXECUTABLE(dftreedump treedump.cpp) TARGET_LINK_LIBRARIES(dftreedump dfhack) +# spatterdump - dump spatter 'veins' +ADD_EXECUTABLE(dfspatterdump spatterdump.cpp) +TARGET_LINK_LIBRARIES(dfspatterdump dfhack) + # catsplosion - Makes every cat pregnant, and almost due... # Author: Zhentar # ADD_EXECUTABLE(dfcatsplosion catsplosion.cpp) diff --git a/examples/miscutils.h b/examples/miscutils.h new file mode 100644 index 000000000..bfe768aae --- /dev/null +++ b/examples/miscutils.h @@ -0,0 +1,219 @@ +#ifndef DF_MISCUTILS +#define DF_MISCUTILS +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +#include + +void DumpObjStr0Vector (const char * name, DFHack::Process *p, uint32_t addr) +{ + cout << "----==== " << name << " ====----" << endl; + DFHack::DfVector vect(p,addr,4); + for(int i = 0; i < vect.getSize();i++) + { + uint32_t addr = *(uint32_t *) vect[i]; + cout << p->readSTLString(addr) << endl; + } + cout << endl; +} +void DumpObjVtables (const char * name, DFHack::Process *p, uint32_t addr) +{ + cout << "----==== " << name << " ====----" << endl; + DFHack::DfVector vect(p,addr,4); + for(int i = 0; i < vect.getSize();i++) + { + uint32_t addr = *(uint32_t *) vect[i]; + uint32_t vptr = p->readDWord(addr); + cout << p->readClassName(vptr) << endl; + } + cout << endl; +} +void DumpDWordVector (const char * name, DFHack::Process *p, uint32_t addr) +{ + cout << "----==== " << name << " ====----" << endl; + DFHack::DfVector vect(p,addr,4); + for(int i = 0; i < vect.getSize();i++) + { + uint32_t number = *(uint32_t *) vect[i]; + cout << number << endl; + } + cout << endl; +} + +/* +address = absolute address of dump start +length = length in lines. 1 line = 16 bytes +*/ +void hexdump (DFHack::API& DF, uint32_t address, uint32_t length) +{ + char *buf = new char[length * 16]; + + DF.ReadRaw(address, length * 16, (uint8_t *) buf); + for (int i = 0; i < length; i++) + { + // leading offset + cout << "0x" << hex << setw(8) << address + i*16 << "| "; + // groups + for(int j = 0; j < 4; j++) + { + // bytes + for(int k = 0; k < 4; k++) + { + int idx = i * 16 + j * 4 + k; + + cout << hex << setw(2) << int(static_cast(buf[idx])) << " "; + } + cout << " "; + } + cout << endl; + } + delete buf; +} + +void interleave_hex (DFHack::API& DF, vector < uint32_t > & addresses, uint32_t length) +{ + vector bufs; + + for(int counter = 0; counter < addresses.size(); counter ++) + { + char * buf = new char[length * 16]; + DF.ReadRaw(addresses[counter], length * 16, (uint8_t *) buf); + bufs.push_back(buf); + } + cout << setfill('0'); + + // output a header + cout << "line offset "; + for (int obj = 0; obj < addresses.size(); obj++) + { + cout << "0x" << hex << setw(9) << addresses[obj] << " "; + } + cout << endl; + + for(int offs = 0 ; offs < length * 16; offs += 4) + { + if((!(offs % 16)) && offs != 0) + { + cout << endl; + } + cout << setfill(' '); + cout << dec << setw(4) << offs/4 << " "; + cout << setfill('0'); + cout << "0x" << hex << setw(4) << offs << " "; + for (int object = 0; object < bufs.size(); object++) + { + // bytes + for(int k = 0; k < 4; k++) + { + uint8_t data = bufs[object][offs + k]; + cout << hex << setw(2) << int(static_cast(data)) << " "; + } + cout << " "; + } + cout << endl; + } + for(int counter = 0; counter < addresses.size(); counter ++) + { + delete bufs[counter]; + } +} + +template +void print_bits ( T val, std::ostream& out ) +{ + T n_bits = sizeof ( val ) * CHAR_BIT; + + for ( unsigned i = 0; i < n_bits; ++i ) { + out<< !!( val & 1 ) << " "; + val >>= 1; + } +} + +// this is probably completely bogus +std::string PrintSplatterType (int16_t mat1, int32_t mat2, vector &creature_types) +{ + std::string ret; + switch (mat1) + { + case 0: + return "Rock"; + break; + case 1: + return "Amber"; + break; + case 2: + return "Coral"; + break; + case 3: + return "Green Glass"; + break; + case 4: + return "Clear Glass"; + break; + case 5: + return "Crystal Glass"; + break; + case 6: + return "Ice"; + break; + case 7: + return "Coal"; + break; + case 8: + return "Potash"; + break; + case 9: + return "Ash"; + break; + case 10: + return "Pearlash"; + break; + case 11: + return "Lye"; + break; + case 12: + return "Mud"; + break; + case 13: + return "Vomit"; + break; + case 14: + return "Salt"; + break; + case 15: + return "Filth"; + break; + case 16: + return "Frozen? Filth"; + break; + case 18: + return "Grime"; + break; + case 0xF2: + return "Very Specific Blood (references a named creature)"; + break; + case 0x2A: + case 0x2B: + if(mat2 != -1) + { + ret += creature_types[mat2].id; + ret += " "; + } + ret += "Blood"; + return ret; + break; + default: + return "Unknown"; + break; + } +} + + +#endif \ No newline at end of file diff --git a/examples/spatterdump.cpp b/examples/spatterdump.cpp new file mode 100644 index 000000000..6190eba24 --- /dev/null +++ b/examples/spatterdump.cpp @@ -0,0 +1,152 @@ +// Just show some position data + +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "miscutils.h" + +using namespace DFHack; + +char shades[10] = {'#','$','O','=','+','|','-','^','.',' '}; +int main (int numargs, const char ** args) +{ + uint32_t addr; + uint32_t x_max,y_max,z_max; + vector veinVector; + vector IceVeinVector; + vector splatter; + + DFHack::API DF("Memory.xml"); + try + { + DF.Attach(); + } + catch (exception& e) + { + cerr << e.what() << endl; + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + + DFHack::Maps *Maps =DF.getMaps(); + DFHack::Position *Pos =DF.getPosition(); + DFHack::Materials *Mats =DF.getMaterials(); + vector creature_types; + + Mats->ReadCreatureTypes(creature_types); + + // init the map + if(!Maps->Start()) + { + cerr << "Can't init map." << endl; + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + + int32_t cx, cy, cz; + Maps->getSize(x_max,y_max,z_max); + Pos->getCursorCoords(cx,cy,cz); + if(cx == -30000) + { + // walk the map + for(uint32_t x = 0; x< x_max;x++) for(uint32_t y = 0; y< y_max;y++) for(uint32_t z = 0; z< z_max;z++) + { + if(Maps->isValidBlock(x,y,z)) + { + // look for splater veins + Maps->ReadVeins(x,y,z,veinVector,IceVeinVector,splatter); + if(splatter.size()) + { + printf("Block %d/%d/%d\n",x,y,z); + + for(int i = 0; i < splatter.size(); i++) + { + printf("Splatter %d\nmat1: %d\nunknown: %d\nmat2: %d\nmat3: %d\n",i,splatter[i].mat1,splatter[i].unk1,splatter[i].mat2,splatter[i].mat3); + cout << PrintSplatterType(splatter[i].mat1,splatter[i].mat2,creature_types) << endl; + printf("Address 0x%08x\n",splatter[i].address_of); + for(uint32_t yyy = 0; yyy < 16; yyy++) + { + cout << "|"; + for(uint32_t xxx = 0; xxx < 16; xxx++) + { + uint8_t intensity = splatter[i].intensity[xxx][yyy]; + cout << shades[9 - (intensity / 28)]; + } + cout << "|" << endl; + } + + hexdump(DF, splatter[i].address_of,20); + cout << endl; + } + } + } + } + } + else + { + uint32_t bx,by,bz; + bx = cx / 16; + by = cy / 16; + bz = cz; + // look for splater veins + Maps->ReadVeins(bx,by,bz,veinVector,IceVeinVector,splatter); + if(splatter.size()) + { + printf("Block %d/%d/%d\n",bx,by,bz); + + for(int i = 0; i < splatter.size(); i++) + { + printf("Splatter %d\nmat1: %d\nunknown: %d\nmat2: %d\nmat3: %d\n",i,splatter[i].mat1,splatter[i].unk1,splatter[i].mat2,splatter[i].mat3); + PrintSplatterType(splatter[i].mat1,splatter[i].mat2,creature_types); + cout << endl; + printf("Address 0x%08x\n",splatter[i].address_of); + for(uint32_t y = 0; y < 16; y++) + { + cout << "|"; + for(uint32_t x = 0; x < 16; x++) + { + uint8_t intensity = splatter[i].intensity[x][y]; + if(intensity) + { + cout << "#"; + } + else + { + cout << " "; + } + } + cout << "|" << endl; + } + + hexdump(DF, splatter[i].address_of,20); + cout << endl; + } + } + } + #ifndef LINUX_BUILD + cout << "Done. Press any key to continue" << endl; + cin.ignore(); + #endif + return 0; +} diff --git a/examples/veccheck.cpp b/examples/veccheck.cpp index 93452467f..e0d365073 100644 --- a/examples/veccheck.cpp +++ b/examples/veccheck.cpp @@ -19,16 +19,20 @@ using namespace std; #include #include #include +#include #include "miscutils.h" +using namespace DFHack; + +char shades[10] = {'#','$','O','=','+','|','-','^','.',' '}; int main (int numargs, const char ** args) { uint32_t addr; - if (numargs == 2) - { - istringstream input (args[1],istringstream::in); - input >> std::hex >> addr; - } + uint32_t x_max,y_max,z_max; + vector veinVector; + vector IceVeinVector; + vector splatter; + DFHack::API DF("Memory.xml"); try { @@ -42,7 +46,93 @@ int main (int numargs, const char ** args) #endif return 1; } - + + DFHack::Maps *Maps =DF.getMaps(); + DFHack::Position *Pos =DF.getPosition(); + // init the map + if(!Maps->Start()) + { + cerr << "Can't init map." << endl; + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + int32_t cx, cy, cz; + Maps->getSize(x_max,y_max,z_max); + Pos->getCursorCoords(cx,cy,cz); + if(cx == -30000) + { + // walk the map + for(uint32_t x = 0; x< x_max;x++) for(uint32_t y = 0; y< y_max;y++) for(uint32_t z = 0; z< z_max;z++) + { + if(Maps->isValidBlock(x,y,z)) + { + // look for splater veins + Maps->ReadVeins(x,y,z,veinVector,IceVeinVector,splatter); + if(splatter.size()) + { + printf("Block %d/%d/%d\n",x,y,z); + + for(int i = 0; i < splatter.size(); i++) + { + printf("Splatter %d\nmat1: %d\nunknown: %d\nmat2: %d\nmat3: %d\n",i,splatter[i].mat1,splatter[i].unk1,splatter[i].mat2,splatter[i].mat3); + for(uint32_t yyy = 0; yyy < 16; yyy++) + { + cout << "|"; + for(uint32_t xxx = 0; xxx < 16; xxx++) + { + uint8_t intensity = splatter[i].intensity[xxx][yyy]; + cout << shades[9 - (intensity / 28)]; + } + cout << "|" << endl; + } + + hexdump(DF, splatter[i].address_of,20); + cout << endl; + } + } + } + } + } + else + { + uint32_t bx,by,bz; + bx = cx / 16; + by = cy / 16; + bz = cz; + // look for splater veins + Maps->ReadVeins(bx,by,bz,veinVector,IceVeinVector,splatter); + if(splatter.size()) + { + printf("Block %d/%d/%d\n",bx,by,bz); + + for(int i = 0; i < splatter.size(); i++) + { + printf("Splatter %d\nmat1: %d\nunknown: %d\nmat2: %d\nmat3: %d\n",i,splatter[i].mat1,splatter[i].unk1,splatter[i].mat2,splatter[i].mat3); + for(uint32_t y = 0; y < 16; y++) + { + cout << "|"; + for(uint32_t x = 0; x < 16; x++) + { + uint8_t intensity = splatter[i].intensity[x][y]; + if(intensity) + { + cout << "#"; + } + else + { + cout << " "; + } + } + cout << "|" << endl; + } + + hexdump(DF, splatter[i].address_of,20); + cout << endl; + } + } + } #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; cin.ignore(); diff --git a/examples/veinlook.cpp b/examples/veinlook.cpp index b22723fa5..3f16036d1 100644 --- a/examples/veinlook.cpp +++ b/examples/veinlook.cpp @@ -21,6 +21,7 @@ using namespace std; #include #include #include +#include "miscutils.h" using namespace DFHack; @@ -307,10 +308,12 @@ main(int argc, char *argv[]) materials.clear(); mapblock40d blocks[3][3]; vector stonetypes; + vector creature_types; vector effects; vector< vector > layerassign; vector veinVector; vector IceVeinVector; + vector splatter; DFHack::Materials * Mats = 0; DFHack::Maps * Maps = 0; @@ -354,6 +357,13 @@ main(int argc, char *argv[]) pDF = 0; finish(0); } + + if(!Mats->ReadCreatureTypes(creature_types)) + { + error = "Can't read stone types."; + pDF = 0; + finish(0); + } /* // get region geology if(!DF.ReadGeology( layerassign )) @@ -444,6 +454,7 @@ main(int argc, char *argv[]) veinVector.clear(); IceVeinVector.clear(); effects.clear(); + splatter.clear(); dirtybit = 0; // Supend, read/write data @@ -473,7 +484,7 @@ main(int argc, char *argv[]) if(i == 0 && j == 0) { // read veins - Maps->ReadVeins(cursorX+i,cursorY+j,cursorZ,veinVector,IceVeinVector); + Maps->ReadVeins(cursorX+i,cursorY+j,cursorZ,veinVector,IceVeinVector,splatter); // get pointer to block blockaddr = Maps->getBlockPtr(cursorX+i,cursorY+j,cursorZ); @@ -556,11 +567,12 @@ main(int argc, char *argv[]) gotoxy(0,50); uint32_t mineralsize = veinVector.size(); uint32_t icesize = IceVeinVector.size(); - uint32_t totalVeinSize = mineralsize+ icesize; + uint32_t splattersize = splatter.size(); + uint32_t totalVeinSize = mineralsize+ icesize + splattersize; if(vein == totalVeinSize) vein = totalVeinSize - 1; if(vein < -1) vein = -1; cprintf("X %d/%d, Y %d/%d, Z %d/%d. Vein %d of %d",cursorX+1,x_max,cursorY+1,y_max,cursorZ,z_max,vein+1,totalVeinSize); - if(!veinVector.empty() || !IceVeinVector.empty()) + if(!veinVector.empty() || !IceVeinVector.empty() || !splatter.empty()) { if(vein != -1 && vein < totalVeinSize) { @@ -593,7 +605,7 @@ main(int argc, char *argv[]) gotoxy(0,51); cprintf("Mineral: %s",stonetypes[veinVector[vein].type].id); } - else + else if (vein < mineralsize + icesize) { realvein = vein - mineralsize; t_frozenliquidvein &frozen = IceVeinVector[realvein]; @@ -613,6 +625,26 @@ main(int argc, char *argv[]) gotoxy(0,51); cprintf("ICE"); } + else + { + realvein = vein - mineralsize - icesize; + t_spattervein &bloodmud = splatter[realvein]; + for(uint32_t yyy = 0; yyy < 16; yyy++) + { + for(uint32_t xxx = 0; xxx < 16; xxx++) + { + uint8_t intensity = splatter[realvein].intensity[xxx][yyy]; + if(intensity) + { + attron(A_STANDOUT); + putch(xxx+16,yyy+16,'*', COLOR_RED); + attroff(A_STANDOUT); + } + } + } + gotoxy(0,51); + cprintf("Spatter: %s",PrintSplatterType(splatter[realvein].mat1,splatter[realvein].mat2,creature_types).c_str()); + } } } gotoxy (0,52); diff --git a/output/Memory.xml b/output/Memory.xml index 9eac342f3..7cdbb2459 100644 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -1358,15 +1358,15 @@ 55 56 57 + 58 + 59 60 + 61 62 63 64 65 66 - 58 - 59 - 61 67 68 69 @@ -3026,6 +3026,8 @@ map_data_1b60_offset 0x1B9c
0x016AFE58
+ this is an array of 4B pointers to material templates and length 0x292 +
0x016b90cc
Constructions ============= diff --git a/tools/prospector.cpp b/tools/prospector.cpp index f944638dc..f75cedd96 100644 --- a/tools/prospector.cpp +++ b/tools/prospector.cpp @@ -110,6 +110,7 @@ int main (int argc, const char* argv[]) int16_t tempvein [16][16]; vector veins; vector iceveins; + vector splatter; uint32_t maximum_regionoffset = 0; uint32_t num_overflows = 0; // walk the map! @@ -128,7 +129,7 @@ int main (int argc, const char* argv[]) memset(tempvein, -1, sizeof(tempvein)); veins.clear(); - Maps->ReadVeins(x,y,z,veins,iceveins); + Maps->ReadVeins(x,y,z,veins,iceveins,splatter); if(showbaselayers) {