diff --git a/build/generate-MSVC-2010.bat b/build/generate-MSVC-2010.bat new file mode 100644 index 000000000..588051bc6 --- /dev/null +++ b/build/generate-MSVC-2010.bat @@ -0,0 +1,4 @@ +mkdir build-real +cd build-real +cmake ..\.. -G"Visual Studio 10" +pause \ No newline at end of file diff --git a/dfhack/APIPrivate.cpp b/dfhack/APIPrivate.cpp index 72f7517f1..9d41a0639 100644 --- a/dfhack/APIPrivate.cpp +++ b/dfhack/APIPrivate.cpp @@ -56,7 +56,7 @@ bool APIPrivate::InitReadNames() void APIPrivate::readName(t_name & name, uint32_t address) { - g_pProcess->readSTLString(address + name_firstname_offset , name.first_name, 128); - g_pProcess->readSTLString(address + name_nickname_offset , name.nickname, 128); - g_pProcess->read(address + name_words_offset ,48, (uint8_t *) name.words); + p->readSTLString(address + name_firstname_offset , name.first_name, 128); + p->readSTLString(address + name_nickname_offset , name.nickname, 128); + p->read(address + name_words_offset ,48, (uint8_t *) name.words); } \ No newline at end of file diff --git a/dfhack/DFHackAPI.cpp b/dfhack/DFHackAPI.cpp index 2ec8edccf..b023ccbd6 100644 --- a/dfhack/DFHackAPI.cpp +++ b/dfhack/DFHackAPI.cpp @@ -113,6 +113,62 @@ bool API::Detach() d->p = NULL; d->shm_start = 0; d->offset_descriptor = NULL; + // invalidate all modules + if(d->creatures) + { + delete d->creatures; + d->creatures = 0; + } + if(d->creatures) + { + delete d->creatures; + d->creatures = 0; + } + if(d->maps) + { + delete d->maps; + d->maps = 0; + } + if(d->gui) + { + delete d->gui; + d->gui = 0; + } + if(d->position) + { + delete d->position; + d->position = 0; + } + if(d->materials) + { + delete d->materials; + d->materials = 0; + } + if(d->gui) + { + delete d->gui; + d->gui = 0; + } + if(d->translation) + { + delete d->translation; + d->translation = 0; + } + if(d->vegetation) + { + delete d->vegetation; + d->vegetation = 0; + } + if(d->constructions) + { + delete d->constructions; + d->constructions = 0; + } + if(d->translation) + { + delete d->translation; + d->translation = 0; + } return true; } @@ -145,12 +201,12 @@ bool API::isSuspended() void API::ReadRaw (const uint32_t offset, const uint32_t size, uint8_t *target) { - g_pProcess->read (offset, size, target); + d->p->read (offset, size, target); } void API::WriteRaw (const uint32_t offset, const uint32_t size, uint8_t *source) { - g_pProcess->write (offset, size, source); + d->p->write (offset, size, source); } memory_info *API::getMemoryInfo() @@ -250,7 +306,7 @@ bool API::InitReadEffects ( uint32_t & numeffects ) return false; } d->effectsInited = true; - d->p_effect = new DfVector (d->p, effects, 4); + d->p_effect = new DfVector (d->p, effects); numeffects = d->p_effect->getSize(); return true; } @@ -263,9 +319,9 @@ bool API::ReadEffect(const uint32_t index, t_effect_df40d & effect) return false; // read pointer from vector at position - uint32_t temp = * (uint32_t *) d->p_effect->at (index); + uint32_t temp = d->p_effect->at (index); //read effect from memory - g_pProcess->read (temp, sizeof (t_effect_df40d), (uint8_t *) &effect); + d->p->read (temp, sizeof (t_effect_df40d), (uint8_t *) &effect); return true; } @@ -277,9 +333,9 @@ bool API::WriteEffect(const uint32_t index, const t_effect_df40d & effect) if(index >= d->p_effect->getSize()) return false; // read pointer from vector at position - uint32_t temp = * (uint32_t *) d->p_effect->at (index); + uint32_t temp = d->p_effect->at (index); // write effect to memory - g_pProcess->write(temp,sizeof(t_effect_df40d), (uint8_t *) &effect); + d->p->write(temp,sizeof(t_effect_df40d), (uint8_t *) &effect); return true; } @@ -306,7 +362,7 @@ bool API::InitReadNotes( uint32_t &numnotes ) d->note_name_offset = minfo->getOffset ("note_name"); d->note_xyz_offset = minfo->getOffset ("note_xyz"); - d->p_notes = new DfVector (d->p, notes, 4); + d->p_notes = new DfVector (d->p, notes); d->notesInited = true; numnotes = d->p_notes->getSize(); return true; @@ -322,12 +378,12 @@ bool API::ReadNote (const int32_t index, t_note & note) { if(!d->notesInited) return false; // read pointer from vector at position - uint32_t temp = * (uint32_t *) d->p_notes->at (index); - note.symbol = g_pProcess->readByte(temp); - note.foreground = g_pProcess->readWord(temp + d->note_foreground_offset); - note.background = g_pProcess->readWord(temp + d->note_background_offset); + uint32_t temp = d->p_notes->at (index); + note.symbol = d->p->readByte(temp); + note.foreground = d->p->readWord(temp + d->note_foreground_offset); + note.background = d->p->readWord(temp + d->note_background_offset); d->p->readSTLString (temp + d->note_name_offset, note.name, 128); - g_pProcess->read (temp + d->note_xyz_offset, 3*sizeof (uint16_t), (uint8_t *) ¬e.x); + d->p->read (temp + d->note_xyz_offset, 3*sizeof (uint16_t), (uint8_t *) ¬e.x); return true; } bool API::InitReadSettlements( uint32_t & numsettlements ) @@ -343,8 +399,8 @@ bool API::InitReadSettlements( uint32_t & numsettlements ) d->settlement_world_xy_offset = minfo->getOffset ("settlement_world_xy"); d->settlement_local_xy_offset = minfo->getOffset ("settlement_local_xy"); - d->p_settlements = new DfVector (d->p, allSettlements, 4); - d->p_current_settlement = new DfVector(d->p, currentSettlement,4); + d->p_settlements = new DfVector (d->p, allSettlements); + d->p_current_settlement = new DfVector(d->p, currentSettlement); d->settlementsInited = true; numsettlements = d->p_settlements->getSize(); return true; @@ -362,11 +418,11 @@ bool API::ReadSettlement(const int32_t index, t_settlement & settlement) if(!d->p_settlements->getSize()) return false; // read pointer from vector at position - uint32_t temp = * (uint32_t *) d->p_settlements->at (index); + uint32_t temp = d->p_settlements->at (index); settlement.origin = temp; d->readName(settlement.name, temp + d->settlement_name_offset); - g_pProcess->read(temp + d->settlement_world_xy_offset, 2 * sizeof(int16_t), (uint8_t *) &settlement.world_x); - g_pProcess->read(temp + d->settlement_local_xy_offset, 4 * sizeof(int16_t), (uint8_t *) &settlement.local_x1); + d->p->read(temp + d->settlement_world_xy_offset, 2 * sizeof(int16_t), (uint8_t *) &settlement.world_x); + d->p->read(temp + d->settlement_local_xy_offset, 4 * sizeof(int16_t), (uint8_t *) &settlement.local_x1); return true; } @@ -375,11 +431,11 @@ bool API::ReadCurrentSettlement(t_settlement & settlement) if(!d->settlementsInited) return false; if(!d->p_current_settlement->getSize()) return false; - uint32_t temp = * (uint32_t *) d->p_current_settlement->at(0); + uint32_t temp = d->p_current_settlement->at(0); settlement.origin = temp; d->readName(settlement.name, temp + d->settlement_name_offset); - g_pProcess->read(temp + d->settlement_world_xy_offset, 2 * sizeof(int16_t), (uint8_t *) &settlement.world_x); - g_pProcess->read(temp + d->settlement_local_xy_offset, 4 * sizeof(int16_t), (uint8_t *) &settlement.local_x1); + d->p->read(temp + d->settlement_world_xy_offset, 2 * sizeof(int16_t), (uint8_t *) &settlement.world_x); + d->p->read(temp + d->settlement_local_xy_offset, 4 * sizeof(int16_t), (uint8_t *) &settlement.local_x1); return true; } @@ -411,8 +467,8 @@ bool API::getItemIndexesInBox(vector &indexes, }; temp2 temp2; for(uint32_t i =0;ip_itm->at(i); - g_pProcess->read(temp+sizeof(uint32_t),5 * sizeof(uint16_t), (uint8_t *) &temp2); + 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) { @@ -449,7 +505,7 @@ bool API::InitReadItems(uint32_t & numitems) 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, 4); + d->p_itm = new DfVector (d->p, items); d->itemsInited = true; numitems = d->p_itm->getSize(); return true; @@ -468,10 +524,10 @@ bool API::ReadItem (const uint32_t index, t_item & item) t_item_df40d item_40d; // read pointer from vector at position - uint32_t temp = * (uint32_t *) d->p_itm->at (index); + uint32_t temp = d->p_itm->at (index); //read building from memory - g_pProcess->read (temp, sizeof (t_item_df40d), (uint8_t *) &item_40d); + d->p->read (temp, sizeof (t_item_df40d), (uint8_t *) &item_40d); // transform int32_t type = -1; @@ -486,7 +542,7 @@ bool API::ReadItem (const uint32_t index, t_item & item) 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 - g_pProcess->read (temp + d->item_material_offset, sizeof (t_matglossPair), (uint8_t *) &item.material); + 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); @@ -512,7 +568,7 @@ bool API::ReadItemTypes(vector< vector< t_itemType > > & itemTypes) 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,4); + DfVector p_temp (d->p, matgloss_address + i*matgloss_skip); vector< t_itemType > typesForVec; for(uint32_t j =0; jbase = 0; + d->p = 0; d->classindex = 0; } @@ -96,6 +98,10 @@ memory_info::memory_info(const memory_info &old) d->traits = old.d->traits; d->labors = old.d->labors; } +void memory_info::setParentProcess(Process * _p) +{ + d->p = _p; +} // destructor memory_info::~memory_info() @@ -327,7 +333,7 @@ void memory_info::setClassChild (t_class * parent, const char * name, const char // FIXME: stupid. we need a better container bool memory_info::resolveObjectToClassID(const uint32_t address, int32_t & classid) { - uint32_t vtable = g_pProcess->readDWord(address); + uint32_t vtable = d->p->readDWord(address); // try to find the vtable in our cache map::iterator it; it = d->classIDs.find(vtable); @@ -341,7 +347,7 @@ bool memory_info::resolveObjectToClassID(const uint32_t address, int32_t & class else// couldn't find? { // we set up the class for the first time - string classname = g_pProcess->readClassName(vtable); + string classname = d->p->readClassName(vtable); d->classIDs[vtable] = cl = setClass(classname.c_str(),vtable); } // and isn't a multi-class @@ -356,7 +362,7 @@ bool memory_info::resolveObjectToClassID(const uint32_t address, int32_t & class { // find the type vector & vec = cl->subs; - uint32_t type = g_pProcess->readWord(address + cl->type_offset); + uint32_t type = d->p->readWord(address + cl->type_offset); // return typed building if successful //FIXME: the vector should map directly to the type IDs here, so we don't have to mess with O(n) search for (uint32_t k = 0; k < vec.size();k++) @@ -393,6 +399,22 @@ bool memory_info::resolveClassnameToVPtr(const string classname, uint32_t & vptr return false; } +bool memory_info::resolveClassnameToClassID (const string classname, int32_t & classID) +{ + // FIXME: another stupid search. + classID = -1; + for(uint32_t i = 0;i< d->classnames.size();i++) + { + if(d->classnames[i] == classname) + { + classID = i; + return true; + } + } + // we failed to find anything that would match + return false; +} + bool memory_info::resolveClassIDToClassname (const int32_t classID, string & classname) { if (classID >=0 && (uint32_t)classID < d->classnames.size()) diff --git a/dfhack/DFProcess-linux-SHM.cpp b/dfhack/DFProcess-linux-SHM.cpp index bcc55fb08..b7b8045a3 100644 --- a/dfhack/DFProcess-linux-SHM.cpp +++ b/dfhack/DFProcess-linux-SHM.cpp @@ -46,7 +46,7 @@ using namespace DFHack; class SHMProcess::Private { public: - Private() + Private(Process * self_) { memdescriptor = NULL; process_ID = 0; @@ -62,10 +62,12 @@ class SHMProcess::Private suspend_lock = -1; attachmentIdx = 0; locked = false; + self = self_; }; ~Private(){}; memory_info * memdescriptor; DFWindow * window; + Process * self; pid_t process_ID; char *shm_addr; int shm_ID; @@ -118,7 +120,6 @@ bool SHMProcess::Private::SetAndWait (uint32_t state) FreeLocks(); attached = locked = identified = false; // we aren't the current process anymore - g_pProcess = NULL; throw Error::SHMServerDisappeared(); } else @@ -263,9 +264,10 @@ bool SHMProcess::Private::GetLocks() } SHMProcess::SHMProcess(uint32_t PID, vector< memory_info* >& known_versions) -: d(new Private()) +: d(new Private(this)) { d->process_ID = PID; + d->memdescriptor = 0; if(!attach()) { // couldn't attach to process @@ -336,8 +338,9 @@ bool SHMProcess::Private::validate(vector & known_versions) try{ if(hash == (*it)->getString("md5")) // are the md5 hashes the same? { - memory_info * m = *it; + memory_info *m = new memory_info(**it); memdescriptor = m; + m->setParentProcess(dynamic_cast( self )); identified = true; // cerr << "identified " << m->getVersion() << endl; return true; @@ -357,7 +360,8 @@ SHMProcess::~SHMProcess() { detach(); } - // destroy data model. this is assigned by processmanager + if(d->memdescriptor) + delete d->memdescriptor; if(d->window) { delete d->window; @@ -537,11 +541,11 @@ bool SHMProcess::resume() bool SHMProcess::attach() { - if(g_pProcess != 0) + if(d->attached) { - // FIXME: throw exception here - programmer error - cerr << "client is already attached to a process!" << endl; - return false; + if(!d->locked) + return suspend(); + return true; } if(!d->GetLocks()) { @@ -576,7 +580,6 @@ bool SHMProcess::attach() cerr << "unable to suspend" << endl; return false; } - g_pProcess = this; return true; } @@ -597,7 +600,6 @@ bool SHMProcess::detach() d->locked = false; d->attached = false; d->shm_addr = 0; - g_pProcess = 0; return true; } // fail if we can't detach @@ -608,7 +610,7 @@ bool SHMProcess::detach() void SHMProcess::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); // normal read under 1MB if(size <= SHM_BODY) @@ -645,7 +647,7 @@ void SHMProcess::read (uint32_t src_address, uint32_t size, uint8_t *target_buff uint8_t SHMProcess::readByte (const uint32_t offset) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; gcc_barrier @@ -655,7 +657,7 @@ uint8_t SHMProcess::readByte (const uint32_t offset) void SHMProcess::readByte (const uint32_t offset, uint8_t &val ) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; gcc_barrier @@ -665,7 +667,7 @@ void SHMProcess::readByte (const uint32_t offset, uint8_t &val ) uint16_t SHMProcess::readWord (const uint32_t offset) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; gcc_barrier @@ -675,7 +677,7 @@ uint16_t SHMProcess::readWord (const uint32_t offset) void SHMProcess::readWord (const uint32_t offset, uint16_t &val) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; gcc_barrier @@ -685,7 +687,7 @@ void SHMProcess::readWord (const uint32_t offset, uint16_t &val) uint32_t SHMProcess::readDWord (const uint32_t offset) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; gcc_barrier @@ -694,7 +696,26 @@ uint32_t SHMProcess::readDWord (const uint32_t offset) } void SHMProcess::readDWord (const uint32_t offset, uint32_t &val) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); + + D_SHMHDR->address = offset; + gcc_barrier + d->SetAndWait(CORE_READ_DWORD); + val = D_SHMHDR->value; +} + +float SHMProcess::readFloat (const uint32_t offset) +{ + if(!d->locked) throw Error::MemoryAccessDenied(); + + D_SHMHDR->address = offset; + gcc_barrier + d->SetAndWait(CORE_READ_DWORD); + return D_SHMHDR->value; +} +void SHMProcess::readFloat (const uint32_t offset, float &val) +{ + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; gcc_barrier @@ -708,7 +729,7 @@ void SHMProcess::readDWord (const uint32_t offset, uint32_t &val) void SHMProcess::writeDWord (uint32_t offset, uint32_t data) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; D_SHMHDR->value = data; @@ -719,7 +740,7 @@ void SHMProcess::writeDWord (uint32_t offset, uint32_t data) // using these is expensive. void SHMProcess::writeWord (uint32_t offset, uint16_t data) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; D_SHMHDR->value = data; @@ -729,7 +750,7 @@ void SHMProcess::writeWord (uint32_t offset, uint16_t data) void SHMProcess::writeByte (uint32_t offset, uint8_t data) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; D_SHMHDR->value = data; @@ -739,7 +760,7 @@ void SHMProcess::writeByte (uint32_t offset, uint8_t data) void SHMProcess::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); // normal write under 1MB if(size <= SHM_BODY) @@ -777,7 +798,7 @@ void SHMProcess::write (uint32_t dst_address, uint32_t size, uint8_t *source_buf // FIXME: butt-fugly const std::string SHMProcess::readCString (uint32_t offset) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); std::string temp; char temp_c[256]; @@ -796,7 +817,7 @@ const std::string SHMProcess::readCString (uint32_t offset) const std::string SHMProcess::readSTLString(uint32_t offset) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; full_barrier @@ -806,7 +827,7 @@ const std::string SHMProcess::readSTLString(uint32_t offset) size_t SHMProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; full_barrier @@ -820,7 +841,7 @@ size_t SHMProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapa void SHMProcess::writeSTLString(const uint32_t address, const std::string writeString) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = address; strncpy(D_SHMDATA(char),writeString.c_str(),writeString.length()+1); // length + 1 for the null terminator @@ -830,7 +851,7 @@ void SHMProcess::writeSTLString(const uint32_t address, const std::string writeS string SHMProcess::readClassName (uint32_t vptr) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); int typeinfo = readDWord(vptr - 0x4); int typestring = readDWord(typeinfo + 0x4); @@ -843,7 +864,7 @@ string SHMProcess::readClassName (uint32_t vptr) // get module index by name and version. bool 0 = error bool SHMProcess::getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); modulelookup * payload = D_SHMDATA(modulelookup); payload->version = version; @@ -873,7 +894,7 @@ char * SHMProcess::getSHMStart (void) bool SHMProcess::Private::Aux_Core_Attach(bool & versionOK, pid_t & PID) { - if(!locked) throw Error::SHMAccessDenied(); + if(!locked) throw Error::MemoryAccessDenied(); SHMDATA(coreattach)->cl_affinity = OS_getAffinity(); if(!SetAndWait(CORE_ATTACH)) return false; @@ -888,4 +909,4 @@ bool SHMProcess::Private::Aux_Core_Attach(bool & versionOK, pid_t & PID) if(useYield) cerr << "Using Yield!" << endl; #endif return true; -} \ No newline at end of file +} diff --git a/dfhack/DFProcess-linux-wine.cpp b/dfhack/DFProcess-linux-wine.cpp index da4a11fb2..8bbe7dc51 100644 --- a/dfhack/DFProcess-linux-wine.cpp +++ b/dfhack/DFProcess-linux-wine.cpp @@ -34,7 +34,7 @@ using namespace DFHack; class WineProcess::Private { public: - Private() + Private(Process * self_) { my_descriptor = NULL; my_handle = NULL; @@ -43,10 +43,12 @@ class WineProcess::Private attached = false; suspended = false; memFileHandle = 0; + self = self_; }; ~Private(){}; DFWindow* my_window; memory_info * my_descriptor; + Process * self; ProcessHandle my_handle; uint32_t my_pid; string memFile; @@ -58,7 +60,7 @@ class WineProcess::Private }; WineProcess::WineProcess(uint32_t pid, vector & known_versions) -: d(new Private()) +: d(new Private(this)) { char dir_name [256]; char exe_link_name [256]; @@ -69,6 +71,7 @@ WineProcess::WineProcess(uint32_t pid, vector & known_versions) int target_result; d->identified = false; + d->my_descriptor = 0; sprintf(dir_name,"/proc/%d/", pid); sprintf(exe_link_name,"/proc/%d/exe", pid); @@ -147,8 +150,11 @@ bool WineProcess::Private::validate(char* exe_file, uint32_t pid, char* mem_file // are the md5 hashes the same? if(memory_info::OS_WINDOWS == (*it)->getOS() && hash == thishash) { - memory_info * m = *it; + + // keep track of created memory_info object so we can destroy it later + memory_info *m = new memory_info(**it); my_descriptor = m; + m->setParentProcess(dynamic_cast( self )); my_handle = my_pid = pid; // tell WineProcess about the /proc/PID/mem file memFile = mem_file; @@ -165,6 +171,9 @@ WineProcess::~WineProcess() { detach(); } + // destroy our copy of the memory descriptor + if(d->my_descriptor) + delete d->my_descriptor; if(d->my_window) delete d->my_window; delete d; @@ -281,9 +290,11 @@ bool WineProcess::resume() bool WineProcess::attach() { int status; - if(g_pProcess != NULL) + if(d->attached) { - return false; + if(!d->suspended) + return suspend(); + return true; } // can we attach? if (ptrace(PTRACE_ATTACH , d->my_handle, NULL, NULL) == -1) @@ -323,7 +334,6 @@ bool WineProcess::attach() else { d->attached = true; - g_pProcess = this; d->memFileHandle = proc_pid_mem; return true; // we are attached @@ -356,7 +366,6 @@ bool WineProcess::detach() else { d->attached = false; - g_pProcess = NULL; return true; } } @@ -377,6 +386,7 @@ void WineProcess::read (const uint32_t offset, const uint32_t size, uint8_t *tar cerr << "pread failed: can't read " << size << " bytes at addres " << offset << endl; cerr << "errno: " << errno << endl; errno = 0; + throw Error::MemoryAccessDenied(); } else { @@ -420,6 +430,17 @@ void WineProcess::readDWord (const uint32_t offset, uint32_t &val) read(offset, 4, (uint8_t *) &val); } +float WineProcess::readFloat (const uint32_t offset) +{ + float val; + read(offset, 4, (uint8_t *) &val); + return val; +} +void WineProcess::readFloat (const uint32_t offset, float &val) +{ + read(offset, 4, (uint8_t *) &val); +} + /* * WRITING */ @@ -516,20 +537,20 @@ size_t WineProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcap Uint32 capacity */ uint32_t start_offset = offset + 4; - size_t length = g_pProcess->readDWord(offset + 20); + size_t length = readDWord(offset + 20); - size_t capacity = g_pProcess->readDWord(offset + 24); + size_t capacity = readDWord(offset + 24); size_t read_real = min(length, bufcapacity-1);// keep space for null termination // read data from inside the string structure if(capacity < 16) { - g_pProcess->read(start_offset, read_real , (uint8_t *)buffer); + read(start_offset, read_real , (uint8_t *)buffer); } else // read data from what the offset + 4 dword points to { - start_offset = g_pProcess->readDWord(start_offset);// dereference the start offset - g_pProcess->read(start_offset, read_real, (uint8_t *)buffer); + start_offset = readDWord(start_offset);// dereference the start offset + read(start_offset, read_real, (uint8_t *)buffer); } buffer[read_real] = 0; @@ -550,19 +571,19 @@ const string WineProcess::readSTLString (uint32_t offset) Uint32 capacity */ uint32_t start_offset = offset + 4; - uint32_t length = g_pProcess->readDWord(offset + 20); - uint32_t capacity = g_pProcess->readDWord(offset + 24); + uint32_t length = readDWord(offset + 20); + uint32_t capacity = readDWord(offset + 24); char * temp = new char[capacity+1]; // read data from inside the string structure if(capacity < 16) { - g_pProcess->read(start_offset, capacity, (uint8_t *)temp); + read(start_offset, capacity, (uint8_t *)temp); } else // read data from what the offset + 4 dword points to { - start_offset = g_pProcess->readDWord(start_offset);// dereference the start offset - g_pProcess->read(start_offset, capacity, (uint8_t *)temp); + start_offset = readDWord(start_offset);// dereference the start offset + read(start_offset, capacity, (uint8_t *)temp); } temp[length] = 0; @@ -578,4 +599,4 @@ string WineProcess::readClassName (uint32_t vptr) string raw = readCString(typeinfo + 0xC); // skips the .?AV raw.resize(raw.length() - 2);// trim @@ from end return raw; -} \ No newline at end of file +} diff --git a/dfhack/DFProcess-linux.cpp b/dfhack/DFProcess-linux.cpp index 71220a051..48d3b1342 100644 --- a/dfhack/DFProcess-linux.cpp +++ b/dfhack/DFProcess-linux.cpp @@ -33,7 +33,7 @@ using namespace DFHack; class NormalProcess::Private { public: - Private() + Private(Process * self_) { my_descriptor = NULL; my_handle = NULL; @@ -42,6 +42,7 @@ class NormalProcess::Private attached = false; suspended = false; memFileHandle = 0; + self = self_; }; ~Private(){}; DFWindow* my_window; @@ -53,11 +54,12 @@ class NormalProcess::Private bool attached; bool suspended; bool identified; + Process * self; bool validate(char * exe_file, uint32_t pid, char * mem_file, vector & known_versions); }; NormalProcess::NormalProcess(uint32_t pid, vector< memory_info* >& known_versions) -: d(new Private()) +: d(new Private(this)) { char dir_name [256]; char exe_link_name [256]; @@ -68,6 +70,7 @@ NormalProcess::NormalProcess(uint32_t pid, vector< memory_info* >& known_version int target_result; d->identified = false; + d->my_descriptor = 0; sprintf(dir_name,"/proc/%d/", pid); sprintf(exe_link_name,"/proc/%d/exe", pid); @@ -125,7 +128,9 @@ bool NormalProcess::Private::validate(char * exe_file,uint32_t pid, char * memFi memory_info * m = *it; if (memory_info::OS_LINUX == m->getOS()) { - my_descriptor = m; + memory_info *m2 = new memory_info(*m); + my_descriptor = m2; + m2->setParentProcess(dynamic_cast( self )); my_handle = my_pid = pid; } else @@ -153,6 +158,9 @@ NormalProcess::~NormalProcess() { detach(); } + // destroy our copy of the memory descriptor + if(d->my_descriptor) + delete d->my_descriptor; // destroy data model. this is assigned by processmanager if(d->my_window) delete d->my_window; @@ -270,9 +278,11 @@ bool NormalProcess::resume() bool NormalProcess::attach() { int status; - if(g_pProcess != NULL) + if(d->attached) { - return false; + if(!d->suspended) + return suspend(); + return true; } // can we attach? if (ptrace(PTRACE_ATTACH , d->my_handle, NULL, NULL) == -1) @@ -311,7 +321,6 @@ bool NormalProcess::attach() else { d->attached = true; - g_pProcess = this; d->memFileHandle = proc_pid_mem; return true; // we are attached @@ -344,7 +353,6 @@ bool NormalProcess::detach() else { d->attached = false; - g_pProcess = NULL; return true; } } @@ -365,6 +373,7 @@ void NormalProcess::read (const uint32_t offset, const uint32_t size, uint8_t *t cerr << "pread failed: can't read " << size << " bytes at addres " << offset << endl; cerr << "errno: " << errno << endl; errno = 0; + throw Error::MemoryAccessDenied(); } else { @@ -408,6 +417,17 @@ void NormalProcess::readDWord (const uint32_t offset, uint32_t &val) read(offset, 4, (uint8_t *) &val); } +float NormalProcess::readFloat (const uint32_t offset) +{ + float val; + read(offset, 4, (uint8_t *) &val); + return val; +} +void NormalProcess::readFloat (const uint32_t offset, float &val) +{ + read(offset, 4, (uint8_t *) &val); +} + /* * WRITING */ @@ -500,10 +520,10 @@ struct _Rep_base size_t NormalProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity) { _Rep_base header; - offset = g_pProcess->readDWord(offset); - g_pProcess->read(offset - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header); + offset = readDWord(offset); + read(offset - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header); size_t read_real = min((size_t)header._M_length, bufcapacity-1);// keep space for null termination - g_pProcess->read(offset,read_real,(uint8_t * )buffer); + read(offset,read_real,(uint8_t * )buffer); buffer[read_real] = 0; return read_real; } @@ -512,12 +532,12 @@ const string NormalProcess::readSTLString (uint32_t offset) { _Rep_base header; - offset = g_pProcess->readDWord(offset); - g_pProcess->read(offset - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header); + offset = readDWord(offset); + read(offset - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header); // FIXME: use char* everywhere, avoid string char * temp = new char[header._M_length+1]; - g_pProcess->read(offset,header._M_length+1,(uint8_t * )temp); + read(offset,header._M_length+1,(uint8_t * )temp); string ret(temp); delete temp; return ret; @@ -531,4 +551,4 @@ string NormalProcess::readClassName (uint32_t vptr) size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers size_t end = raw.length(); return raw.substr(start,end-start); -} \ No newline at end of file +} diff --git a/dfhack/DFProcess-windows-SHM.cpp b/dfhack/DFProcess-windows-SHM.cpp index 49ceabeac..f849741f7 100644 --- a/dfhack/DFProcess-windows-SHM.cpp +++ b/dfhack/DFProcess-windows-SHM.cpp @@ -52,7 +52,7 @@ class SHMProcess::Private ~Private(){}; memory_info * memdescriptor; DFWindow * window; - SHMProcess * q; + SHMProcess * self; uint32_t process_ID; char *shm_addr; HANDLE DFSVMutex; @@ -110,7 +110,6 @@ bool SHMProcess::Private::SetAndWait (uint32_t state) FreeLocks(); attached = locked = identified = false; // we aren't the current process anymore - g_pProcess = NULL; throw Error::SHMServerDisappeared(); } else @@ -282,7 +281,7 @@ SHMProcess::SHMProcess(uint32_t PID, vector & known_versions) : d(new Private()) { d->process_ID = PID; - d->q = this; + d->self = this; // attach the SHM if(!attach()) { @@ -345,9 +344,9 @@ bool SHMProcess::Private::validate(vector & known_versions) uint32_t base = (uint32_t)hmod; // read from this process - uint32_t pe_offset = q->readDWord(base+0x3C); - q->read(base + pe_offset , sizeof(pe_header), (uint8_t *)&pe_header); - q->read(base + pe_offset+ sizeof(pe_header), sizeof(sections) , (uint8_t *)§ions ); + uint32_t pe_offset = self->readDWord(base+0x3C); + self->read(base + pe_offset , sizeof(pe_header), (uint8_t *)&pe_header); + self->read(base + pe_offset+ sizeof(pe_header), sizeof(sections) , (uint8_t *)§ions ); // iterate over the list of memory locations vector::iterator it; @@ -367,6 +366,7 @@ bool SHMProcess::Private::validate(vector & known_versions) memory_info *m = new memory_info(**it); m->RebaseAll(base); memdescriptor = m; + m->setParentProcess(self); identified = true; cerr << "identified " << m->getVersion() << endl; CloseHandle(hProcess); @@ -577,10 +577,11 @@ bool SHMProcess::resume() bool SHMProcess::attach() { - if(g_pProcess != 0) + if(d->attached) { - cerr << "there's already a process attached" << endl; - return false; + if(!d->locked) + return suspend(); + return true; } //cerr << "attach" << endl;// FIXME: throw if(!d->GetLocks()) @@ -639,7 +640,6 @@ bool SHMProcess::attach() //cerr << "unable to suspend" << endl;// FIXME: throw return false; } - g_pProcess = this; return true; } @@ -663,13 +663,12 @@ bool SHMProcess::detach() d->attached = false; d->locked = false; d->shm_addr = false; - g_pProcess = 0; return true; } void SHMProcess::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); // normal read under 1MB if(size <= SHM_BODY) @@ -706,7 +705,7 @@ void SHMProcess::read (uint32_t src_address, uint32_t size, uint8_t *target_buff uint8_t SHMProcess::readByte (const uint32_t offset) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; full_barrier @@ -716,7 +715,7 @@ uint8_t SHMProcess::readByte (const uint32_t offset) void SHMProcess::readByte (const uint32_t offset, uint8_t &val ) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; full_barrier @@ -726,7 +725,7 @@ void SHMProcess::readByte (const uint32_t offset, uint8_t &val ) uint16_t SHMProcess::readWord (const uint32_t offset) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; full_barrier @@ -736,7 +735,7 @@ uint16_t SHMProcess::readWord (const uint32_t offset) void SHMProcess::readWord (const uint32_t offset, uint16_t &val) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; full_barrier @@ -746,7 +745,7 @@ void SHMProcess::readWord (const uint32_t offset, uint16_t &val) uint32_t SHMProcess::readDWord (const uint32_t offset) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; full_barrier @@ -755,7 +754,26 @@ uint32_t SHMProcess::readDWord (const uint32_t offset) } void SHMProcess::readDWord (const uint32_t offset, uint32_t &val) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); + + D_SHMHDR->address = offset; + full_barrier + d->SetAndWait(CORE_READ_DWORD); + val = D_SHMHDR->value; +} + +float SHMProcess::readFloat (const uint32_t offset) +{ + if(!d->locked) throw Error::MemoryAccessDenied(); + + D_SHMHDR->address = offset; + full_barrier + d->SetAndWait(CORE_READ_DWORD); + return D_SHMHDR->value; +} +void SHMProcess::readFloat (const uint32_t offset, float &val) +{ + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; full_barrier @@ -763,13 +781,14 @@ void SHMProcess::readDWord (const uint32_t offset, uint32_t &val) val = D_SHMHDR->value; } + /* * WRITING */ void SHMProcess::writeDWord (uint32_t offset, uint32_t data) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; D_SHMHDR->value = data; @@ -780,7 +799,7 @@ void SHMProcess::writeDWord (uint32_t offset, uint32_t data) // using these is expensive. void SHMProcess::writeWord (uint32_t offset, uint16_t data) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; D_SHMHDR->value = data; @@ -790,7 +809,7 @@ void SHMProcess::writeWord (uint32_t offset, uint16_t data) void SHMProcess::writeByte (uint32_t offset, uint8_t data) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; D_SHMHDR->value = data; @@ -800,7 +819,7 @@ void SHMProcess::writeByte (uint32_t offset, uint8_t data) void SHMProcess::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); // normal write under 1MB if(size <= SHM_BODY) @@ -838,7 +857,7 @@ void SHMProcess::write (uint32_t dst_address, uint32_t size, uint8_t *source_buf // FIXME: butt-fugly const std::string SHMProcess::readCString (uint32_t offset) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); std::string temp; char temp_c[256]; @@ -857,7 +876,7 @@ const std::string SHMProcess::readCString (uint32_t offset) const std::string SHMProcess::readSTLString(uint32_t offset) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; full_barrier @@ -867,7 +886,7 @@ const std::string SHMProcess::readSTLString(uint32_t offset) size_t SHMProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = offset; full_barrier @@ -881,7 +900,7 @@ size_t SHMProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapa void SHMProcess::writeSTLString(const uint32_t address, const std::string writeString) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); D_SHMHDR->address = address; strncpy(D_SHMDATA(char),writeString.c_str(),writeString.length()+1); // length + 1 for the null terminator @@ -901,7 +920,7 @@ string SHMProcess::readClassName (uint32_t vptr) // get module index by name and version. bool 0 = error bool SHMProcess::getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); modulelookup * payload = D_SHMDATA(modulelookup); payload->version = version; @@ -924,13 +943,13 @@ bool SHMProcess::getModuleIndex (const char * name, const uint32_t version, uint char * SHMProcess::getSHMStart (void) { - if(!d->locked) throw Error::SHMAccessDenied(); + if(!d->locked) throw Error::MemoryAccessDenied(); return /*d->shm_addr_with_cl_idx*/ d->shm_addr; } bool SHMProcess::Private::Aux_Core_Attach(bool & versionOK, uint32_t & PID) { - if(!locked) throw Error::SHMAccessDenied(); + if(!locked) throw Error::MemoryAccessDenied(); SHMDATA(coreattach)->cl_affinity = OS_getAffinity(); if(!SetAndWait(CORE_ATTACH)) return false; @@ -945,4 +964,4 @@ bool SHMProcess::Private::Aux_Core_Attach(bool & versionOK, uint32_t & PID) if(useYield) cerr << "Using Yield!" << endl; #endif return true; -} \ No newline at end of file +} diff --git a/dfhack/DFProcess-windows.cpp b/dfhack/DFProcess-windows.cpp index b1dac9568..7c1a8612b 100644 --- a/dfhack/DFProcess-windows.cpp +++ b/dfhack/DFProcess-windows.cpp @@ -82,11 +82,21 @@ NormalProcess::NormalProcess(uint32_t pid, vector & known_versio // temporarily assign this to allow some checks d->my_handle = hProcess; + d->my_main_thread = 0; // read from this process - uint32_t pe_offset = readDWord(base+0x3C); - read(base + pe_offset , sizeof(pe_header), (uint8_t *)&pe_header); - read(base + pe_offset+ sizeof(pe_header), sizeof(sections) , (uint8_t *)§ions ); - d->my_handle = 0; + try + { + uint32_t pe_offset = readDWord(base+0x3C); + read(base + pe_offset , sizeof(pe_header), (uint8_t *)&pe_header); + read(base + pe_offset+ sizeof(pe_header), sizeof(sections) , (uint8_t *)§ions ); + d->my_handle = 0; + } + catch (exception &) + { + CloseHandle(hProcess); + d->my_handle = 0; + return; + } // see if there's a version entry that matches this process vector::iterator it; @@ -117,6 +127,7 @@ NormalProcess::NormalProcess(uint32_t pid, vector & known_versio m->RebaseAll(base); // keep track of created memory_info object so we can destroy it later d->my_descriptor = m; + m->setParentProcess(this); // process is responsible for destroying its data model d->my_pid = pid; d->my_handle = hProcess; @@ -239,12 +250,13 @@ bool NormalProcess::resume() bool NormalProcess::attach() { - if(g_pProcess != NULL) + if(d->attached) { - return false; + if(!d->suspended) + return suspend(); + return true; } d->attached = true; - g_pProcess = this; suspend(); return true; @@ -259,7 +271,6 @@ bool NormalProcess::detach() } resume(); d->attached = false; - g_pProcess = NULL; return true; } @@ -315,64 +326,89 @@ void NormalProcess::getMemRanges( vector & ranges ) uint8_t NormalProcess::readByte (const uint32_t offset) { uint8_t result; - ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint8_t), NULL); + if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint8_t), NULL)) + throw Error::MemoryAccessDenied(); return result; } void NormalProcess::readByte (const uint32_t offset,uint8_t &result) { - ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint8_t), NULL); + if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint8_t), NULL)) + throw Error::MemoryAccessDenied(); } uint16_t NormalProcess::readWord (const uint32_t offset) { uint16_t result; - ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint16_t), NULL); + if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint16_t), NULL)) + throw Error::MemoryAccessDenied(); return result; } void NormalProcess::readWord (const uint32_t offset, uint16_t &result) { - ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint16_t), NULL); + if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint16_t), NULL)) + throw Error::MemoryAccessDenied(); } uint32_t NormalProcess::readDWord (const uint32_t offset) { uint32_t result; - ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint32_t), NULL); + if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint32_t), NULL)) + throw Error::MemoryAccessDenied(); return result; } void NormalProcess::readDWord (const uint32_t offset, uint32_t &result) { - ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint32_t), NULL); + if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint32_t), NULL)) + throw Error::MemoryAccessDenied(); +} + +float NormalProcess::readFloat (const uint32_t offset) +{ + float result; + if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(float), NULL)) + throw Error::MemoryAccessDenied(); + return result; +} + +void NormalProcess::readFloat (const uint32_t offset, float &result) +{ + if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(float), NULL)) + throw Error::MemoryAccessDenied(); } void NormalProcess::read (const uint32_t offset, uint32_t size, uint8_t *target) { - ReadProcessMemory(d->my_handle, (int*) offset, target, size, NULL); + if(!ReadProcessMemory(d->my_handle, (int*) offset, target, size, NULL)) + throw Error::MemoryAccessDenied(); } // WRITING void NormalProcess::writeDWord (const uint32_t offset, uint32_t data) { - WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint32_t), NULL); + if(!WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint32_t), NULL)) + throw Error::MemoryAccessDenied(); } // using these is expensive. void NormalProcess::writeWord (uint32_t offset, uint16_t data) { - WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint16_t), NULL); + if(!WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint16_t), NULL)) + throw Error::MemoryAccessDenied(); } void NormalProcess::writeByte (uint32_t offset, uint8_t data) { - WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint8_t), NULL); + if(!WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint8_t), NULL)) + throw Error::MemoryAccessDenied(); } void NormalProcess::write (uint32_t offset, uint32_t size, uint8_t *source) { - WriteProcessMemory(d->my_handle, (int*) offset, source, size, NULL); + if(!WriteProcessMemory(d->my_handle, (int*) offset, source, size, NULL)) + throw Error::MemoryAccessDenied(); } @@ -383,7 +419,9 @@ const string NormalProcess::readCString (const uint32_t offset) string temp; char temp_c[256]; DWORD read; - ReadProcessMemory(d->my_handle, (int *) offset, temp_c, 254, &read); // needs to be 254+1 byte for the null term + if(!ReadProcessMemory(d->my_handle, (int *) offset, temp_c, 254, &read)) + throw Error::MemoryAccessDenied(); + // needs to be 254+1 byte for the null term temp_c[read+1] = 0; temp.assign(temp_c); return temp; @@ -403,20 +441,20 @@ Uint32 length Uint32 capacity */ uint32_t start_offset = offset + 4; - size_t length = g_pProcess->readDWord(offset + 20); + size_t length = readDWord(offset + 20); - size_t capacity = g_pProcess->readDWord(offset + 24); + size_t capacity = readDWord(offset + 24); size_t read_real = min(length, bufcapacity-1);// keep space for null termination // read data from inside the string structure if(capacity < 16) { - g_pProcess->read(start_offset, read_real , (uint8_t *)buffer); + read(start_offset, read_real , (uint8_t *)buffer); } else // read data from what the offset + 4 dword points to { - start_offset = g_pProcess->readDWord(start_offset);// dereference the start offset - g_pProcess->read(start_offset, read_real, (uint8_t *)buffer); + start_offset = readDWord(start_offset);// dereference the start offset + read(start_offset, read_real, (uint8_t *)buffer); } buffer[read_real] = 0; @@ -437,19 +475,19 @@ const string NormalProcess::readSTLString (uint32_t offset) Uint32 capacity */ uint32_t start_offset = offset + 4; - uint32_t length = g_pProcess->readDWord(offset + 20); - uint32_t capacity = g_pProcess->readDWord(offset + 24); + uint32_t length = readDWord(offset + 20); + uint32_t capacity = readDWord(offset + 24); char * temp = new char[capacity+1]; // read data from inside the string structure if(capacity < 16) { - g_pProcess->read(start_offset, capacity, (uint8_t *)temp); + read(start_offset, capacity, (uint8_t *)temp); } else // read data from what the offset + 4 dword points to { - start_offset = g_pProcess->readDWord(start_offset);// dereference the start offset - g_pProcess->read(start_offset, capacity, (uint8_t *)temp); + start_offset = readDWord(start_offset);// dereference the start offset + read(start_offset, capacity, (uint8_t *)temp); } temp[length] = 0; @@ -465,4 +503,4 @@ string NormalProcess::readClassName (uint32_t vptr) string raw = readCString(typeinfo + 0xC); // skips the .?AV raw.resize(raw.length() - 2);// trim @@ from end return raw; -} \ No newline at end of file +} diff --git a/dfhack/DFProcessEnumerator-linux.cpp b/dfhack/DFProcessEnumerator-linux.cpp index 19103c1f3..1f1e26eeb 100644 --- a/dfhack/DFProcessEnumerator-linux.cpp +++ b/dfhack/DFProcessEnumerator-linux.cpp @@ -35,9 +35,6 @@ distribution. using namespace DFHack; -/// HACK: global variables (only one process can be attached at the same time.) -Process * DFHack::g_pProcess; ///< current process. non-NULL when picked - class DFHack::ProcessEnumerator::Private { public: diff --git a/dfhack/DFProcessEnumerator-windows.cpp b/dfhack/DFProcessEnumerator-windows.cpp index da42ebd50..4d078e2e3 100644 --- a/dfhack/DFProcessEnumerator-windows.cpp +++ b/dfhack/DFProcessEnumerator-windows.cpp @@ -29,9 +29,6 @@ distribution. #include "DFMemInfoManager.h" using namespace DFHack; -/// HACK: global variables (only one process can be attached at the same time.) -Process * DFHack::g_pProcess; ///< current process. non-NULL when picked - class DFHack::ProcessEnumerator::Private { public: diff --git a/dfhack/DFVector.cpp b/dfhack/DFVector.cpp index 61c33c30c..c1ff06910 100644 --- a/dfhack/DFVector.cpp +++ b/dfhack/DFVector.cpp @@ -24,34 +24,8 @@ distribution. #include "Tranquility.h" #include "DFCommonInternal.h" -#include "DFVector.h" #include "DFMemInfo.h" #include "DFProcess.h" - +#include "DFVector.h" using namespace DFHack; - -DfVector::DfVector(Process * p, uint32_t address, uint32_t _item_size) -{ - uint32_t triplet[3]; - item_size = _item_size; - memory_info * mem = p->getDescriptor(); - uint32_t offs = mem->getOffset("vector_triplet"); - - p->read(address + offs, sizeof(triplet), (uint8_t *) &triplet); - start = triplet[0]; - uint32_t byte_size = triplet[1] - triplet[0]; - size = byte_size / item_size; - data = (uint8_t *) new char[byte_size]; - g_pProcess->read(start,byte_size, (uint8_t *)data); -}; -DfVector::DfVector() -{ - data = 0; -}; - -DfVector::~DfVector() -{ - if(data) - delete [] data; -}; diff --git a/dfhack/include/DFCommonInternal.h b/dfhack/include/DFCommonInternal.h index 255dde145..3a583c23b 100644 --- a/dfhack/include/DFCommonInternal.h +++ b/dfhack/include/DFCommonInternal.h @@ -25,6 +25,10 @@ distribution. #ifndef DFCOMMONINTERNAL_H_INCLUDED #define DFCOMMONINTERNAL_H_INCLUDED +// this makes everything that includes this file export symbols whn using DFHACK_EXPORT (see Export.h) +#define BUILD_DFHACK_LIB + +#include "DFGlobal.h" #include "Tranquility.h" #include @@ -65,14 +69,6 @@ typedef pid_t ProcessHandle; typedef HANDLE ProcessHandle; #endif -namespace DFHack -{ - class Process; - /* - * Currently attached process and its handle - */ - extern Process * g_pProcess; ///< current process. non-NULL when picked -} #ifndef BUILD_DFHACK_LIB # define BUILD_DFHACK_LIB #endif diff --git a/dfhack/include/DFError.h b/dfhack/include/DFError.h index 375a5c581..15086b9bb 100644 --- a/dfhack/include/DFError.h +++ b/dfhack/include/DFError.h @@ -236,11 +236,11 @@ namespace DFHack return s.str().c_str(); } }; - class DFHACK_EXPORT SHMAccessDenied : public std::exception + class DFHACK_EXPORT MemoryAccessDenied : public std::exception { public: - SHMAccessDenied() {} - virtual ~SHMAccessDenied() throw(){}; + MemoryAccessDenied() {} + virtual ~MemoryAccessDenied() throw(){}; std::string type; diff --git a/dfhack/include/DFGlobal.h b/dfhack/include/DFGlobal.h new file mode 100644 index 000000000..2143d5f66 --- /dev/null +++ b/dfhack/include/DFGlobal.h @@ -0,0 +1,11 @@ +#ifndef DFHACK_GLOBAL +#define DFHACK_GLOBAL +#include "Export.h" + +// globals, if any, should be placed here. + +namespace DFHack +{ + // extern DFHACK_EXPORT TYPE NAME; +} +#endif \ No newline at end of file diff --git a/dfhack/include/DFMemInfo.h b/dfhack/include/DFMemInfo.h index 3712031d1..9066c116e 100644 --- a/dfhack/include/DFMemInfo.h +++ b/dfhack/include/DFMemInfo.h @@ -34,6 +34,12 @@ distribution. namespace DFHack { + /* + * Stubs + */ + + class Process; + /* * Common data types */ @@ -148,6 +154,7 @@ namespace DFHack void setLabor(const string &, const string &); void RebaseVTable(const int32_t offset); + void setParentProcess(Process * _p); t_class * setClass (const char * classname, uint32_t vptr = 0, uint32_t typeoffset = 0); void setClassChild (t_class * parent, const char * classname, const char * type); @@ -160,18 +167,15 @@ namespace DFHack bool resolveObjectToClassID (const uint32_t address, int32_t & classID); /* - * Get a classID from an address. The address has to point to the start of a virtual object (one with a virtual base class) - * can fail if the class is not in the cache + * Get a ClassID when you know the classname. can fail if the class is not in the cache */ bool resolveClassnameToClassID (const string classname, int32_t & classID); - //bool resolveClassnameToClassID (const char * classname, int32_t & classID); /* * Get a vptr from a classname. Can fail if the type is not in the cache * limited to normal classes, variable-dependent types will resolve to the base class */ bool resolveClassnameToVPtr ( const string classname, uint32_t & vptr ); - //bool resolveClassnameToVPtr ( const char * classname, uint32_t & vptr ); /* * Get a classname from a previous classID. Can fail if the type is not in the cache (you use bogus classID) diff --git a/dfhack/include/DFProcess.h b/dfhack/include/DFProcess.h index 65adefe7f..951ebfac9 100644 --- a/dfhack/include/DFProcess.h +++ b/dfhack/include/DFProcess.h @@ -34,7 +34,6 @@ namespace DFHack class memory_info; class Process; class DFWindow; - class DfVector; // structure describing a memory range struct DFHACK_EXPORT t_memrange @@ -82,7 +81,9 @@ namespace DFHack virtual bool forceresume() = 0; virtual uint32_t readDWord(const uint32_t address) = 0; + virtual float readFloat(const uint32_t address) = 0; virtual void readDWord(const uint32_t address, uint32_t & value) = 0; + virtual void readFloat(const uint32_t address, float & value) = 0; virtual uint16_t readWord(const uint32_t address) = 0; virtual void readWord(const uint32_t address, uint16_t & value) = 0; virtual uint8_t readByte(const uint32_t address) = 0; @@ -151,7 +152,9 @@ namespace DFHack bool forceresume(); uint32_t readDWord(const uint32_t address); + float readFloat(const uint32_t address); void readDWord(const uint32_t address, uint32_t & value); + void readFloat(const uint32_t address, float & value); uint16_t readWord(const uint32_t address); void readWord(const uint32_t address, uint16_t & value); uint8_t readByte(const uint32_t address); @@ -214,7 +217,9 @@ namespace DFHack bool forceresume(); uint32_t readDWord(const uint32_t address); + float readFloat(const uint32_t address); void readDWord(const uint32_t address, uint32_t & value); + void readFloat(const uint32_t address, float & value); uint16_t readWord(const uint32_t address); void readWord(const uint32_t address, uint16_t & value); uint8_t readByte(const uint32_t address); @@ -276,7 +281,9 @@ namespace DFHack bool forceresume(); uint32_t readDWord(const uint32_t address); + float readFloat(const uint32_t address); void readDWord(const uint32_t address, uint32_t & value); + void readFloat(const uint32_t address, float & value); uint16_t readWord(const uint32_t address); void readWord(const uint32_t address, uint16_t & value); uint8_t readByte(const uint32_t address); diff --git a/dfhack/include/DFTileTypes.h b/dfhack/include/DFTileTypes.h index 8931a8422..dc6912be4 100644 --- a/dfhack/include/DFTileTypes.h +++ b/dfhack/include/DFTileTypes.h @@ -417,75 +417,75 @@ namespace DFHack {0 ,EMPTY, AIR, VAR_1}, {"glowing floor" ,FLOOR, CYAN_GLOW, VAR_1}, {0 ,EMPTY, AIR, VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall RD2",WALL,OBSIDIAN,VAR_1}, // 270 - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall R2D",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall R2U",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall RU2",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall L2U",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall LU2",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall L2D",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall LD2",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall LRUD",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall RUD",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall LRD",WALL,OBSIDIAN,VAR_1}, // 280 - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, + {"smooth obsidian wall LRU",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall LUD",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall RD",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall RU",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall LU",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall LD",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall UD",WALL,OBSIDIAN,VAR_1}, + {"smooth obsidian wall LR",WALL,OBSIDIAN,VAR_1}, + {"smooth featstone wall RD2",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall R2D",WALL,FEATSTONE,VAR_1}, // 290 - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall R2U",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall RU2",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall L2U",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall LU2",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall L2D",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall LD2",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall LRUD",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall RUD",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall LRD",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall LRU",WALL,FEATSTONE,VAR_1}, //300 - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth featstone? wall",WALL,FEATSTONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, + {"smooth featstone wall LUD",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall RD",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall RU",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall LU",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall LD",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall UD",WALL,FEATSTONE,VAR_1}, + {"smooth featstone wall LR",WALL,FEATSTONE,VAR_1}, + {"smooth stone wall RD2",WALL,STONE,VAR_1}, + {"smooth stone wall R2D",WALL,STONE,VAR_1}, + {"smooth stone wall R2U",WALL,STONE,VAR_1}, //310 - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, + {"smooth stone wall RU2",WALL,STONE,VAR_1}, + {"smooth stone wall L2U",WALL,STONE,VAR_1}, + {"smooth stone wall LU2",WALL,STONE,VAR_1}, + {"smooth stone wall L2D",WALL,STONE,VAR_1}, + {"smooth stone wall LD2",WALL,STONE,VAR_1}, + {"smooth stone wall LRUD",WALL,STONE,VAR_1}, + {"smooth stone wall RUD",WALL,STONE,VAR_1}, + {"smooth stone wall LRD",WALL,STONE,VAR_1}, + {"smooth stone wall LRU",WALL,STONE,VAR_1}, + {"smooth stone wall LUD",WALL,STONE,VAR_1}, //320 - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, - {"smooth stone wall",WALL,STONE,VAR_1}, + {"smooth stone wall RD",WALL,STONE,VAR_1}, + {"smooth stone wall RU",WALL,STONE,VAR_1}, + {"smooth stone wall LU",WALL,STONE,VAR_1}, + {"smooth stone wall LD",WALL,STONE,VAR_1}, + {"smooth stone wall UD",WALL,STONE,VAR_1}, + {"smooth stone wall LR",WALL,STONE,VAR_1}, {"obsidian fortification",FORTIFICATION,OBSIDIAN,VAR_1}, {"featstone? fortification",FORTIFICATION,FEATSTONE,VAR_1}, {"cracked obsidian wall",WALL,OBSIDIAN,VAR_1}, @@ -494,10 +494,14 @@ namespace DFHack // 330 {"worn obsidian wall",WALL,OBSIDIAN,VAR_1}, {"obsidian wall",WALL,OBSIDIAN,VAR_1}, - {"cracked stone wall",WALL,STONE,VAR_1}, - {"damaged stone wall",WALL,STONE,VAR_1}, - {"worn stone wall",WALL,STONE,VAR_1}, - {"stone wall",WALL,STONE,VAR_1}, + /*MAPTILE_FEATSTONE_WALL_WORN1, + MAPTILE_FEATSTONE_WALL_WORN2, + MAPTILE_FEATSTONE_WALL_WORN3, + MAPTILE_FEATSTONE_WALL,*/ + {"cracked featstone wall",WALL,STONE,VAR_1}, + {"damaged featstone wall",WALL,STONE,VAR_1}, + {"worn featstone wall",WALL,STONE,VAR_1}, + {"featstone wall",WALL,STONE,VAR_1}, {"stone floor",FLOOR,STONE,VAR_1}, {"stone floor",FLOOR,STONE,VAR_2}, {"stone floor",FLOOR,STONE,VAR_3}, @@ -508,16 +512,16 @@ namespace DFHack {"obsidian floor",FLOOR,OBSIDIAN,VAR_2}, {"obsidian floor",FLOOR,OBSIDIAN,VAR_3}, {"obsidian floor",FLOOR,OBSIDIAN,VAR_4}, - {"featstone? floor",FLOOR,FEATSTONE,VAR_1}, - {"featstone? floor",FLOOR,FEATSTONE,VAR_2}, - {"featstone? floor",FLOOR,FEATSTONE,VAR_3}, - {"featstone? floor",FLOOR,FEATSTONE,VAR_4}, - {"grass",FLOOR,GRASS,VAR_1}, - {"grass",FLOOR,GRASS,VAR_2}, + {"featstone floor 1",FLOOR,FEATSTONE,VAR_1}, + {"featstone floor 2",FLOOR,FEATSTONE,VAR_2}, + {"featstone floor 3",FLOOR,FEATSTONE,VAR_3}, + {"featstone floor 4",FLOOR,FEATSTONE,VAR_4}, + {"grass 1",FLOOR,GRASS,VAR_1}, + {"grass 2",FLOOR,GRASS,VAR_2}, // 350 - {"grass",FLOOR,GRASS,VAR_3}, - {"grass",FLOOR,GRASS,VAR_4}, + {"grass 3",FLOOR,GRASS,VAR_3}, + {"grass 4",FLOOR,GRASS,VAR_4}, {"soil floor",FLOOR,SOIL,VAR_1}, {"soil floor",FLOOR,SOIL,VAR_2}, {"soil floor",FLOOR,SOIL,VAR_3}, @@ -533,58 +537,58 @@ namespace DFHack {"damaged ice wall",WALL,ICE,VAR_1}, {"worn ice wall",WALL,ICE,VAR_1}, {"ice wall",WALL,ICE,VAR_1}, - {"river",FLOOR,SOIL,VAR_1}, - {"river",FLOOR,SOIL,VAR_1}, - {"river",FLOOR,SOIL,VAR_1}, - {"river",FLOOR,SOIL,VAR_1}, - {"river",FLOOR,SOIL,VAR_1}, + {"river N",FLOOR,SOIL,VAR_1}, + {"river S",FLOOR,SOIL,VAR_1}, + {"river E",FLOOR,SOIL,VAR_1}, + {"river W",FLOOR,SOIL,VAR_1}, + {"river NW",FLOOR,SOIL,VAR_1}, //370 - {"river",FLOOR,SOIL,VAR_1}, - {"river",FLOOR,SOIL,VAR_1}, - {"river",FLOOR,SOIL,VAR_1}, - {"stream",FLOOR,SOIL,VAR_1}, - {"stream",FLOOR,SOIL,VAR_1}, - {"stream",FLOOR,SOIL,VAR_1}, - {"stream",FLOOR,SOIL,VAR_1}, - {"stream",FLOOR,SOIL,VAR_1}, - {"stream",FLOOR,SOIL,VAR_1}, - {"stream",FLOOR,SOIL,VAR_1}, + {"river NE",FLOOR,SOIL,VAR_1}, + {"river SW",FLOOR,SOIL,VAR_1}, + {"river SE",FLOOR,SOIL,VAR_1}, + {"stream bed N",FLOOR,SOIL,VAR_1}, + {"stream bed S",FLOOR,SOIL,VAR_1}, + {"stream bed E",FLOOR,SOIL,VAR_1}, + {"stream bed W",FLOOR,SOIL,VAR_1}, + {"stream bed NW",FLOOR,SOIL,VAR_1}, + {"stream bed NE",FLOOR,SOIL,VAR_1}, + {"stream bed SW",FLOOR,SOIL,VAR_1}, // 380 - {"stream",FLOOR,SOIL,VAR_1}, + {"stream bed SE",FLOOR,SOIL,VAR_1}, {"stream top",FLOOR,SOIL,VAR_1}, {0 ,EMPTY, AIR, VAR_1}, {0 ,EMPTY, AIR, VAR_1}, {0 ,EMPTY, AIR, VAR_1}, {0 ,EMPTY, AIR, VAR_1}, {0 ,EMPTY, AIR, VAR_1}, - {"dry grass",FLOOR,GRASS_DRY,VAR_1}, - {"dry grass",FLOOR,GRASS_DRY,VAR_2}, - {"dry grass",FLOOR,GRASS_DRY,VAR_3}, + {"dry grass 1",FLOOR,GRASS_DRY,VAR_1}, + {"dry grass 2",FLOOR,GRASS_DRY,VAR_2}, + {"dry grass 3",FLOOR,GRASS_DRY,VAR_3}, // 390 - {"dry grass",FLOOR,GRASS_DRY,VAR_4}, + {"dry grass 4",FLOOR,GRASS_DRY,VAR_4}, {"dead tree",TREE_DEAD,SOIL,VAR_1}, {"dead sapling",SAPLING_DEAD,SOIL,VAR_1}, {"dead shrub",SHRUB_DEAD,SOIL,VAR_1}, - {"dead grass",FLOOR,GRASS_DEAD,VAR_1}, - {"dead grass",FLOOR,GRASS_DEAD,VAR_2}, - {"dead grass",FLOOR,GRASS_DEAD,VAR_3}, - {"dead grass",FLOOR,GRASS_DEAD,VAR_4}, - {"grass",FLOOR,GRASS2,VAR_1}, - {"grass",FLOOR,GRASS2,VAR_2}, + {"dead grass 1",FLOOR,GRASS_DEAD,VAR_1}, + {"dead grass 2",FLOOR,GRASS_DEAD,VAR_2}, + {"dead grass 3",FLOOR,GRASS_DEAD,VAR_3}, + {"dead grass 4",FLOOR,GRASS_DEAD,VAR_4}, + {"grass B1",FLOOR,GRASS2,VAR_1}, + {"grass B2",FLOOR,GRASS2,VAR_2}, // 400 - {"grass",FLOOR,GRASS2,VAR_3}, - {"grass",FLOOR,GRASS2,VAR_4}, + {"grass B3",FLOOR,GRASS2,VAR_3}, + {"grass B4",FLOOR,GRASS2,VAR_4}, {"boulder",BOULDER,STONE,VAR_1}, {"obsidian boulder",BOULDER,OBSIDIAN,VAR_1}, {"featstone? boulder",BOULDER,FEATSTONE,VAR_1}, - {"pebbles",PEBBLES,STONE,VAR_1}, - {"pebbles",PEBBLES,STONE,VAR_2}, - {"pebbles",PEBBLES,STONE,VAR_3}, - {"pebbles",PEBBLES,STONE,VAR_4}, + {"pebbles 1",PEBBLES,STONE,VAR_1}, + {"pebbles 2",PEBBLES,STONE,VAR_2}, + {"pebbles 3",PEBBLES,STONE,VAR_3}, + {"pebbles 4",PEBBLES,STONE,VAR_4}, {"obsidian shards",PEBBLES,OBSIDIAN,VAR_1}, // 410 diff --git a/dfhack/include/DFVector.h b/dfhack/include/DFVector.h index 12e940cd0..7d69330a8 100644 --- a/dfhack/include/DFVector.h +++ b/dfhack/include/DFVector.h @@ -27,41 +27,61 @@ distribution. #include "Tranquility.h" #include "Export.h" - namespace DFHack { class Process; + template class DFHACK_EXPORT DfVector { private: - // starting offset - uint32_t start; - // vector size - uint32_t size; - uint32_t item_size; - uint8_t* data; - + uint32_t _start;// starting offset + uint32_t _size;// vector size + T * data; // cached data public: - DfVector(); - DfVector(Process * p, uint32_t address, uint32_t item_size); - ~DfVector(); + DfVector(Process * p, uint32_t address) + { + uint32_t triplet[3]; + memory_info * mem = p->getDescriptor(); + uint32_t offs = mem->getOffset("vector_triplet"); + + p->read(address + offs, sizeof(triplet), (uint8_t *) &triplet); + _start = triplet[0]; + uint32_t byte_size = triplet[1] - triplet[0]; + _size = byte_size / sizeof(T); + data = new T[_size]; + p->read(_start,byte_size, (uint8_t *)data); + }; + DfVector() + { + data = 0; + }; + ~DfVector() + { + if(data) + delete [] data; + }; // get offset of the specified index - inline void* operator[] (uint32_t index) + inline T& operator[] (uint32_t index) { // FIXME: vector out of bounds exception //assert(index < size); - return data + index*item_size; + return data[index]; }; // get offset of the specified index - inline void* at (uint32_t index) + inline T& at (uint32_t index) { //assert(index < size); - return data + index*item_size; + return data[index]; }; // get vector size - inline uint32_t getSize () + inline uint32_t size () + { + return _size; + }; + // get vector start + inline uint32_t start () { - return size; + return _start; }; }; } diff --git a/dfhack/include/modules/Buildings.h b/dfhack/include/modules/Buildings.h index fd3589bee..1d27a6f41 100644 --- a/dfhack/include/modules/Buildings.h +++ b/dfhack/include/modules/Buildings.h @@ -32,9 +32,15 @@ namespace DFHack Buildings(APIPrivate * d); ~Buildings(); bool Start(uint32_t & numBuildings); + // read one building at offset bool Read (const uint32_t index, t_building & building); bool Finish(); + // read a vector of names + bool ReadCustomWorkshopTypes(map & btypes); + // returns -1 on error, >= 0 for real value + int32_t GetCustomWorkshopType(t_building & building); + private: struct Private; Private *d; diff --git a/dfhack/include/modules/Constructions.h b/dfhack/include/modules/Constructions.h index 9732b2e66..634d3643c 100644 --- a/dfhack/include/modules/Constructions.h +++ b/dfhack/include/modules/Constructions.h @@ -14,7 +14,7 @@ namespace DFHack constr_boulder = 4, constr_logs = 5, }; - #pragma pack(1) + #pragma pack(push, 1) struct t_construction { //0 @@ -38,7 +38,7 @@ namespace DFHack // added later by dfhack uint32_t origin; }; - + #pragma pack (pop) class APIPrivate; class DFHACK_EXPORT Constructions { diff --git a/dfhack/include/modules/Creatures.h b/dfhack/include/modules/Creatures.h index aa3627977..e6f826f9b 100644 --- a/dfhack/include/modules/Creatures.h +++ b/dfhack/include/modules/Creatures.h @@ -319,6 +319,7 @@ namespace DFHack uint16_t y; uint16_t z; uint32_t race; + int32_t civ; t_creaturflags1 flags1; t_creaturflags2 flags2; @@ -344,9 +345,9 @@ namespace DFHack t_attrib recuperation; t_attrib disease_resistance; int32_t squad_leader_id; - uint8_t sex; + uint8_t sex; // really a caste uint32_t pregnancy_timer; //Countdown timer to giving birth - + bool has_default_soul; t_soul defaultSoul; }; @@ -368,10 +369,11 @@ namespace DFHack bool ReadCreature(const int32_t index, t_creature & furball); /// write labors of a creature (for Dwarf Therapist) bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]); - + uint32_t GetDwarfRaceIndex ( void ); + int32_t GetDwarfCivId ( void ); private: struct Private; Private *d; }; } -#endif \ No newline at end of file +#endif diff --git a/dfhack/include/modules/Maps.h b/dfhack/include/modules/Maps.h index 1192baf6a..2e03d54ce 100644 --- a/dfhack/include/modules/Maps.h +++ b/dfhack/include/modules/Maps.h @@ -114,9 +114,10 @@ namespace DFHack e_traffic traffic : 2; // needs enum unsigned int flow_forbid : 1; // what? unsigned int liquid_static : 1; - unsigned int moss : 1;// I LOVE MOSS - unsigned int feature_present : 1; // another wtf... is this required for magma pipes to work? + unsigned int feature_type_1 : 1; // this tile is a part of a feature + unsigned int feature_type_2 : 1; // this tile is a part of a feature unsigned int liquid_character : 2; // those ripples on streams? + }; union t_designation @@ -199,6 +200,7 @@ namespace DFHack typedef DFHack::t_designation designations40d [16][16]; typedef DFHack::t_occupancy occupancies40d [16][16]; typedef uint8_t biome_indices40d [16]; + typedef uint16_t t_temperatures [16][16]; typedef struct { @@ -290,6 +292,10 @@ 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 temperatures + bool ReadTemperatures(uint32_t blockx, uint32_t blocky, uint32_t blockz, t_temperatures *temp1, t_temperatures *temp2); + bool WriteTemperatures (uint32_t blockx, uint32_t blocky, uint32_t blockz, t_temperatures *temp1, t_temperatures *temp2); + /// 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); diff --git a/dfhack/include/modules/Materials.h b/dfhack/include/modules/Materials.h index 83a4f203b..f4073c1ca 100644 --- a/dfhack/include/modules/Materials.h +++ b/dfhack/include/modules/Materials.h @@ -17,6 +17,15 @@ namespace DFHack char name[128]; //this is the name displayed ingame }; + struct t_descriptor_color + { + char id[128]; // id in the raws + float r; + float v; + float b; + char name[128]; //displayed name + }; + struct t_matglossPlant { char id[128]; //the id in the raws @@ -29,6 +38,27 @@ namespace DFHack char extract_name[128]; }; + struct t_creaturecaste + { + char rawname[128]; + char singular[128]; + char plural[128]; + char adjective[128]; + }; + // this doesn't transfer well across the shm gap... + struct t_creaturetype + { + char rawname[128]; + vector castes; + uint8_t tile_character; + struct + { + uint16_t fore; + uint16_t back; + uint16_t bright; + } tilecolor; + }; + class DFHACK_EXPORT Materials { public: @@ -45,8 +75,12 @@ namespace DFHack // TODO: maybe move to creatures? bool ReadCreatureTypes (std::vector & output); + bool ReadCreatureTypesEx (vector & creatures); + + bool ReadDescriptorColors(std::vector & output); private: - APIPrivate* d; + class Private; + Private* d; }; } #endif diff --git a/dfhack/modules/Buildings.cpp b/dfhack/modules/Buildings.cpp index 8e8c4de31..b9f44e139 100644 --- a/dfhack/modules/Buildings.cpp +++ b/dfhack/modules/Buildings.cpp @@ -52,10 +52,14 @@ struct t_building_df40d struct Buildings::Private { uint32_t buildings_vector; - // translation - DfVector * p_bld; - + uint32_t custom_workshop_vector; + uint32_t building_custom_workshop_type; + uint32_t custom_workshop_type; + uint32_t custom_workshop_name; + int32_t custom_workshop_id; + DfVector * p_bld; APIPrivate *d; + Process * owner; bool Inited; bool Started; }; @@ -64,9 +68,15 @@ Buildings::Buildings(APIPrivate * d_) { d = new Private; d->d = d_; + d->owner = d_->p; d->Inited = d->Started = false; memory_info * mem = d->d->offset_descriptor; + d->custom_workshop_vector = mem->getAddress("custom_workshop_vector"); + d->building_custom_workshop_type = mem->getOffset("building_custom_workshop_type"); + d->custom_workshop_type = mem->getOffset("custom_workshop_type"); + d->custom_workshop_name = mem->getOffset("custom_workshop_name"); d->buildings_vector = mem->getAddress ("buildings_vector"); + mem->resolveClassnameToClassID("building_custom_workshop", d->custom_workshop_id); d->Inited = true; } @@ -79,8 +89,8 @@ Buildings::~Buildings() bool Buildings::Start(uint32_t & numbuildings) { - d->p_bld = new DfVector (g_pProcess, d->buildings_vector, 4); - numbuildings = d->p_bld->getSize(); + d->p_bld = new DfVector (d->owner, d->buildings_vector); + numbuildings = d->p_bld->size(); d->Started = true; return true; } @@ -92,15 +102,15 @@ bool Buildings::Read (const uint32_t index, t_building & building) t_building_df40d bld_40d; // read pointer from vector at position - uint32_t temp = * (uint32_t *) d->p_bld->at (index); + uint32_t temp = d->p_bld->at (index); //d->p_bld->read(index,(uint8_t *)&temp); //read building from memory - g_pProcess->read (temp, sizeof (t_building_df40d), (uint8_t *) &bld_40d); + d->owner->read (temp, sizeof (t_building_df40d), (uint8_t *) &bld_40d); // transform int32_t type = -1; - d->d->offset_descriptor->resolveObjectToClassID (temp, type); + d->owner->getDescriptor()->resolveObjectToClassID (temp, type); building.origin = temp; building.vtable = bld_40d.vtable; building.x1 = bld_40d.x1; @@ -122,4 +132,40 @@ bool Buildings::Finish() } d->Started = false; return true; +} + +bool Buildings::ReadCustomWorkshopTypes(map & btypes) +{ + if(!d->Started) + return false; + + Process * p = d->owner; + DfVector p_matgloss (p, d->custom_workshop_vector); + uint32_t size = p_matgloss.size(); + btypes.clear(); + + for (uint32_t i = 0; i < size;i++) + { + string out = p->readSTLString (p_matgloss[i] + d->custom_workshop_name); + uint32_t type = p->readDWord (p_matgloss[i] + d->custom_workshop_type); + #ifdef DEBUG + cout << out << ": " << type << endl; + #endif + btypes[type] = out; + } + return true; +} + +int32_t Buildings::GetCustomWorkshopType(t_building & building) +{ + if(!d->Inited) + return false; + int32_t type = (int32_t)building.type; + int32_t ret = -1; + if(type != -1 && type == d->custom_workshop_id) + { + // read the custom workshop subtype + ret = (int32_t) d->owner->readDWord(building.origin + d->building_custom_workshop_type); + } + return ret; } \ No newline at end of file diff --git a/dfhack/modules/Constructions.cpp b/dfhack/modules/Constructions.cpp index 1aa9c5a00..aa4a71a03 100644 --- a/dfhack/modules/Constructions.cpp +++ b/dfhack/modules/Constructions.cpp @@ -37,9 +37,10 @@ struct Constructions::Private { uint32_t construction_vector; // translation - DfVector * p_cons; + DfVector * p_cons; APIPrivate *d; + Process * owner; bool Inited; bool Started; }; @@ -48,6 +49,7 @@ Constructions::Constructions(APIPrivate * d_) { d = new Private; d->d = d_; + d->owner = d_->p; d->p_cons = 0; d->Inited = d->Started = false; memory_info * mem = d->d->offset_descriptor; @@ -64,8 +66,8 @@ Constructions::~Constructions() bool Constructions::Start(uint32_t & numconstructions) { - d->p_cons = new DfVector (g_pProcess, d->construction_vector, 4); - numconstructions = d->p_cons->getSize(); + d->p_cons = new DfVector (d->owner, d->construction_vector); + numconstructions = d->p_cons->size(); d->Started = true; return true; } @@ -76,10 +78,10 @@ bool Constructions::Read (const uint32_t index, t_construction & construction) if(!d->Started) return false; // read pointer from vector at position - uint32_t temp = * (uint32_t *) d->p_cons->at (index); + uint32_t temp = d->p_cons->at (index); //read construction from memory - g_pProcess->read (temp, sizeof (t_construction), (uint8_t *) &construction); + d->owner->read (temp, sizeof (t_construction), (uint8_t *) &construction); // transform construction.origin = temp; diff --git a/dfhack/modules/Creatures.cpp b/dfhack/modules/Creatures.cpp index 0b756e81d..8c83e1ed9 100644 --- a/dfhack/modules/Creatures.cpp +++ b/dfhack/modules/Creatures.cpp @@ -25,9 +25,9 @@ distribution. #include "DFCommonInternal.h" #include "../private/APIPrivate.h" -#include "DFVector.h" #include "DFMemInfo.h" #include "DFProcess.h" +#include "DFVector.h" #include "DFError.h" #include "DFTypes.h" @@ -51,14 +51,18 @@ struct Creatures::Private bool Started; Creatures2010::creature_offsets creatures; uint32_t creature_module; - DfVector *p_cre; + uint32_t dwarf_race_index_addr; + uint32_t dwarf_civ_id_addr; + DfVector *p_cre; APIPrivate *d; + Process *owner; }; Creatures::Creatures(APIPrivate* _d) { d = new Private; d->d = _d; + Process * p = d->owner = _d->p; d->Inited = false; d->Started = false; d->d->InitReadNames(); // throws on error @@ -71,6 +75,7 @@ Creatures::Creatures(APIPrivate* _d) creatures.profession_offset = minfo->getOffset ("creature_profession"); creatures.custom_profession_offset = minfo->getOffset ("creature_custom_profession"); creatures.race_offset = minfo->getOffset ("creature_race"); + creatures.civ_offset = minfo->getOffset ("creature_civ"); creatures.flags1_offset = minfo->getOffset ("creature_flags1"); creatures.flags2_offset = minfo->getOffset ("creature_flags2"); creatures.name_offset = minfo->getOffset ("creature_name"); @@ -83,6 +88,7 @@ Creatures::Creatures(APIPrivate* _d) creatures.default_soul_offset = minfo->getOffset("creature_default_soul"); creatures.physical_offset = minfo->getOffset("creature_physical"); creatures.mood_offset = minfo->getOffset("creature_mood"); + creatures.pickup_equipment_bit = minfo->getOffset("creature_pickup_equipment_bit"); // soul offsets creatures.soul_skills_vector_offset = minfo->getOffset("soul_skills_vector"); creatures.soul_mental_offset = minfo->getOffset("soul_mental"); @@ -92,14 +98,15 @@ Creatures::Creatures(APIPrivate* _d) creatures.name_firstname_offset = minfo->getOffset("name_firstname"); creatures.name_nickname_offset = minfo->getOffset("name_nickname"); creatures.name_words_offset = minfo->getOffset("name_words"); - + d->dwarf_race_index_addr = minfo->getAddress("dwarf_race_index"); + d->dwarf_civ_id_addr = minfo->getAddress("dwarf_civ_id"); // upload offsets to the SHM - if(g_pProcess->getModuleIndex("Creatures2010",1,d->creature_module)) + if(p->getModuleIndex("Creatures2010",1,d->creature_module)) { // supply the module with offsets so it can work with them memcpy(SHMDATA(Creatures2010::creature_offsets),&creatures,sizeof(Creatures2010::creature_offsets)); const uint32_t cmd = Creatures2010::CREATURE_INIT + (d->creature_module << 16); - g_pProcess->SetAndWait(cmd); + p->SetAndWait(cmd); } d->Inited = true; } @@ -118,9 +125,9 @@ Creatures::~Creatures() bool Creatures::Start( uint32_t &numcreatures ) { - d->p_cre = new DfVector (d->d->p, d->creatures.vector, 4); + d->p_cre = new DfVector (d->owner, d->creatures.vector); d->Started = true; - numcreatures = d->p_cre->getSize(); + numcreatures = d->p_cre->size(); return true; } @@ -139,11 +146,12 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball) { if(!d->Started) return false; // SHM fast path + Process * p = d->owner; if(d->creature_module) { SHMCREATURESHDR->index = index; const uint32_t cmd = Creatures2010::CREATURE_AT_INDEX + (d->creature_module << 16); - g_pProcess->SetAndWait(cmd); + p->SetAndWait(cmd); memcpy(&furball,SHMDATA(t_creature),sizeof(t_creature)); return true; } @@ -151,7 +159,7 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball) // non-SHM slow path // read pointer from vector at position - uint32_t temp = * (uint32_t *) d->p_cre->at (index); + uint32_t temp = d->p_cre->at (index); furball.origin = temp; Creatures2010::creature_offsets &offs = d->creatures; @@ -161,38 +169,39 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball) d->d->readName(furball.name,temp + offs.name_offset); // basic stuff - g_pProcess->readDWord (temp + offs.happiness_offset, furball.happiness); - g_pProcess->readDWord (temp + offs.id_offset, furball.id); - g_pProcess->read (temp + offs.pos_offset, 3 * sizeof (uint16_t), (uint8_t *) & (furball.x)); // xyz really - g_pProcess->readDWord (temp + offs.race_offset, furball.race); - g_pProcess->readByte (temp + offs.sex_offset, furball.sex); - g_pProcess->readDWord (temp + offs.flags1_offset, furball.flags1.whole); - g_pProcess->readDWord (temp + offs.flags2_offset, furball.flags2.whole); + p->readDWord (temp + offs.happiness_offset, furball.happiness); + p->readDWord (temp + offs.id_offset, furball.id); + p->read (temp + offs.pos_offset, 3 * sizeof (uint16_t), (uint8_t *) & (furball.x)); // xyz really + p->readDWord (temp + offs.race_offset, furball.race); + furball.civ = p->readDWord (temp + offs.civ_offset); + p->readByte (temp + offs.sex_offset, furball.sex); + p->readDWord (temp + offs.flags1_offset, furball.flags1.whole); + p->readDWord (temp + offs.flags2_offset, furball.flags2.whole); // physical attributes - g_pProcess->read(temp + offs.physical_offset, sizeof(t_attrib) * 6, (uint8_t *)&furball.strength); + p->read(temp + offs.physical_offset, sizeof(t_attrib) * 6, (uint8_t *)&furball.strength); // mood stuff - furball.mood = (int16_t) g_pProcess->readWord (temp + offs.mood_offset); + furball.mood = (int16_t) p->readWord (temp + offs.mood_offset); d->d->readName(furball.artifact_name, temp + offs.artifact_name_offset); // custom profession - fill_char_buf (furball.custom_profession, g_pProcess->readSTLString (temp + offs.custom_profession_offset)); + fill_char_buf (furball.custom_profession, p->readSTLString (temp + offs.custom_profession_offset)); // labors - g_pProcess->read (temp + offs.labors_offset, NUM_CREATURE_LABORS, furball.labors); + p->read (temp + offs.labors_offset, NUM_CREATURE_LABORS, furball.labors); // profession - furball.profession = g_pProcess->readByte (temp + offs.profession_offset); + furball.profession = p->readByte (temp + offs.profession_offset); // current job HACK: the job object isn't cleanly represented here /* - uint32_t jobIdAddr = g_pProcess->readDWord (temp + offs.creature_current_job_offset); + uint32_t jobIdAddr = p->readDWord (temp + offs.creature_current_job_offset); if (jobIdAddr) { furball.current_job.active = true; - furball.current_job.jobId = g_pProcess->readByte (jobIdAddr + offs.creature_current_job_id_offset); + furball.current_job.jobId = p->readByte (jobIdAddr + offs.creature_current_job_id_offset); } else { @@ -201,39 +210,43 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball) */ /* - g_pProcess->readDWord(temp + offs.creature_pregnancy_offset, furball.pregnancy_timer); + p->readDWord(temp + offs.creature_pregnancy_offset, furball.pregnancy_timer); */ /* // enum soul pointer vector - DfVector souls(g_pProcess,temp + offs.creature_soul_vector_offset,4); + DfVector souls(p,temp + offs.creature_soul_vector_offset); */ - uint32_t soul = g_pProcess->readDWord(temp + offs.default_soul_offset); - // get first soul's skills - DfVector skills(g_pProcess, soul + offs.soul_skills_vector_offset, 4 ); - furball.defaultSoul.numSkills = skills.getSize(); - for (uint32_t i = 0; i < furball.defaultSoul.numSkills;i++) + uint32_t soul = p->readDWord(temp + offs.default_soul_offset); + furball.has_default_soul = false; + if(soul) { - uint32_t temp2 = * (uint32_t *) skills[i]; - // a byte: this gives us 256 skills maximum. - furball.defaultSoul.skills[i].id = g_pProcess->readByte (temp2); - furball.defaultSoul.skills[i].rating = g_pProcess->readByte (temp2 + 4); - furball.defaultSoul.skills[i].experience = g_pProcess->readWord (temp2 + 8); + furball.has_default_soul = true; + // get first soul's skills + DfVector skills(p, soul + offs.soul_skills_vector_offset); + furball.defaultSoul.numSkills = skills.size(); + for (uint32_t i = 0; i < furball.defaultSoul.numSkills;i++) + { + uint32_t temp2 = skills[i]; + // a byte: this gives us 256 skills maximum. + furball.defaultSoul.skills[i].id = p->readByte (temp2); + furball.defaultSoul.skills[i].rating = p->readByte (temp2 + 4); + furball.defaultSoul.skills[i].experience = p->readWord (temp2 + 8); + } + // mental attributes are part of the soul + p->read(soul + offs.soul_mental_offset, sizeof(t_attrib) * 13, (uint8_t *)&furball.defaultSoul.analytical_ability); + + // traits as well + p->read(soul + offs.soul_traits_offset, sizeof (uint16_t) * NUM_CREATURE_TRAITS, (uint8_t *) &furball.defaultSoul.traits); } - // mental attributes are part of the soul - g_pProcess->read(soul + offs.soul_mental_offset, sizeof(t_attrib) * 13, (uint8_t *)&furball.defaultSoul.analytical_ability); - - // traits as well - g_pProcess->read(soul + offs.soul_traits_offset, sizeof (uint16_t) * NUM_CREATURE_TRAITS, (uint8_t *) &furball.defaultSoul.traits); - //likes /* - DfVector likes(d->p, temp + offs.creature_likes_offset, 4); + DfVector likes(d->p, temp + offs.creature_likes_offset); furball.numLikes = likes.getSize(); for(uint32_t i = 0;iread(temp2,sizeof(t_like),(uint8_t *) &furball.likes[i]); + p->read(temp2,sizeof(t_like),(uint8_t *) &furball.likes[i]); }*/ return true; @@ -244,7 +257,11 @@ int32_t Creatures::ReadCreatureInBox (int32_t index, t_creature & furball, 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->Started) return -1; + if (!d->Started) + return -1; + + Process *p = d->owner; + if(d->creature_module) { // supply the module with offsets so it can work with them @@ -256,7 +273,7 @@ int32_t Creatures::ReadCreatureInBox (int32_t index, t_creature & furball, SHMCREATURESHDR->y2 = y2; SHMCREATURESHDR->z2 = z2; const uint32_t cmd = Creatures2010::CREATURE_FIND_IN_BOX + (d->creature_module << 16); - g_pProcess->SetAndWait(cmd); + p->SetAndWait(cmd); if(SHMCREATURESHDR->index != -1) memcpy(&furball,SHMDATA(void),sizeof(t_creature)); return SHMCREATURESHDR->index; @@ -264,12 +281,12 @@ int32_t Creatures::ReadCreatureInBox (int32_t index, t_creature & furball, else { uint16_t coords[3]; - uint32_t size = d->p_cre->getSize(); + uint32_t size = d->p_cre->size(); while (uint32_t(index) < size) { // read pointer from vector at position - uint32_t temp = * (uint32_t *) d->p_cre->at (index); - g_pProcess->read (temp + d->creatures.pos_offset, 3 * sizeof (uint16_t), (uint8_t *) &coords); + uint32_t temp = d->p_cre->at(index); + p->read (temp + d->creatures.pos_offset, 3 * sizeof (uint16_t), (uint8_t *) &coords); if (coords[0] >= x1 && coords[0] < x2) { if (coords[1] >= y1 && coords[1] < y2) @@ -292,16 +309,36 @@ int32_t Creatures::ReadCreatureInBox (int32_t index, t_creature & furball, bool Creatures::WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]) { if(!d->Started) return false; - uint32_t temp = * (uint32_t *) d->p_cre->at (index); - g_pProcess->write(temp + d->creatures.labors_offset, NUM_CREATURE_LABORS, labors); + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + + p->write(temp + d->creatures.labors_offset, NUM_CREATURE_LABORS, labors); + uint32_t pickup_equip; + p->readDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip); + pickup_equip |= 1u; + p->writeDWord(temp + d->creatures.pickup_equipment_bit, pickup_equip); return true; } +uint32_t Creatures::GetDwarfRaceIndex() +{ + if(!d->Inited) return 0; + Process * p = d->owner; + return p->readDWord(d->dwarf_race_index_addr); +} + +int32_t Creatures::GetDwarfCivId() +{ + if(!d->Inited) return -1; + Process * p = d->owner; + return p->readDWord(d->dwarf_civ_id_addr); +} /* -bool API::getCurrentCursorCreature(uint32_t & creature_index) +bool Creatures::getCurrentCursorCreature(uint32_t & creature_index) { if(!d->cursorWindowInited) return false; - creature_index = g_pProcess->readDWord(d->current_cursor_creature_offset); + Process * p = d->owner; + creature_index = p->readDWord(d->current_cursor_creature_offset); return true; } -*/ \ No newline at end of file +*/ diff --git a/dfhack/modules/Gui.cpp b/dfhack/modules/Gui.cpp index eb1d774eb..c113c05bc 100644 --- a/dfhack/modules/Gui.cpp +++ b/dfhack/modules/Gui.cpp @@ -40,6 +40,7 @@ struct Gui::Private uint32_t current_cursor_creature_offset; uint32_t current_menu_state_offset; APIPrivate *d; + Process * owner; }; Gui::Gui(APIPrivate * _d) @@ -47,6 +48,7 @@ Gui::Gui(APIPrivate * _d) d = new Private; d->d = _d; + d->owner = _d->p; d->Inited = d->Started = true; memory_info * mem = d->d->offset_descriptor; @@ -76,29 +78,30 @@ bool Gui::ReadPauseState() // replace with an exception if(!d->Inited) return false; - uint32_t pauseState = g_pProcess->readDWord (d->pause_state_offset); + uint32_t pauseState = d->owner->readDWord (d->pause_state_offset); return pauseState & 1; } uint32_t Gui::ReadMenuState() { if(d->Inited) - return(g_pProcess->readDWord(d->current_menu_state_offset)); + return(d->owner->readDWord(d->current_menu_state_offset)); return false; } bool Gui::ReadViewScreen (t_viewscreen &screen) { if (!d->Inited) return false; + Process * p = d->owner; - uint32_t last = g_pProcess->readDWord (d->view_screen_offset); - uint32_t screenAddr = g_pProcess->readDWord (last); - uint32_t nextScreenPtr = g_pProcess->readDWord (last + 4); + uint32_t last = p->readDWord (d->view_screen_offset); + uint32_t screenAddr = p->readDWord (last); + uint32_t nextScreenPtr = p->readDWord (last + 4); while (nextScreenPtr != 0) { last = nextScreenPtr; - screenAddr = g_pProcess->readDWord (nextScreenPtr); - nextScreenPtr = g_pProcess->readDWord (nextScreenPtr + 4); + screenAddr = p->readDWord (nextScreenPtr); + nextScreenPtr = p->readDWord (nextScreenPtr + 4); } return d->d->offset_descriptor->resolveObjectToClassID (last, screen.type); } diff --git a/dfhack/modules/Maps.cpp b/dfhack/modules/Maps.cpp index 7eb499d9a..b562ed655 100644 --- a/dfhack/modules/Maps.cpp +++ b/dfhack/modules/Maps.cpp @@ -51,6 +51,7 @@ struct Maps::Private Server::Maps::maps_offsets offsets; APIPrivate *d; + Process * owner; bool Inited; bool Started; vector v_geology[eBiomeCount]; @@ -60,9 +61,10 @@ Maps::Maps(APIPrivate* _d) { d = new Private; d->d = _d; + Process *p = d->owner = _d->p; d->Inited = d->Started = false; - DFHack::memory_info * mem = d->d->offset_descriptor; + DFHack::memory_info * mem = p->getDescriptor(); Server::Maps::maps_offsets &off = d->offsets; // get the offsets once here @@ -70,12 +72,14 @@ Maps::Maps(APIPrivate* _d) off.x_count_offset = mem->getAddress ("x_count_block"); off.y_count_offset = mem->getAddress ("y_count_block"); off.z_count_offset = mem->getAddress ("z_count_block"); - off.tile_type_offset = mem->getOffset ("type"); - off.designation_offset = mem->getOffset ("designation"); - off.occupancy_offset = mem->getOffset("occupancy"); - off.biome_stuffs = mem->getOffset ("biome_stuffs"); - off.veinvector = mem->getOffset ("v_vein"); - + off.tile_type_offset = mem->getOffset ("map_data_type"); + off.designation_offset = mem->getOffset ("map_data_designation"); + off.occupancy_offset = mem->getOffset("map_data_occupancy"); + off.biome_stuffs = mem->getOffset ("map_data_biome_stuffs"); + off.veinvector = mem->getOffset ("map_data_vein_vector"); + off.temperature1_offset = mem->getOffset ("map_data_temperature1_offset"); + off.temperature2_offset = mem->getOffset ("map_data_temperature2_offset"); + // these can fail and will be found when looking at the actual veins later // basically a cache off.vein_ice_vptr = 0; @@ -85,14 +89,14 @@ Maps::Maps(APIPrivate* _d) // upload offsets to SHM server if possible d->maps_module = 0; - if(g_pProcess->getModuleIndex("Maps2010",1,d->maps_module)) + if(p->getModuleIndex("Maps2010",1,d->maps_module)) { // supply the module with offsets so it can work with them Server::Maps::maps_offsets *off2 = SHMDATA(Server::Maps::maps_offsets); memcpy(off2, &(d->offsets), sizeof(Server::Maps::maps_offsets)); full_barrier const uint32_t cmd = Server::Maps::MAP_INIT + (d->maps_module << 16); - g_pProcess->SetAndWait(cmd); + p->SetAndWait(cmd); } d->Inited = true; } @@ -112,9 +116,10 @@ bool Maps::Start() return false; if(d->Started) Finish(); + Process *p = d->owner; Server::Maps::maps_offsets &off = d->offsets; // get the map pointer - uint32_t x_array_loc = g_pProcess->readDWord (off.map_offset); + uint32_t x_array_loc = p->readDWord (off.map_offset); if (!x_array_loc) { return false; @@ -122,9 +127,9 @@ bool Maps::Start() // get the size uint32_t mx, my, mz; - mx = d->x_block_count = g_pProcess->readDWord (off.x_count_offset); - my = d->y_block_count = g_pProcess->readDWord (off.y_count_offset); - mz = d->z_block_count = g_pProcess->readDWord (off.z_count_offset); + mx = d->x_block_count = p->readDWord (off.x_count_offset); + my = d->y_block_count = p->readDWord (off.y_count_offset); + mz = d->z_block_count = p->readDWord (off.z_count_offset); // test for wrong map dimensions if (mx == 0 || mx > 48 || my == 0 || my > 48 || mz == 0) @@ -137,23 +142,21 @@ bool Maps::Start() d->block = new uint32_t[mx*my*mz]; uint32_t *temp_x = new uint32_t[mx]; uint32_t *temp_y = new uint32_t[my]; - uint32_t *temp_z = new uint32_t[mz]; - g_pProcess->read (x_array_loc, mx * sizeof (uint32_t), (uint8_t *) temp_x); + p->read (x_array_loc, mx * sizeof (uint32_t), (uint8_t *) temp_x); for (uint32_t x = 0; x < mx; x++) { - g_pProcess->read (temp_x[x], my * sizeof (uint32_t), (uint8_t *) temp_y); + p->read (temp_x[x], my * sizeof (uint32_t), (uint8_t *) temp_y); // y -> map column for (uint32_t y = 0; y < my; y++) { - g_pProcess->read (temp_y[y], + p->read (temp_y[y], mz * sizeof (uint32_t), (uint8_t *) (d->block + x*my*mz + y*mz)); } } delete [] temp_x; delete [] temp_y; - delete [] temp_z; return true; } @@ -195,13 +198,14 @@ uint32_t Maps::getBlockPtr (uint32_t x, uint32_t y, uint32_t z) bool Maps::ReadBlock40d(uint32_t x, uint32_t y, uint32_t z, mapblock40d * buffer) { + Process *p = d->owner; if(d->d->shm_start && d->maps_module) // ACCELERATE! { SHMMAPSHDR->x = x; SHMMAPSHDR->y = y; SHMMAPSHDR->z = z; volatile uint32_t cmd = Server::Maps::MAP_READ_BLOCK_BY_COORDS + (d->maps_module << 16); - if(!g_pProcess->SetAndWait(cmd)) + if(!p->SetAndWait(cmd)) return false; memcpy(buffer,SHMDATA(mapblock40d),sizeof(mapblock40d)); return true; @@ -211,13 +215,13 @@ bool Maps::ReadBlock40d(uint32_t x, uint32_t y, uint32_t z, mapblock40d * buffer uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { - g_pProcess->read (addr + d->offsets.tile_type_offset, sizeof (buffer->tiletypes), (uint8_t *) buffer->tiletypes); - g_pProcess->read (addr + d->offsets.designation_offset, sizeof (buffer->designation), (uint8_t *) buffer->designation); - g_pProcess->read (addr + d->offsets.occupancy_offset, sizeof (buffer->occupancy), (uint8_t *) buffer->occupancy); - g_pProcess->read (addr + d->offsets.biome_stuffs, sizeof (biome_indices40d), (uint8_t *) buffer->biome_indices); + p->read (addr + d->offsets.tile_type_offset, sizeof (buffer->tiletypes), (uint8_t *) buffer->tiletypes); + p->read (addr + d->offsets.designation_offset, sizeof (buffer->designation), (uint8_t *) buffer->designation); + p->read (addr + d->offsets.occupancy_offset, sizeof (buffer->occupancy), (uint8_t *) buffer->occupancy); + p->read (addr + d->offsets.biome_stuffs, sizeof (biome_indices40d), (uint8_t *) buffer->biome_indices); buffer->origin = addr; - uint32_t addr_of_struct = g_pProcess->readDWord(addr); - buffer->blockflags.whole = g_pProcess->readDWord(addr_of_struct); + uint32_t addr_of_struct = p->readDWord(addr); + buffer->blockflags.whole = p->readDWord(addr_of_struct); return true; } return false; @@ -233,7 +237,7 @@ bool Maps::ReadTileTypes (uint32_t x, uint32_t y, uint32_t z, tiletypes40d *buff uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { - g_pProcess->read (addr + d->offsets.tile_type_offset, sizeof (tiletypes40d), (uint8_t *) buffer); + d->owner->read (addr + d->offsets.tile_type_offset, sizeof (tiletypes40d), (uint8_t *) buffer); return true; } return false; @@ -244,7 +248,7 @@ bool Maps::WriteTileTypes (uint32_t x, uint32_t y, uint32_t z, tiletypes40d *buf uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { - g_pProcess->write (addr + d->offsets.tile_type_offset, sizeof (tiletypes40d), (uint8_t *) buffer); + d->owner->write (addr + d->offsets.tile_type_offset, sizeof (tiletypes40d), (uint8_t *) buffer); return true; } return false; @@ -259,8 +263,9 @@ bool Maps::ReadDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool &dirtybit) uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if(addr) { - uint32_t addr_of_struct = g_pProcess->readDWord(addr); - dirtybit = g_pProcess->readDWord(addr_of_struct) & 1; + Process * p = d->owner; + uint32_t addr_of_struct = p->readDWord(addr); + dirtybit = p->readDWord(addr_of_struct) & 1; return true; } return false; @@ -271,11 +276,12 @@ bool Maps::WriteDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool dirtybit) uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { - uint32_t addr_of_struct = g_pProcess->readDWord(addr); - uint32_t dirtydword = g_pProcess->readDWord(addr_of_struct); + Process * p = d->owner; + uint32_t addr_of_struct = p->readDWord(addr); + uint32_t dirtydword = p->readDWord(addr_of_struct); dirtydword &= 0xFFFFFFFE; dirtydword |= (uint32_t) dirtybit; - g_pProcess->writeDWord (addr_of_struct, dirtydword); + p->writeDWord (addr_of_struct, dirtydword); return true; } return false; @@ -287,8 +293,9 @@ bool Maps::ReadBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags &bloc uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if(addr) { - uint32_t addr_of_struct = g_pProcess->readDWord(addr); - blockflags.whole = g_pProcess->readDWord(addr_of_struct); + Process * p = d->owner; + uint32_t addr_of_struct = p->readDWord(addr); + blockflags.whole = p->readDWord(addr_of_struct); return true; } return false; @@ -298,8 +305,9 @@ bool Maps::WriteBlockFlags(uint32_t x, uint32_t y, uint32_t z, t_blockflags bloc uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { - uint32_t addr_of_struct = g_pProcess->readDWord(addr); - g_pProcess->writeDWord (addr_of_struct, blockflags.whole); + Process * p = d->owner; + uint32_t addr_of_struct = p->readDWord(addr); + p->writeDWord (addr_of_struct, blockflags.whole); return true; } return false; @@ -314,7 +322,7 @@ bool Maps::ReadDesignations (uint32_t x, uint32_t y, uint32_t z, designations40d uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { - g_pProcess->read (addr + d->offsets.designation_offset, sizeof (designations40d), (uint8_t *) buffer); + d->owner->read (addr + d->offsets.designation_offset, sizeof (designations40d), (uint8_t *) buffer); return true; } return false; @@ -325,7 +333,7 @@ bool Maps::WriteDesignations (uint32_t x, uint32_t y, uint32_t z, designations40 uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { - g_pProcess->write (addr + d->offsets.designation_offset, sizeof (designations40d), (uint8_t *) buffer); + d->owner->write (addr + d->offsets.designation_offset, sizeof (designations40d), (uint8_t *) buffer); return true; } return false; @@ -340,7 +348,7 @@ bool Maps::ReadOccupancy (uint32_t x, uint32_t y, uint32_t z, occupancies40d *bu uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { - g_pProcess->read (addr + d->offsets.occupancy_offset, sizeof (occupancies40d), (uint8_t *) buffer); + d->owner->read (addr + d->offsets.occupancy_offset, sizeof (occupancies40d), (uint8_t *) buffer); return true; } return false; @@ -351,7 +359,37 @@ bool Maps::WriteOccupancy (uint32_t x, uint32_t y, uint32_t z, occupancies40d *b uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { - g_pProcess->write (addr + d->offsets.occupancy_offset, sizeof (tiletypes40d), (uint8_t *) buffer); + d->owner->write (addr + d->offsets.occupancy_offset, sizeof (tiletypes40d), (uint8_t *) buffer); + return true; + } + return false; +} + +/* + * Temperatures + */ +bool Maps::ReadTemperatures(uint32_t x, uint32_t y, uint32_t z, t_temperatures *temp1, t_temperatures *temp2) +{ + uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; + if (addr) + { + if(temp1) + d->owner->read (addr + d->offsets.temperature1_offset, sizeof (t_temperatures), (uint8_t *) temp1); + if(temp2) + d->owner->read (addr + d->offsets.temperature2_offset, sizeof (t_temperatures), (uint8_t *) temp2); + return true; + } + return false; +} +bool Maps::WriteTemperatures (uint32_t x, uint32_t y, uint32_t z, t_temperatures *temp1, t_temperatures *temp2) +{ + uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; + if (addr) + { + if(temp1) + d->owner->write (addr + d->offsets.temperature1_offset, sizeof (t_temperatures), (uint8_t *) temp1); + if(temp2) + d->owner->write (addr + d->offsets.temperature2_offset, sizeof (t_temperatures), (uint8_t *) temp2); return true; } return false; @@ -365,7 +403,7 @@ bool Maps::ReadRegionOffsets (uint32_t x, uint32_t y, uint32_t z, biome_indices4 uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if (addr) { - g_pProcess->read (addr + d->offsets.biome_stuffs, sizeof (biome_indices40d), (uint8_t *) buffer); + d->owner->read (addr + d->offsets.biome_stuffs, sizeof (biome_indices40d), (uint8_t *) buffer); return true; } return false; @@ -379,6 +417,7 @@ bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector * veins, t_vein v; t_frozenliquidvein fv; t_spattervein sv; + Process* p = d->owner; uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; if(veins) veins->clear(); @@ -390,19 +429,19 @@ bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector * veins, { // veins are stored as a vector of pointers to veins /*pointer is 4 bytes! we work with a 32bit program here, no matter what architecture we compile khazad for*/ - DfVector p_veins (d->d->p, addr + off.veinvector, 4); - uint32_t size = p_veins.getSize(); + DfVector p_veins (p, addr + off.veinvector); + uint32_t size = p_veins.size(); // read all veins for (uint32_t i = 0; i < size;i++) { // read the vein pointer from the vector - uint32_t temp = * (uint32_t *) p_veins[i]; - uint32_t type = g_pProcess->readDWord(temp); + uint32_t temp = p_veins[i]; + uint32_t type = p->readDWord(temp); try_again: if(veins && type == off.vein_mineral_vptr) { // read the vein data (dereference pointer) - g_pProcess->read (temp, sizeof(t_vein), (uint8_t *) &v); + p->read (temp, sizeof(t_vein), (uint8_t *) &v); v.address_of = temp; // store it in the vector veins->push_back (v); @@ -410,7 +449,7 @@ try_again: else if(ices && type == off.vein_ice_vptr) { // read the ice vein data (dereference pointer) - g_pProcess->read (temp, sizeof(t_frozenliquidvein), (uint8_t *) &fv); + p->read (temp, sizeof(t_frozenliquidvein), (uint8_t *) &fv); fv.address_of = temp; // store it in the vector ices->push_back (fv); @@ -418,14 +457,14 @@ try_again: else if(splatter && type == off.vein_spatter_vptr) { // read the splatter vein data (dereference pointer) - g_pProcess->read (temp, sizeof(t_spattervein), (uint8_t *) &sv); + p->read (temp, sizeof(t_spattervein), (uint8_t *) &sv); sv.address_of = temp; // store it in the vector splatter->push_back (sv); } else { - string cname = g_pProcess->readClassName(type); + string cname = p->readClassName(type); if(ices && cname == "block_square_event_frozen_liquidst") { off.vein_ice_vptr = type; @@ -516,6 +555,7 @@ __int16 __userpurge GetGeologicalRegion(__int16 block_X, int X, __i bool Maps::ReadGeology (vector < vector >& assign) { memory_info * minfo = d->d->offset_descriptor; + Process *p = d->owner; // get needed addresses and offsets. Now this is what I call crazy. int region_x_offset = minfo->getAddress ("region_x"); int region_y_offset = minfo->getAddress ("region_y"); @@ -534,19 +574,19 @@ bool Maps::ReadGeology (vector < vector >& assign) uint16_t worldSizeX, worldSizeY; // read position of the region inside DF world - g_pProcess->readDWord (region_x_offset, regionX); - g_pProcess->readDWord (region_y_offset, regionY); - g_pProcess->readDWord (region_z_offset, regionZ); + p->readDWord (region_x_offset, regionX); + p->readDWord (region_y_offset, regionY); + p->readDWord (region_z_offset, regionZ); // get world size - g_pProcess->readWord (world_size_x, worldSizeX); - g_pProcess->readWord (world_size_y, worldSizeY); + p->readWord (world_size_x, worldSizeX); + p->readWord (world_size_y, worldSizeY); // get pointer to first part of 2d array of regions - uint32_t regions = g_pProcess->readDWord (world_regions); + uint32_t regions = p->readDWord (world_regions); // read the geoblock vector - DfVector geoblocks (d->d->p, world_geoblocks_vector, 4); + DfVector geoblocks (d->d->p, world_geoblocks_vector); // iterate over 8 surrounding regions + local region for (int i = eNorthWest; i < eBiomeCount; i++) @@ -563,32 +603,32 @@ bool Maps::ReadGeology (vector < vector >& assign) /// regions are of region_size size // get pointer to column of regions uint32_t geoX; - g_pProcess->readDWord (regions + bioRX*4, geoX); + p->readDWord (regions + bioRX*4, geoX); // get index into geoblock vector uint16_t geoindex; - g_pProcess->readWord (geoX + bioRY*region_size + region_geo_index_offset, geoindex); + p->readWord (geoX + bioRY*region_size + region_geo_index_offset, geoindex); /// geology blocks are assigned to regions from a vector // get the geoblock from the geoblock vector using the geoindex // read the matgloss pointer from the vector into temp - uint32_t geoblock_off = * (uint32_t *) geoblocks[geoindex]; + uint32_t geoblock_off = geoblocks[geoindex]; /// geology blocks have a vector of layer descriptors // get the vector with pointer to layers - DfVector geolayers (d->d->p, geoblock_off + geolayer_geoblock_offset , 4); // let's hope + DfVector geolayers (p, geoblock_off + geolayer_geoblock_offset); // let's hope // make sure we don't load crap - assert (geolayers.getSize() > 0 && geolayers.getSize() <= 16); + assert (geolayers.size() > 0 && geolayers.size() <= 16); /// layer descriptor has a field that determines the type of stone/soil - d->v_geology[i].reserve (geolayers.getSize()); + d->v_geology[i].reserve (geolayers.size()); // finally, read the layer matgloss - for (uint32_t j = 0;j < geolayers.getSize();j++) + for (uint32_t j = 0;j < geolayers.size();j++) { // read pointer to a layer - uint32_t geol_offset = * (uint32_t *) geolayers[j]; + uint32_t geol_offset = geolayers[j]; // read word at pointer + 2, store in our geology vectors - d->v_geology[i].push_back (g_pProcess->readWord (geol_offset + type_inside_geolayer)); + d->v_geology[i].push_back (p->readWord (geol_offset + type_inside_geolayer)); } } assign.clear(); diff --git a/dfhack/modules/Materials.cpp b/dfhack/modules/Materials.cpp index 265f5074c..e0e8da8a7 100644 --- a/dfhack/modules/Materials.cpp +++ b/dfhack/modules/Materials.cpp @@ -25,17 +25,33 @@ distribution. #include "DFCommonInternal.h" #include "../private/APIPrivate.h" #include "modules/Materials.h" -#include "DFVector.h" #include "DFMemInfo.h" #include "DFProcess.h" +#include "DFVector.h" using namespace DFHack; +class Materials::Private +{ + public: + APIPrivate *d; + Process * owner; + /* + bool Inited; + bool Started; + */ +}; + Materials::Materials(APIPrivate * d_) { - d = d_; + d = new Private; + d->d = d_; + d->owner = d_->p; +} +Materials::~Materials() +{ + delete d; } -Materials::~Materials(){} /* { LABEL_53: @@ -131,12 +147,13 @@ LABEL_53: /* bool API::ReadInorganicMaterials (vector & inorganic) { - memory_info * minfo = d->offset_descriptor; + Process *p = d->owner; + memory_info * minfo = p->getDescriptor(); int matgloss_address = minfo->getAddress ("mat_inorganics"); int matgloss_colors = minfo->getOffset ("material_color"); int matgloss_stone_name_offset = minfo->getOffset("matgloss_stone_name"); - DfVector p_matgloss (d->p, matgloss_address, 4); + DfVector p_matgloss (p, matgloss_address); uint32_t size = p_matgloss.getSize(); inorganic.resize (0); @@ -144,17 +161,17 @@ bool API::ReadInorganicMaterials (vector & inorganic) for (uint32_t i = 0; i < size;i++) { // read the matgloss pointer from the vector into temp - uint32_t temp = * (uint32_t *) p_matgloss[i]; + uint32_t temp = p_matgloss[i]; // read the string pointed at by t_matgloss mat; //cout << temp << endl; //fill_char_buf(mat.id, d->p->readSTLString(temp)); // reads a C string given an address - d->p->readSTLString (temp, mat.id, 128); + p->readSTLString (temp, mat.id, 128); - d->p->readSTLString (temp+matgloss_stone_name_offset, mat.name, 128); - mat.fore = (uint8_t) g_pProcess->readWord (temp + matgloss_colors); - mat.back = (uint8_t) g_pProcess->readWord (temp + matgloss_colors + 2); - mat.bright = (uint8_t) g_pProcess->readWord (temp + matgloss_colors + 4); + p->readSTLString (temp+matgloss_stone_name_offset, mat.name, 128); + mat.fore = (uint8_t) p->readWord (temp + matgloss_colors); + mat.back = (uint8_t) p->readWord (temp + matgloss_colors + 2); + mat.bright = (uint8_t) p->readWord (temp + matgloss_colors + 4); inorganic.push_back (mat); } @@ -167,14 +184,14 @@ bool API::ReadInorganicMaterials (vector & inorganic) // good for now inline bool ReadNamesOnly(Process* p, uint32_t address, vector & names) { - DfVector p_matgloss (p, address, 4); - uint32_t size = p_matgloss.getSize(); + DfVector p_matgloss (p, address); + uint32_t size = p_matgloss.size(); names.clear(); names.reserve (size); for (uint32_t i = 0; i < size;i++) { t_matgloss mat; - p->readSTLString (*(uint32_t *) p_matgloss[i], mat.id, 128); + p->readSTLString (p_matgloss[i], mat.id, 128); names.push_back(mat); } return true; @@ -182,33 +199,85 @@ inline bool ReadNamesOnly(Process* p, uint32_t address, vector & nam bool Materials::ReadInorganicMaterials (vector & inorganic) { - return ReadNamesOnly(d->p, d->offset_descriptor->getAddress ("mat_inorganics"), inorganic ); + return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("mat_inorganics"), inorganic ); } bool Materials::ReadOrganicMaterials (vector & organic) { - return ReadNamesOnly(d->p, d->offset_descriptor->getAddress ("mat_organics_all"), organic ); + return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("mat_organics_all"), organic ); } bool Materials::ReadWoodMaterials (vector & trees) { - return ReadNamesOnly(d->p, d->offset_descriptor->getAddress ("mat_organics_trees"), trees ); + return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("mat_organics_trees"), trees ); } bool Materials::ReadPlantMaterials (vector & plants) { - return ReadNamesOnly(d->p, d->offset_descriptor->getAddress ("mat_organics_plants"), plants ); + return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("mat_organics_plants"), plants ); } -/* -Gives bad results combined with the creature race field! + bool Materials::ReadCreatureTypes (vector & creatures) { - return ReadNamesOnly(d->p, d->offset_descriptor->getAddress ("mat_creature_types"), creatures ); + return ReadNamesOnly(d->owner, d->owner->getDescriptor()->getAddress ("creature_type_vector"), creatures ); return true; } -*/ -bool Materials::ReadCreatureTypes (vector & creatures) + +bool Materials::ReadDescriptorColors (vector & color) { - return ReadNamesOnly(d->p, d->offset_descriptor->getAddress ("creature_type_vector"), creatures ); + Process * p = d->owner; + DfVector p_colors (p, p->getDescriptor()->getAddress ("descriptor_colors_vector")); + uint32_t size = p_colors.size(); + + color.clear(); + color.reserve(size); + for (uint32_t i = 0; i < size;i++) + { + t_descriptor_color col; + p->readSTLString (p_colors[i] + p->getDescriptor()->getOffset ("descriptor_rawname"), col.id, 128); + p->readSTLString (p_colors[i] + p->getDescriptor()->getOffset ("descriptor_name"), col.name, 128); + col.r = p->readFloat( p_colors[i] + p->getDescriptor()->getOffset ("descriptor_color_r") ); + col.v = p->readFloat( p_colors[i] + p->getDescriptor()->getOffset ("descriptor_color_v") ); + col.b = p->readFloat( p_colors[i] + p->getDescriptor()->getOffset ("descriptor_color_b") ); + color.push_back(col); + } +} + +bool Materials::ReadCreatureTypesEx (vector & creatures) +{ + Process *p = d->owner; + memory_info *mem = d->owner->getDescriptor(); + DfVector p_races (p, mem->getAddress ("creature_type_vector")); + uint32_t castes_vector_offset = mem->getOffset ("creature_type_caste_vector"); + uint32_t sizeof_string = mem->getHexValue ("sizeof_string"); + uint32_t size = p_races.size(); + uint32_t sizecas = 0; + uint32_t tile_offset = mem->getOffset ("creature_tile"); + uint32_t tile_color_offset = mem->getOffset ("creature_tile_color"); + creatures.clear(); + creatures.reserve (size); + for (uint32_t i = 0; i < size;i++) + { + t_creaturetype mat; + p->readSTLString (p_races[i], mat.rawname, sizeof(mat.rawname)); + DfVector p_castes(p, p_races[i] + castes_vector_offset); + sizecas = p_castes.size(); + for (uint32_t j = 0; j < sizecas;j++) + { + t_creaturecaste caste; + uint32_t caste_start = p_castes[j]; + p->readSTLString (caste_start, caste.rawname, sizeof(caste.rawname)); + p->readSTLString (caste_start + sizeof_string, caste.singular, sizeof(caste.singular)); + p->readSTLString (caste_start + 2 * sizeof_string, caste.plural, sizeof(caste.plural)); + p->readSTLString (caste_start + 3 * sizeof_string, caste.adjective, sizeof(caste.adjective)); + mat.castes.push_back(caste); + } + mat.tile_character = p->readByte( p_races[i] + tile_offset ); + mat.tilecolor.fore = p->readWord( p_races[i] + tile_color_offset ); + mat.tilecolor.back = p->readWord( p_races[i] + tile_color_offset + 2 ); + mat.tilecolor.bright = p->readWord( p_races[i] + tile_color_offset + 4 ); + creatures.push_back(mat); + } return true; } + diff --git a/dfhack/modules/Position.cpp b/dfhack/modules/Position.cpp index c4e56b37d..dbdde2282 100644 --- a/dfhack/modules/Position.cpp +++ b/dfhack/modules/Position.cpp @@ -46,6 +46,7 @@ struct Position::Private uint32_t hotkey_size; APIPrivate *d; + Process * owner; bool Inited; bool Started; bool StartedHotkeys; @@ -57,6 +58,7 @@ Position::Position(APIPrivate * d_) { d = new Private; d->d = d_; + d->owner = d_->p; d->Inited = true; d->StartedHotkeys = d->Started = false; memory_info * mem; @@ -88,11 +90,13 @@ bool Position::ReadHotkeys(t_hotkey hotkeys[]) { if (!d->StartedHotkeys) return false; uint32_t currHotkey = d->hotkey_start; + Process * p = d->owner; + for(uint32_t i = 0 ; i < NUM_HOTKEYS ;i++) { - g_pProcess->readSTLString(currHotkey,hotkeys[i].name,10); - hotkeys[i].mode = g_pProcess->readWord(currHotkey+d->hotkey_mode_offset); - g_pProcess->read (currHotkey + d->hotkey_xyz_offset, 3*sizeof (int32_t), (uint8_t *) &hotkeys[i].x); + p->readSTLString(currHotkey,hotkeys[i].name,10); + hotkeys[i].mode = p->readWord(currHotkey+d->hotkey_mode_offset); + p->read (currHotkey + d->hotkey_xyz_offset, 3*sizeof (int32_t), (uint8_t *) &hotkeys[i].x); currHotkey+=d->hotkey_size; } return true; @@ -101,9 +105,11 @@ bool Position::ReadHotkeys(t_hotkey hotkeys[]) bool Position::getViewCoords (int32_t &x, int32_t &y, int32_t &z) { if (!d->Inited) return false; - g_pProcess->readDWord (d->window_x_offset, (uint32_t &) x); - g_pProcess->readDWord (d->window_y_offset, (uint32_t &) y); - g_pProcess->readDWord (d->window_z_offset, (uint32_t &) z); + Process * p = d->owner; + + p->readDWord (d->window_x_offset, (uint32_t &) x); + p->readDWord (d->window_y_offset, (uint32_t &) y); + p->readDWord (d->window_z_offset, (uint32_t &) z); return true; } @@ -111,9 +117,11 @@ bool Position::getViewCoords (int32_t &x, int32_t &y, int32_t &z) bool Position::setViewCoords (const int32_t x, const int32_t y, const int32_t z) { if (!d->Inited) return false; - g_pProcess->writeDWord (d->window_x_offset, (uint32_t) x); - g_pProcess->writeDWord (d->window_y_offset, (uint32_t) y); - g_pProcess->writeDWord (d->window_z_offset, (uint32_t) z); + Process * p = d->owner; + + p->writeDWord (d->window_x_offset, (uint32_t) x); + p->writeDWord (d->window_y_offset, (uint32_t) y); + p->writeDWord (d->window_z_offset, (uint32_t) z); return true; } @@ -121,7 +129,7 @@ bool Position::getCursorCoords (int32_t &x, int32_t &y, int32_t &z) { if(!d->Inited) return false; int32_t coords[3]; - g_pProcess->read (d->cursor_xyz_offset, 3*sizeof (int32_t), (uint8_t *) coords); + d->owner->read (d->cursor_xyz_offset, 3*sizeof (int32_t), (uint8_t *) coords); x = coords[0]; y = coords[1]; z = coords[2]; @@ -134,7 +142,7 @@ bool Position::setCursorCoords (const int32_t x, const int32_t y, const int32_t { if (!d->Inited) return false; int32_t coords[3] = {x, y, z}; - g_pProcess->write (d->cursor_xyz_offset, 3*sizeof (int32_t), (uint8_t *) coords); + d->owner->write (d->cursor_xyz_offset, 3*sizeof (int32_t), (uint8_t *) coords); return true; } @@ -143,7 +151,7 @@ bool Position::getWindowSize (int32_t &width, int32_t &height) if(!d->Inited) return false; int32_t coords[2]; - g_pProcess->read (d->window_dims_offset, 2*sizeof (int32_t), (uint8_t *) coords); + d->owner->read (d->window_dims_offset, 2*sizeof (int32_t), (uint8_t *) coords); width = coords[0]; height = coords[1]; return true; diff --git a/dfhack/modules/Translation.cpp b/dfhack/modules/Translation.cpp index ddec1c72e..c82f82d32 100644 --- a/dfhack/modules/Translation.cpp +++ b/dfhack/modules/Translation.cpp @@ -73,15 +73,15 @@ bool Translation::Start() if(!d->Inited) return false; Process * p = d->d->p; - DfVector genericVec (p, d->genericAddress, 4); - DfVector transVec (p, d->transAddress, 4); + DfVector genericVec (p, d->genericAddress); + DfVector transVec (p, d->transAddress); DFDict & translations = d->dicts.translations; DFDict & foreign_languages = d->dicts.foreign_languages; translations.resize(10); - for (uint32_t i = 0;i < genericVec.getSize();i++) + for (uint32_t i = 0;i < genericVec.size();i++) { - uint32_t genericNamePtr = * (uint32_t *) genericVec.at (i); + uint32_t genericNamePtr = genericVec.at(i); for(int i=0; i<10;i++) { string word = p->readSTLString (genericNamePtr + i * d->sizeof_string); @@ -89,15 +89,15 @@ bool Translation::Start() } } - foreign_languages.resize(transVec.getSize()); - for (uint32_t i = 0; i < transVec.getSize();i++) + foreign_languages.resize(transVec.size()); + for (uint32_t i = 0; i < transVec.size();i++) { - uint32_t transPtr = * (uint32_t *) transVec.at (i); - //string transName = d->p->readSTLString (transPtr); - DfVector trans_names_vec (p, transPtr + d->word_table_offset, 4); - for (uint32_t j = 0;j < trans_names_vec.getSize();j++) + uint32_t transPtr = transVec.at(i); + + DfVector trans_names_vec (p, transPtr + d->word_table_offset); + for (uint32_t j = 0;j < trans_names_vec.size();j++) { - uint32_t transNamePtr = * (uint32_t *) trans_names_vec.at (j); + uint32_t transNamePtr = trans_names_vec.at(j); string name = p->readSTLString (transNamePtr); foreign_languages[i].push_back (name); } diff --git a/dfhack/modules/Vegetation.cpp b/dfhack/modules/Vegetation.cpp index 721f6af1e..70c1adeb0 100644 --- a/dfhack/modules/Vegetation.cpp +++ b/dfhack/modules/Vegetation.cpp @@ -38,9 +38,10 @@ struct Vegetation::Private uint32_t vegetation_vector; uint32_t tree_desc_offset; // translation - DfVector * p_veg; + DfVector * p_veg; APIPrivate *d; + Process * owner; bool Inited; bool Started; }; @@ -48,6 +49,7 @@ struct Vegetation::Private Vegetation::Vegetation(APIPrivate * d_) { d = new Private; + d->owner = d_->p; d->d = d_; d->Inited = d->Started = false; memory_info * mem = d->d->offset_descriptor; @@ -65,8 +67,8 @@ Vegetation::~Vegetation() bool Vegetation::Start(uint32_t & numplants) { - d->p_veg = new DfVector (g_pProcess, d->vegetation_vector, 4); - numplants = d->p_veg->getSize(); + d->p_veg = new DfVector (d->owner, d->vegetation_vector); + numplants = d->p_veg->size(); d->Started = true; return true; } @@ -77,9 +79,9 @@ bool Vegetation::Read (const uint32_t index, t_tree & shrubbery) if(!d->Started) return false; // read pointer from vector at position - uint32_t temp = * (uint32_t *) d->p_veg->at (index); + uint32_t temp = d->p_veg->at (index); // read from memory - g_pProcess->read (temp + d->tree_desc_offset, sizeof (t_tree), (uint8_t *) &shrubbery); + d->owner->read (temp + d->tree_desc_offset, sizeof (t_tree), (uint8_t *) &shrubbery); shrubbery.address = temp; return true; } diff --git a/dfhack/shm/mod-creature2010.h b/dfhack/shm/mod-creature2010.h index ae8a2ec4d..656cd6561 100644 --- a/dfhack/shm/mod-creature2010.h +++ b/dfhack/shm/mod-creature2010.h @@ -39,6 +39,7 @@ typedef struct uint32_t profession_offset; uint32_t custom_profession_offset; uint32_t race_offset; + int32_t civ_offset; uint32_t flags1_offset; uint32_t flags2_offset; uint32_t name_offset; @@ -49,6 +50,7 @@ typedef struct uint32_t artifact_name_offset; uint32_t physical_offset; uint32_t mood_offset; + uint32_t pickup_equipment_bit; uint32_t soul_vector_offset; uint32_t default_soul_offset; // soul offsets @@ -93,4 +95,4 @@ DFPP_module Init(void); } } -#endif \ No newline at end of file +#endif diff --git a/dfhack/shm/mod-creature40d.cpp b/dfhack/shm/mod-creature40d.cpp index 63c033066..35b17b57f 100644 --- a/dfhack/shm/mod-creature40d.cpp +++ b/dfhack/shm/mod-creature40d.cpp @@ -84,7 +84,6 @@ void ReadCreatureAtIndex(void *data) } raw_skill; // learned skills std::vector * skillv = (std::vector *) (temp + offsets.creature_skills_offset + offsets.vector_correct); - //DfVector skills (d->p->readVector (temp + offsets.creature_skills_offset, 4)); furball->numSkills = skillv->size(); for (uint32_t i = 0; i < furball->numSkills;i++) { diff --git a/dfhack/shm/mod-maps.h b/dfhack/shm/mod-maps.h index 8023be8bf..832c4e8c8 100644 --- a/dfhack/shm/mod-maps.h +++ b/dfhack/shm/mod-maps.h @@ -47,6 +47,8 @@ typedef struct uint32_t occupancy_offset;// = d->offset_descriptor->getOffset ("occupancy"); uint32_t biome_stuffs;// = d->offset_descriptor->getOffset ("biome_stuffs"); uint32_t veinvector;// = d->offset_descriptor->getOffset ("v_vein"); + uint32_t temperature1_offset; + uint32_t temperature2_offset; uint32_t vein_mineral_vptr; uint32_t vein_ice_vptr; uint32_t vein_spatter_vptr; diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a00ac1662..f388f6ab1 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -69,10 +69,10 @@ TARGET_LINK_LIBRARIES(dftreedump dfhack) ADD_EXECUTABLE(dfspatterdump spatterdump.cpp) TARGET_LINK_LIBRARIES(dfspatterdump dfhack) -# catsplosion - Makes every cat pregnant, and almost due... +# catsplosion - Accelerates pregnancy # Author: Zhentar -# ADD_EXECUTABLE(dfcatsplosion catsplosion.cpp) -# TARGET_LINK_LIBRARIES(dfcatsplosion dfhack) +ADD_EXECUTABLE(dfcatsplosion catsplosion.cpp) +TARGET_LINK_LIBRARIES(dfcatsplosion dfhack) IF(UNIX) SET(CURSES_NEED_WIDE "YES") diff --git a/examples/buildingsdump.cpp b/examples/buildingsdump.cpp index ba6d77cc4..304e4ac96 100644 --- a/examples/buildingsdump.cpp +++ b/examples/buildingsdump.cpp @@ -8,6 +8,7 @@ #include using namespace std; +#include #include #include #include @@ -44,7 +45,7 @@ int main (int argc,const char* argv[]) mode = 1; } - vector creaturestypes; + map custom_workshop_types; DFHack::API DF ("Memory.xml"); try @@ -59,6 +60,7 @@ int main (int argc,const char* argv[]) #endif return 1; } + DFHack::memory_info * mem = DF.getMemoryInfo(); DFHack::Buildings * Bld = DF.getBuildings(); DFHack::Position * Pos = DF.getPosition(); @@ -66,6 +68,7 @@ int main (int argc,const char* argv[]) uint32_t numBuildings; if(Bld->Start(numBuildings)) { + Bld->ReadCustomWorkshopTypes(custom_workshop_types); if(mode) { cout << numBuildings << endl; @@ -110,6 +113,11 @@ int main (int argc,const char* argv[]) mem->resolveClassIDToClassname(temp.type, typestr); printf("Address 0x%x, type %d (%s), %d/%d/%d\n",temp.origin, temp.type, typestr.c_str(), temp.x1,temp.y1,temp.z); printf("Material %d %d\n", temp.material.type, temp.material.index); + int32_t custom; + if((custom = Bld->GetCustomWorkshopType(temp)) != -1) + { + printf("Custom workshop type %s (%d)\n",custom_workshop_types[custom].c_str(),custom); + } hexdump(DF,temp.origin,120); } } diff --git a/examples/catsplosion.cpp b/examples/catsplosion.cpp index ba764d513..90fabf180 100644 --- a/examples/catsplosion.cpp +++ b/examples/catsplosion.cpp @@ -21,28 +21,34 @@ using namespace std; #include #include #include +#include +#include - -vector creaturestypes; -DFHack::memory_info *mem; -DFHack::Process *proc; -uint32_t creature_pregnancy_offset; - -bool femaleonly = 0; -bool showcreatures = 0; -int maxpreg = 1000; // random start value, since its not required and im not sure how to set it to infinity -list s_creatures; +using namespace DFHack; int main ( int argc, char** argv ) { + vector creaturestypes; + DFHack::memory_info *mem; + DFHack::Process *proc; + uint32_t creature_pregnancy_offset; + + //bool femaleonly = 0; + bool showcreatures = 0; + int maxpreg = 1000; // random start value, since its not required and im not sure how to set it to infinity + list s_creatures; + // parse input, handle this nice and neat before we get to the connecting argstream as(argc,argv); - as >>option('f',"female",femaleonly,"Impregnate females only") + as // >>option('f',"female",femaleonly,"Impregnate females only") >>option('s',"show",showcreatures,"Show creature list (read only)") >>parameter('m',"max",maxpreg,"The maximum limit of pregnancies ", false) >>values(back_inserter(s_creatures), "any number of creatures") >>help(); - + + // make the creature list unique + s_creatures.unique(); + if (!as.isOk()) { cout << as.errorLog(); @@ -58,8 +64,9 @@ int main ( int argc, char** argv ) } else if (s_creatures.size() == 0 && showcreatures != 1) { - cout << as.usage(); - return(1); + cout << as.usage() << endl << "---------------------------------------" << endl; + cout << "Creature list empty, assuming CATs" << endl; + s_creatures.push_back("CAT"); } DFHack::API DF("Memory.xml"); @@ -78,9 +85,11 @@ int main ( int argc, char** argv ) proc = DF.getProcess(); mem = DF.getMemoryInfo(); + DFHack::Materials *Mats = DF.getMaterials(); + DFHack::Creatures *Cre = DF.getCreatures(); creature_pregnancy_offset = mem->getOffset("creature_pregnancy"); - if(!DF.ReadCreatureMatgloss(creaturestypes)) + if(!Mats->ReadCreatureTypesEx(creaturestypes)) { cerr << "Can't get the creature types." << endl; #ifndef LINUX_BUILD @@ -90,7 +99,7 @@ int main ( int argc, char** argv ) } uint32_t numCreatures; - if(!DF.InitReadCreatures(numCreatures)) + if(!Cre->Start(numCreatures)) { cerr << "Can't get creatures" << endl; #ifndef LINUX_BUILD @@ -104,68 +113,62 @@ int main ( int argc, char** argv ) string sextype; // shows all the creatures and returns. - if (showcreatures == 1) + + int maxlength = 0; + map > male_counts; + map > female_counts; + + // classify + for(uint32_t i =0;i < numCreatures;i++) { - int maxlength = 0; - map male_counts; - map female_counts; - for(uint32_t i =0;i < numCreatures;i++) + DFHack::t_creature creature; + Cre->ReadCreature(i,creature); + DFHack::t_creaturetype & crt = creaturestypes[creature.race]; + string castename = crt.castes[creature.sex].rawname; + if(castename == "FEMALE") { - DFHack::t_creature creature; - DF.ReadCreature(i,creature); - if(creature.sex == 1){ - male_counts[creaturestypes[creature.type].id]++; - female_counts[creaturestypes[creature.type].id]+=0; //auto initialize the females as well - } - else{ - female_counts[creaturestypes[creature.type].id]++; - male_counts[creaturestypes[creature.type].id]+=0; - } + female_counts[creaturestypes[creature.race].rawname].push_back(creature); + male_counts[creaturestypes[creature.race].rawname].size(); } - cout << "Type\t\t\tMale #\tFemale #" << endl; - for(map::iterator it1 = male_counts.begin();it1!=male_counts.end();it1++) + else // male, other, etc. { - cout << it1->first << "\t\t" << it1->second << "\t" << female_counts[it1->first] << endl; + male_counts[creaturestypes[creature.race].rawname].push_back(creature); + female_counts[creaturestypes[creature.race].rawname].size(); //auto initialize the females as well } - return(1); } - - for(uint32_t i = 0; i < numCreatures && totalchanged != maxpreg; i++) + + // print (optional) + if (showcreatures == 1) { - DFHack::t_creature creature; - DF.ReadCreature(i,creature); - if (showcreatures == 1) + cout << "Type\t\tMale #\tFemale #" << endl; + for(map >::iterator it1 = male_counts.begin();it1!=male_counts.end();it1++) { - if (creature.sex == 0) { sextype = "Female"; } else { sextype = "Male";} - cout << string(creaturestypes[creature.type].id) << ":" << sextype << "" << endl; + cout << it1->first << "\t\t" << it1->second.size() << "\t" << female_counts[it1->first].size() << endl; } - else + } + + // process + for (list::iterator it = s_creatures.begin(); it != s_creatures.end(); ++it) + { + std::string clinput = *it; + std::transform(clinput.begin(), clinput.end(), clinput.begin(), ::toupper); + vector &females = female_counts[clinput]; + uint32_t sz_fem = females.size(); + totalcount += sz_fem; + for(uint32_t i = 0; i < sz_fem && totalchanged != maxpreg; i++) { - s_creatures.unique(); - for (list::iterator it = s_creatures.begin(); it != s_creatures.end(); ++it) + t_creature & female = females[i]; + uint32_t preg_timer = proc->readDWord(female.origin + creature_pregnancy_offset); + if(preg_timer != 0) { - std::string clinput = *it; - std::transform(clinput.begin(), clinput.end(), clinput.begin(), ::toupper); - if(string(creaturestypes[creature.type].id) == clinput) - { - if((femaleonly == 1 && creature.sex == 0) || (femaleonly != 1)) - { - proc->writeDWord(creature.origin + creature_pregnancy_offset, rand() % 100 + 1); - totalchanged+=1; - totalcount+=1; - } - else - { - totalcount+=1; - } - } + proc->writeDWord(female.origin + creature_pregnancy_offset, rand() % 100 + 1); + totalchanged++; } } } - cout << totalchanged << " animals impregnated out of a possible " << totalcount << "." << endl; - - DF.FinishReadCreatures(); + cout << totalchanged << " pregnancies accelerated. Total creatures checked: " << totalcount << "." << endl; + Cre->Finish(); DF.Detach(); #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; diff --git a/examples/construction_dump.cpp b/examples/construction_dump.cpp index 57552dcf1..1f81faeb1 100644 --- a/examples/construction_dump.cpp +++ b/examples/construction_dump.cpp @@ -10,11 +10,11 @@ #include using namespace std; +#include #include #include #include #include -#include #include #include #include diff --git a/examples/creaturedump.cpp b/examples/creaturedump.cpp index 5ef2d1a0c..795387769 100644 --- a/examples/creaturedump.cpp +++ b/examples/creaturedump.cpp @@ -6,6 +6,7 @@ #include using namespace std; +#include #include #include #include @@ -14,17 +15,8 @@ using namespace std; #include #include #include +#include "miscutils.h" -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; - } -} struct matGlosses { vector plantMat; @@ -41,7 +33,7 @@ enum likeType FOOD = 3 }; -vector creaturestypes; +vector creaturestypes; matGlosses mat; vector< vector > itemTypes; DFHack::memory_info *mem; @@ -155,7 +147,13 @@ likeType printLike40d(DFHack::t_like like, const matGlosses & mat,const vector< void printCreature(DFHack::API & DF, const DFHack::t_creature & creature) { - cout << "address: " << hex << creature.origin << dec << " creature type: " << creaturestypes[creature.race].id << ", position: " << creature.x << "x " << creature.y << "y "<< creature.z << "z" << endl; + cout << "address: " << hex << creature.origin << dec << " creature type: " << creaturestypes[creature.race].rawname + << "[" << creaturestypes[creature.race].tile_character + << "," << creaturestypes[creature.race].tilecolor.fore + << "," << creaturestypes[creature.race].tilecolor.back + << "," << creaturestypes[creature.race].tilecolor.bright + << "]" + << ", position: " << creature.x << "x " << creature.y << "y "<< creature.z << "z" << endl; bool addendl = false; if(creature.name.first_name[0]) { @@ -177,6 +175,14 @@ void printCreature(DFHack::API & DF, const DFHack::t_creature & creature) cout << ", trans name: " << transName; addendl=true; } + + transName = Tran->TranslateName(creature.name,true); + if(!transName.empty()) + { + cout << ", last name: " << transName; + addendl=true; + } + /* cout << ", likes: "; @@ -240,46 +246,46 @@ void printCreature(DFHack::API & DF, const DFHack::t_creature & creature) */ cout << endl; - - //skills - cout << "Skills" << endl; - for(unsigned int i = 0; i < creature.defaultSoul.numSkills;i++) + if(creature.has_default_soul) { - if(i > 0) + //skills + cout << "Skills" << endl; + for(unsigned int i = 0; i < creature.defaultSoul.numSkills;i++) { - cout << ", "; + if(i > 0) + { + cout << ", "; + } + cout << mem->getSkill(creature.defaultSoul.skills[i].id) << ": " << creature.defaultSoul.skills[i].rating; } - cout << mem->getSkill(creature.defaultSoul.skills[i].id) << ": " << creature.defaultSoul.skills[i].rating; - } - cout << endl; - - // labors - cout << "Labors" << endl; - for(unsigned int i = 0; i < NUM_CREATURE_LABORS;i++) - { - if(!creature.labors[i]) - continue; - string laborname; - try + cout << endl; + cout << "Traits" << endl; + for(uint32_t i = 0; i < 30;i++) { - laborname = mem->getLabor(i); + string trait = mem->getTrait (i, creature.defaultSoul.traits[i]); + if(!trait.empty()) cout << trait << ", "; } - catch(exception &) + cout << endl; + + // labors + cout << "Labors" << endl; + for(unsigned int i = 0; i < NUM_CREATURE_LABORS;i++) { - break; + if(!creature.labors[i]) + continue; + string laborname; + try + { + laborname = mem->getLabor(i); + } + catch(exception &) + { + break; + } + cout << laborname << ", "; } - cout << laborname << ", "; - } - cout << endl; - - cout << "Traits" << endl; - for(uint32_t i = 0; i < 30;i++) - { - string trait = mem->getTrait (i, creature.defaultSoul.traits[i]); - if(!trait.empty()) - cout << trait << ", "; + cout << endl; } - cout << endl; /* * FLAGS 1 */ @@ -341,17 +347,17 @@ void printCreature(DFHack::API & DF, const DFHack::t_creature & creature) cout << "from the underworld, "; } cout << endl; - /* + if(creature.flags1.bits.had_mood && (creature.mood == -1 || creature.mood == 8 ) ) { - string artifact_name = DF.TranslateName(creature.artifact_name,englishWords,foreignWords,false); + string artifact_name = Tran->TranslateName(creature.artifact_name,false); cout << "artifact: " << artifact_name << endl; - }*/ + } cout << endl; } -int main (void) +int main (int numargs, char ** args) { DFHack::API DF("Memory.xml"); try @@ -366,6 +372,9 @@ int main (void) #endif return 1; } + string check = ""; + if(numargs == 2) + check = args[1]; DFHack::Creatures * Creatures = DF.getCreatures(); DFHack::Materials * Materials = DF.getMaterials(); @@ -388,17 +397,10 @@ int main (void) #endif return 1; } - /* - DF.ReadItemTypes(itemTypes); - DF.ReadPlantMatgloss(mat.plantMat); - DF.ReadWoodMatgloss(mat.woodMat); - DF.ReadStoneMatgloss(mat.stoneMat); - DF.ReadMetalMatgloss(mat.metalMat); - DF.ReadCreatureMatgloss(mat.creatureMat); - */ + mem = DF.getMemoryInfo(); // get stone matgloss mapping - if(!Materials->ReadCreatureTypes(creaturestypes)) + if(!Materials->ReadCreatureTypesEx(creaturestypes)) { cerr << "Can't get the creature types." << endl; return 1; @@ -409,18 +411,21 @@ int main (void) cerr << "Can't get name tables" << endl; return 1; } - + vector addrs; //DF.InitViewAndCursor(); for(uint32_t i = 0; i < numCreatures; i++) { DFHack::t_creature temp; Creatures->ReadCreature(i,temp); - if(string(creaturestypes[temp.race].id) == "DWARF") + if(check.empty() || string(creaturestypes[temp.race].rawname) == check) { cout << "index " << i << " "; + printCreature(DF,temp); + addrs.push_back(temp.origin); } } + interleave_hex(DF,addrs,200); /* uint32_t currentIdx; DFHack::t_creature currentCreature; diff --git a/examples/materialtest.cpp b/examples/materialtest.cpp index db7e5d2a8..487cd9a12 100644 --- a/examples/materialtest.cpp +++ b/examples/materialtest.cpp @@ -8,6 +8,7 @@ #include using namespace std; +#include #include #include #include @@ -56,13 +57,47 @@ int main (int numargs, const char ** args) { cout << i << ": " << matgloss[i].id << endl; } - cout << endl << "----==== Creature types ====----" << endl; - vector creature; - Materials->ReadCreatureTypes (matgloss); + cout << endl << "----==== Organic - trees ====----" << endl; + Materials->ReadWoodMaterials (matgloss); + for(uint32_t i = 0; i < matgloss.size();i++) + { + cout << i << ": " << matgloss[i].id << endl; + } + cout << endl << "----==== Organic - plants ====----" << endl; + Materials->ReadPlantMaterials (matgloss); for(uint32_t i = 0; i < matgloss.size();i++) { cout << i << ": " << matgloss[i].id << endl; } + cout << endl << "----==== Creature types ====----" << endl; + vector creature; + Materials->ReadCreatureTypesEx (creature); + for(uint32_t i = 0; i < creature.size();i++) + { + cout << i << ": " << creature[i].rawname << endl; + vector & castes = creature[i].castes; + for(uint32_t j = 0; j < castes.size();j++) + { + cout << " [" + << castes[j].rawname << ":" + << castes[j].singular << ":" + << castes[j].plural << ":" + << castes[j].adjective << "] "; + cout << endl; + } + cout << endl; + } + cout << endl << "----==== Color descriptors ====----" << endl; + vector colors; + Materials->ReadDescriptorColors(colors); + for(uint32_t i = 0; i < colors.size();i++) + { + cout << i << ": " << colors[i].id << " - " << colors[i].name << "[" + << (unsigned int) (colors[i].r*255) << ":" + << (unsigned int) (colors[i].v*255) << ":" + << (unsigned int) (colors[i].b*255) << ":" + << "]" << endl; + } #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; cin.ignore(); diff --git a/examples/miscutils.h b/examples/miscutils.h index 504933e36..02b8f6462 100644 --- a/examples/miscutils.h +++ b/examples/miscutils.h @@ -10,15 +10,17 @@ #include using namespace std; +#include +#include #include void DumpObjStr0Vector (const char * name, DFHack::Process *p, uint32_t addr) { cout << "----==== " << name << " ====----" << endl; - DFHack::DfVector vect(p,addr,4); - for(uint32_t i = 0; i < vect.getSize();i++) + DFHack::DfVector vect(p,addr); + for(uint32_t i = 0; i < vect.size();i++) { - uint32_t addr = *(uint32_t *) vect[i]; + uint32_t addr = vect[i]; cout << p->readSTLString(addr) << endl; } cout << endl; @@ -26,10 +28,10 @@ void DumpObjStr0Vector (const char * name, DFHack::Process *p, uint32_t addr) void DumpObjVtables (const char * name, DFHack::Process *p, uint32_t addr) { cout << "----==== " << name << " ====----" << endl; - DFHack::DfVector vect(p,addr,4); - for(uint32_t i = 0; i < vect.getSize();i++) + DFHack::DfVector vect(p,addr); + for(uint32_t i = 0; i < vect.size();i++) { - uint32_t addr = *(uint32_t *) vect[i]; + uint32_t addr = vect[i]; uint32_t vptr = p->readDWord(addr); cout << p->readClassName(vptr) << endl; } @@ -38,10 +40,10 @@ void DumpObjVtables (const char * name, DFHack::Process *p, uint32_t addr) void DumpDWordVector (const char * name, DFHack::Process *p, uint32_t addr) { cout << "----==== " << name << " ====----" << endl; - DFHack::DfVector vect(p,addr,4); - for(uint32_t i = 0; i < vect.getSize();i++) + DFHack::DfVector vect(p,addr); + for(uint32_t i = 0; i < vect.size();i++) { - uint32_t number = *(uint32_t *) vect[i]; + uint32_t number = vect[i]; cout << number << endl; } cout << endl; diff --git a/examples/spatterdump.cpp b/examples/spatterdump.cpp index 1f7aca438..69d1aeedd 100644 --- a/examples/spatterdump.cpp +++ b/examples/spatterdump.cpp @@ -10,6 +10,7 @@ #include using namespace std; +#include #include #include #include diff --git a/examples/suspendtest.cpp b/examples/suspendtest.cpp index 9e89a2e93..70cbe1816 100644 --- a/examples/suspendtest.cpp +++ b/examples/suspendtest.cpp @@ -27,7 +27,6 @@ int main (void) #endif return 1; } - cout << "Attached, DF should be suspended now" << endl; getline(cin, blah); diff --git a/examples/treedump.cpp b/examples/treedump.cpp index 463bbb8c3..a5f00d35e 100644 --- a/examples/treedump.cpp +++ b/examples/treedump.cpp @@ -10,6 +10,7 @@ #include using namespace std; +#include #include #include #include diff --git a/examples/veccheck.cpp b/examples/veccheck.cpp index 9f016677a..d3f55d5cf 100644 --- a/examples/veccheck.cpp +++ b/examples/veccheck.cpp @@ -10,6 +10,7 @@ #include using namespace std; +#include #include #include #include @@ -21,9 +22,76 @@ using namespace std; #include #include #include "miscutils.h" +#include using namespace DFHack; +/* +int __userpurge get_feature_at(__int16 tZ, __int16 tY, int world_base, signed __int16 tX) +{ + int block; // ebp@1 + signed __int16 __tX; // di@1 + signed int _tY; // esi@1 + int designation; // eax@2 + int _tX; // ecx@2 + signed int v9; // eax@4 + int v10; // edx@4 + __int64 region_x_local; // qax@4 + __int16 v12; // cx@4 + __int16 v13; // ax@5 + int v14; // esi@5 + int result; // eax@7 + unsigned int some_stuff; // ebp@10 + int v17; // edx@11 + int _designation; // [sp+10h] [bp+4h]@2 + __tX = tX; + LOWORD(_tY) = tY; + block = getBlock(world_base, tX, tY, tZ); + if ( !block ) + goto LABEL_17; + _tX = tX; + _tY = (signed __int16)_tY; + designation = *(_DWORD *)(block + 0x29C + 4 * ((signed __int16)_tY % 16 + 16 * tX % 16)); + _designation = designation; + if ( designation & 0x10000000 && *(_WORD *)(block + 0x2C) != -1 )// first feature_present bit - adamantine + { + region_x_local = __tX / 48 + *(_DWORD *)(world_base + 0x525C8);// tile_x / 48 + region_x + v12 = ((BYTE4(region_x_local) & 0xF) + (_DWORD)region_x_local) >> 4; + WORD2(region_x_local) = (_tY / 48 + *(_DWORD *)(world_base + 0x525CC)) / 16;// tile_y / 48 + region_y + v9 = v12; + _tX = SWORD2(region_x_local); + v10 = *(_DWORD *)(*(_DWORD *)(*(_DWORD *)(world_base + 0x54440) + 4 * (v9 >> 4)) + + 16 * (SWORD2(region_x_local) >> 4) + + 4); + if ( v10 ) + { + _tX %= 16; + v14 = v10 + 24 * ((signed __int16)_tX + 16 * v9 % 16); + v13 = *(_WORD *)(block + 0x2C); + if ( v13 >= 0 ) + { + _tX = (*(_DWORD *)(v14 + 16) - *(_DWORD *)(v14 + 12)) >> 2; + if ( v13 < (unsigned int)_tX ) + return *(_DWORD *)sub_519100(_tX, v10); + } + } + designation = _designation; + } + if ( designation & 0x20000000 && (some_stuff = *(_DWORD *)(block + 0x30), some_stuff != -1) )// second feature_present bit - slade and hell + { + v17 = (*(_DWORD *)(world_base + 0x54384) - *(_DWORD *)(world_base + 0x54380)) >> 2; + if ( some_stuff >= v17 ) + _invalid_parameter_noinfo(_tX, v17); + result = *(_DWORD *)(*(_DWORD *)(*(_DWORD *)(world_base + 0x54380) + 4 * some_stuff) + 0x100); + } + else + { +LABEL_17: + result = 0; + } + return result; +} +*/ int main (int numargs, const char ** args) { DFHack::API DF("Memory.xml"); @@ -39,46 +107,127 @@ int main (int numargs, const char ** args) #endif return 1; } - /* - DFHack::Position *Pos = DF.getPosition(); + DFHack::Position *Pos = DF.getPosition(); + DFHack::memory_info* mem = DF.getMemoryInfo(); DFHack::Maps *Maps = DF.getMaps(); + DFHack::Process * p = DF.getProcess(); + uint32_t designatus = mem->getOffset("map_data_designation"); + uint32_t block_feature1 = mem->getOffset("map_data_feature1"); + uint32_t block_feature2 = mem->getOffset("map_data_feature2"); + uint32_t region_x_offset = mem->getAddress("region_x"); + uint32_t region_y_offset = mem->getAddress("region_y"); + uint32_t region_z_offset = mem->getAddress("region_z"); + uint32_t feature1_start_ptr = mem->getAddress("feature1_start_ptr"); + uint32_t regionX, regionY, regionZ; + + // read position of the region inside DF world + p->readDWord (region_x_offset, regionX); + p->readDWord (region_y_offset, regionY); + p->readDWord (region_z_offset, regionZ); + Maps->Start(); - int32_t cx, cy, cz; - Pos->getCursorCoords(cx,cy,cz); - if(cx != -30000) + int32_t cursorX, cursorY, cursorZ; + Pos->getCursorCoords(cursorX,cursorY,cursorZ); + if(cursorX != -30000) { - uint32_t bx = cx / 16; - uint32_t tx = cx % 16; - uint32_t by = cy / 16; - uint32_t ty = cy % 16; + uint32_t blockX = cursorX / 16; + uint32_t tileX = cursorX % 16; + uint32_t blockY = cursorY / 16; + uint32_t tileY = cursorY % 16; mapblock40d block; - if(Maps->ReadBlock40d(bx,by,cz,&block)) - { - int16_t tiletype = block.tiletypes[tx][ty]; - cout << tiletype << endl; - } - } - */ - vector classIdStrings; - DFHack::memory_info * minfo = DF.getMemoryInfo(); - if(!minfo) - { - cerr <<"FAIL!" << endl; - return 1; - } - for(int i = 0; ; i++) - { - string temp; - if(!minfo->resolveClassIDToClassname(i, temp)) + if(Maps->ReadBlock40d(blockX,blockY,cursorZ,&block)) { - break; + printf("block addr: 0x%x\n", block.origin); + int16_t tiletype = block.tiletypes[tileX][tileY]; + naked_designation &des = block.designation[tileX][tileY].bits; + uint32_t &desw = block.designation[tileX][tileY].whole; + print_bits(block.designation[tileX][tileY].whole,cout); + cout << endl; + print_bits(block.occupancy[tileX][tileY].whole,cout); + cout << endl; + // tiletype + cout <<"tiletype: " << tiletype; + if(tileTypeTable[tiletype].name) + cout << " = " << tileTypeTable[tiletype].name; + cout << endl; + // features present + if(des.feature_type_1) + { + cout << "feature type 1 present: " << p->readDWord(block.origin + block_feature1) << endl; + int32_t idx = p->readDWord(block.origin + block_feature1); + if(idx != -1) + { + uint64_t bigblock_x = cursorX / 48 + regionX; + // blah, dumb disassembly. too tired to think + uint16_t v12 = ((bigblock_x % 16) + bigblock_x) / 16; + uint64_t region_y_local = (cursorY / 48 + regionY) / 16; + // deref pointer to the humongo-structure + uint32_t base = p->readDWord(feature1_start_ptr); + // this is just a few pointers to arrays of 16B (4 DWORD) structs + uint32_t array_elem = p->readDWord(base + (v12 / 16) * 4); + // second element of the struct is a pointer + uint32_t wtf = p->readDWord(array_elem + (16*(region_y_local/16)) + 4); // rounding! + if(wtf) + { + uint32_t feat_vector = wtf + 24 * (region_y_local % 16); + DfVector p_features(p, feat_vector); + printf("feature addr: 0x%x\n", p_features[idx]); + string name = p->readClassName(p->readDWord( p_features[idx] )); + cout << name << endl; + } + } + } + if(des.feature_type_2) + { + int32_t idx = p->readDWord(block.origin + block_feature2); + cout << "feature type 2 present: " << idx << endl; + if(idx != -1) + { + DfVector p_features (p,mem->getAddress("feature2_vector")); + if(idx < p_features.size()) + { + uint32_t feat_ptr = p->readDWord(p_features[idx] + mem->getOffset("feature2_funcptr_")); + printf("feature descriptor?: 0x%x\n", feat_ptr); + string name = p->readClassName(p->readDWord( feat_ptr)); + cout << name << endl; + } + } + } + // biome, geolayer + cout << "biome: " << des.biome << endl; + cout << "geolayer: " << des.geolayer_index << endl; + // liquids + if(des.flow_size) + { + if(des.liquid_type == DFHack::liquid_magma) + cout <<"magma: "; + else cout <<"water: "; + cout << des.flow_size << endl; + } + if(des.flow_forbid) + cout << "flow forbid" << endl; + if(des.pile) + cout << "stockpile?" << endl; + if(des.rained) + cout << "rained?" << endl; + if(des.smooth) + cout << "smooth?" << endl; + uint32_t designato = block.origin + designatus + (tileX * 16 + tileY) * sizeof(t_designation); + printf("designation offset: 0x%x\n", designato); + /* + block.designation[tx][ty].bits.moss = 1; + block.designation[tx][ty].bits.geolayer_index = 15; + block.tiletypes[tx][ty] = 344; + + print_bits(block.designation[tx][ty].whole,cout); + Maps->WriteDesignations(bx,by,cz,&(block.designation)); + Maps->WriteTileTypes(bx,by,cz,&(block.tiletypes)); + */ + } - classIdStrings.push_back(temp); } - for (int i = 0; i < classIdStrings.size(); i++) - cout << i << ": " << classIdStrings[i] << 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 9a08490a0..fdda877ec 100644 --- a/examples/veinlook.cpp +++ b/examples/veinlook.cpp @@ -14,7 +14,9 @@ using namespace std; #include #include #include +#include +#include #include #include #include @@ -30,6 +32,22 @@ string error; API * pDF = 0; +struct t_tempz +{ + int32_t limit; + int character; +}; + +t_tempz temp_limits[]= +{ + {50, '.'}, + {100, '+'}, + {500, '*'}, + {1000, '#'}, + {2000, '!'} +}; +#define NUM_LIMITS 5 + static void finish(int sig); int gotoxy(int x, int y) @@ -315,6 +333,8 @@ main(int argc, char *argv[]) vector veinVector; vector IceVeinVector; vector splatter; + t_temperatures b_temp1; + t_temperatures b_temp2; DFHack::Materials * Mats = 0; DFHack::Maps * Maps = 0; @@ -392,6 +412,13 @@ main(int argc, char *argv[]) uint32_t blockaddr2 = 0; t_blockflags bflags; bflags.whole = 0; + enum e_tempmode + { + TEMP_NO, + TEMP_1, + TEMP_2 + }; + e_tempmode temperature = TEMP_NO; // resume so we don't block DF while we wait for input DF.Resume(); @@ -451,6 +478,15 @@ main(int argc, char *argv[]) case 't': dotwiddle = true; break; + case 'b': + temperature = TEMP_NO; + break; + case 'n': + temperature = TEMP_1; + break; + case 'm': + temperature = TEMP_2; + break; default: break; } @@ -520,6 +556,9 @@ main(int argc, char *argv[]) } Maps->WriteDesignations(cursorX+i,cursorY+j,cursorZ, &(Block->designation)); } + + // read temperature data + Maps->ReadTemperatures(cursorX+i,cursorY+j,cursorZ,&b_temp1, &b_temp2 ); if(dotwiddle) { bitset<32> bs = Block->designation[0][0].whole; @@ -528,6 +567,7 @@ main(int argc, char *argv[]) Maps->WriteDesignations(cursorX+i,cursorY+j,cursorZ, &(Block->designation)); dotwiddle = false; } + // do a dump of the block data if(dump) { @@ -588,11 +628,11 @@ main(int argc, char *argv[]) } */ } - gotoxy(0,48); + gotoxy(50,0); cprintf("arrow keys, PGUP, PGDN = navigate"); - gotoxy(0,49); + gotoxy(50,1); cprintf("+,- = switch vein"); - gotoxy(0,50); + gotoxy(50,2); uint32_t mineralsize = veinVector.size(); uint32_t icesize = IceVeinVector.size(); uint32_t splattersize = splatter.size(); @@ -630,7 +670,7 @@ main(int argc, char *argv[]) } } } - gotoxy(0,51); + gotoxy(50,3); cprintf("Mineral: %s",stonetypes[veinVector[vein].type].id); } else if (vein < mineralsize + icesize) @@ -650,7 +690,7 @@ main(int argc, char *argv[]) attroff(A_STANDOUT); } } - gotoxy(0,51); + gotoxy(50,3); cprintf("ICE"); } else @@ -670,25 +710,78 @@ main(int argc, char *argv[]) } } } - gotoxy(0,51); + gotoxy(50,3); cprintf("Spatter: %s",PrintSplatterType(splatter[realvein].mat1,splatter[realvein].mat2,creature_types).c_str()); } } } mapblock40d * Block = &blocks[1][1]; - for(int x = 0; x < 16; x++) for(int y = 0; y < 16; y++) + t_temperatures * ourtemp; + if(temperature == TEMP_NO) { - if((Block->occupancy[x][y].whole & (1 << twiddle))) + for(int x = 0; x < 16; x++) for(int y = 0; y < 16; y++) { - putch(x + 16,y + 16,'@',COLOR_WHITE); + if((Block->occupancy[x][y].whole & (1 << twiddle))) + { + putch(x + 16,y + 16,'@',COLOR_WHITE); + } + } + } + else + { + if(temperature == TEMP_1) + ourtemp = &b_temp1; + else if(temperature == TEMP_2) + ourtemp = &b_temp2; + uint64_t sum = 0; + uint16_t min, max; + min = max = (*ourtemp)[0][0]; + for(int x = 0; x < 16; x++) for(int y = 0; y < 16; y++) + { + uint16_t temp = (*ourtemp)[x][y]; + if(temp < min) min = temp; + if(temp > max) max = temp; + sum += temp; + } + uint64_t average = sum/256; + gotoxy (50,8); + if(temperature == TEMP_1) + cprintf ("temperature1 [°U] (min,avg,max): %d,%d,%d", min, average, max); + else if(temperature == TEMP_2) + cprintf ("temperature2 [°U] (min,avg,max): %d,%d,%d", min, average, max); + + for(int x = 0; x < 16; x++) for(int y = 0; y < 16; y++) + { + int32_t temper = (int32_t) (*ourtemp)[x][y]; + temper -= average; + uint32_t abs_temp = abs(temper); + int color; + unsigned char character = ' '; + if(temper >= 0) + color = COLOR_RED; + else + color = COLOR_BLUE; + + for(int i = 0; i < NUM_LIMITS; i++) + { + if(temp_limits[i].limit < abs_temp) + character = temp_limits[i].character; + else break; + } + if( character != ' ') + { + putch(x + 16,y + 16,character,color); + } } } - gotoxy (0,52); + gotoxy (50,4); cprintf("block address 0x%x, flags 0x%08x",blockaddr, bflags.whole); - gotoxy (0,53); + gotoxy (50,5); cprintf("dirty bit: %d, twiddle: %d",dirtybit,twiddle); - gotoxy (0,54); + gotoxy (50,6); cprintf ("d - dig veins, o - dump map block, z - toggle dirty bit"); + gotoxy (50,7); + cprintf ("b - no temperature, n - temperature 1, m - temperature 2"); wrefresh(stdscr); } pDF = 0; diff --git a/output/Memory.xml b/output/Memory.xml index 116a87c5c..8be57eb89 100644 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -920,6 +920,7 @@ size=212 + @@ -1052,11 +1053,23 @@ size=212 Map stuff =========
0x016AD718
- 0x08 - 0x009A - 0x029C - 0x069c - 0x1D9C + 0x08 + 0x009A + 0x029C + 0x069c + 0x159c + 0x179c + 0x1D9C + 0x0D9c + 0x2C adamantine? + 0x30 hell? + + WORLD + 0x54374 +
0x16AF4FC
+ 0x100 + WORLD + 0x54440 +
0x16AF5C8
+ + 0X120 0X1F4 + 0X21C 0x238 + 0x28C + 0x290 + 0x464 - - - - this is an array of 4B pointers to material templates and length 0x292 - base_type_array = WORLD + 0x5DF44 -
0x016b90cc
-
0x16afcec
- - + soil, stone, metal inorganics vector = WORLD + 0x54B7C = 0x16AFD04
0x16afd04
- 0x178 - + wood and plant matter, WORLD + 0x54B94
0x16afd1C
- + plant matter, WORLD + 0x54BAC
0x16afd34
- + just wood, WORLD + 0x54BDC +
0x16afd64
+ + creature types actually used for creatures, + WORLD + 0x54CD0 +
0x016AFE58
+ 0x138 + 0xE0 + 0xF6 + + -
0x16afd64
- + + maybe maps beween organics_all and organics_trees
0x16afd7C
- + body material stuff
0x16AFD94
0x16AFDAC
0x16AFDC4
0x16AFDDC
0x16AFDF4
- + *raw* creature types
0x16AFE0C
- -
0x016AFE58
- - + --> Constructions ============= + WORLD + 0x108
0x165b290
0x14 Translations ============ + WORLD + 0x54E50
0x016AFFD8
+ WORLD + 0x54E80
0x016B0008
0x4C Vegetation ========== + WORLD + 0x15184
0x0167030C
belal: 0x017f6d98 ... what? 0x6C Buildings ========= + WORLD + 0x14818
0x0166f9a0
+ 0x164 + WORLD + 0x5D610 +
0x016B8798
+ 0x4 + 0x20 Effects ======= @@ -1291,6 +1334,141 @@ map_data_1b60_offset 0x1B9c 23dfe141c7ea4e63ebb3c618a12b48ec 0x4BBDF378 + + + 94641d97a0ecff6f2194e3d0b310d946 + 0x4BC3C470 + + WORLD: 0x0165c1d0 ? + + Position + ======== +
0x17f6b00
Was 0x17f5ab8 + 0x17f6b00 + 0x17f6b08 + 0x17f6b10 + + Map + === +
0x016AE760
+ + * map size in blocks * +
0x016AE780
+
0x016AE784
+
0x016AE788
+ + * map size in tiles * +
0x016AE78C
+
0x016AE790
+
0x016AE794
+ + * Suspected region coords * +
0x016AE798
+
0x016AE79C
+
0x016AE7A0
+ + * World size * (WORDs) +
0x016AFE1C
+
0x016AFE1E
+ + * geology * +
0x16B0574
+
0x16B05BC
+ + * features * + WORLD + 0x54374 +
0x16B0544
+
0x16B0610
+ + Creatures + ========= +
0x166FD0C
+
0x01471fbc
+ 0x0 + 0x6c + 0x88 + 0x8C + 0x90 + 0xF8 + 0xFC + 0x110 + 0x114 + 0X120 + 0X1F4 + 0X21C + + + 0x464 + + 0x390 + 0x6D4 + 0x774 + 0x0740 + 0x0758 + 0x834 + + + Materials + ========= + soil, stone, metal + inorganics vector = WORLD + 0x54B7C = 0x16B0D4C +
0x16B0D4C
+ + wood and plant matter, WORLD + 0x54B94 +
0x16B0D64
+ + plant matter, WORLD + 0x54BAC +
0x16B0D7C
+ + just wood, WORLD + 0x54BDC +
0x16B0DAC
+ + creature types actually used for creatures, WORLD + 0x54CD0 +
0x16B0EA0
+ + Constructions + ============= + WORLD + 0x108 +
0x165C2D8
+ + Translations + ============ + WORLD + 0x54E50 +
0x016B1020
+ WORLD + 0x54E80 +
0x16B1050
+ + Vegetation + ========== + WORLD + 0x15184 +
0x1671354
+ + Buildings + ========= + WORLD + 0x14818 +
0x16709E8
+ WORLD + 0x5D610 +
0x16B97E0
+ 0x4 + 0x20 + + Descriptor colors + ================= +
0x16B9780
+ 0x0 + 0x4C +
0x16B9768
+ 0x6C floats ! + 0x70 + 0x74 +
.-"""-. ' \ diff --git a/output/dfXvdig.bat b/output/dfXvdig.bat new file mode 100644 index 000000000..5c93c7962 --- /dev/null +++ b/output/dfXvdig.bat @@ -0,0 +1 @@ +dfvdig.exe -x \ No newline at end of file diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 4534481e7..2be94dc20 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -50,8 +50,8 @@ TARGET_LINK_LIBRARIES(dfdigger dfhack) # a magma creation tool # Author: Aleric -ADD_EXECUTABLE(dfmagma_create magma_create.cpp) -TARGET_LINK_LIBRARIES(dfmagma_create dfhack) +ADD_EXECUTABLE(dfliquids liquids.cpp) +TARGET_LINK_LIBRARIES(dfliquids dfhack) IF(UNIX) install(TARGETS diff --git a/tools/cleanmap.cpp b/tools/cleanmap.cpp index e9a5b8e5a..a85432d5f 100644 --- a/tools/cleanmap.cpp +++ b/tools/cleanmap.cpp @@ -60,7 +60,7 @@ int main (void) for(uint32_t i = 0; i < splatter.size(); i++) { DFHack::t_spattervein & vein = splatter[i]; - if(vein.mat1 > 19) + if(vein.mat1 != 0xC) { uint32_t addr = vein.address_of; uint32_t offset = offsetof(DFHack::t_spattervein, intensity); diff --git a/tools/dfbauxite.cpp b/tools/dfbauxite.cpp index 10e867f4a..cebff1351 100644 --- a/tools/dfbauxite.cpp +++ b/tools/dfbauxite.cpp @@ -31,7 +31,7 @@ int main () { DFHack::Process *proc; DFHack::memory_info *meminfo; - DFHack::DfVector *items_vector; + DFHack::DfVector *items_vector; DFHack::t_item_df40d item_40d; DFHack::t_matglossPair item_40d_material; vector stoneMat; @@ -105,11 +105,11 @@ int main () return EXIT_FAILURE; } - items_vector = new DFHack::DfVector (proc, items, 4); - for(uint32_t i = 0; i < items_vector->getSize(); i++) + items_vector = new DFHack::DfVector (proc, items); + for(uint32_t i = 0; i < items_vector->size(); i++) { // get pointer to object - temp = * (uint32_t *) items_vector->at (i); + temp = items_vector->at (i); // read object proc->read (temp, sizeof (DFHack::t_item_df40d), (uint8_t *) &item_40d); diff --git a/tools/liquids.cpp b/tools/liquids.cpp new file mode 100644 index 000000000..e0cc4a5be --- /dev/null +++ b/tools/liquids.cpp @@ -0,0 +1,252 @@ +// This will create 7 deep magama on the square the cursor is on. It does not +// enable magma buildings at this time. + +#include +#include +#include +using namespace std; + +#include +#include +#include +#include +#include + +int main (void) +{ + int32_t x,y,z; + DFHack::designations40d designations; + DFHack::tiletypes40d tiles; + DFHack::t_temperatures temp1,temp2; + uint32_t x_max,y_max,z_max; + + DFHack::API DF("Memory.xml"); + DFHack::Maps * Maps; + DFHack::Position * Position; + try + { + DF.Attach(); + Maps = DF.getMaps(); + Position = DF.getPosition(); + } + catch (exception& e) + { + cerr << e.what() << endl; + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + bool end = false; + cout << "Welcome to the liquid spawner. type 'help' for a list of available commands, 'q' to quit." << endl; + string mode="magma"; + string brush="point"; + string flowmode="f+"; + int amount = 7; + while(!end) + { + Maps->getSize(x_max,y_max,z_max); + DF.Resume(); + string command = ""; + cout <<"[" << mode << ":" << amount << ":" << flowmode << "]# "; + getline(cin, command); + if(command=="help") + { + cout << "Modes:" << endl + << "m - switch to magma" << endl + << "w - switch to water" << endl + << "o - make obsidian wall instead" << endl + << "f - flow bits only" << endl + << "Properties:" << endl + << "f+ - make the spawned liquid flow" << endl + << "f. - don't change flow state (read state in flow mode)" << endl + << "f- - make the spawned liquid static" << endl + << "0-7 - set liquid amount" << endl + << "Brush:" << endl + << "point - single tile" << endl + << "block - block with cursor in it" << endl + << "Other:" << endl + << "q - quit" << endl + << "help - print this list of commands" << endl + << "empty line - put liquid" << endl + << endl + << "Usage: point the DF cursor at a tile you want to modify" << endl + << "and use the commands available :)" << endl; + + } + else if(command == "m") + { + mode = "magma"; + } + else if(command == "o") + { + mode = "obsidian"; + } + else if(command == "clmn") + { + mode = "column"; + } + else if(command == "w") + { + mode = "water"; + } + else if(command == "f") + { + mode = "flowbits"; + } + else if(command == "point") + { + brush = "point"; + } + else if(command == "block") + { + brush = "block"; + } + else if(command == "q") + { + end = true; + } + else if(command == "f+") + { + flowmode = "f+"; + } + else if(command == "f-") + { + flowmode = "f-"; + } + else if(command == "f.") + { + flowmode = "f."; + } + // blah blah, bad code, bite me. + else if(command == "0") + amount = 0; + else if(command == "1") + amount = 1; + else if(command == "2") + amount = 2; + else if(command == "3") + amount = 3; + else if(command == "4") + amount = 4; + else if(command == "5") + amount = 5; + else if(command == "6") + amount = 6; + else if(command == "7") + amount = 7; + else if(command.empty()) + { + DF.Suspend(); + do + { + if(!Maps->Start()) + { + cout << "Can't see any DF map loaded." << endl; + break; + } + if(!Position->getCursorCoords(x,y,z)) + { + cout << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl; + break; + } + cout << "cursor coords: " << x << "/" << y << "/" << z << endl; + if(!Maps->isValidBlock(x/16,y/16,z)) + { + cout << "Not a valid block." << endl; + break; + } + if(mode == "obsidian") + { + Maps->ReadTileTypes((x/16),(y/16),z, &tiles); + tiles[x%16][y%16] = 331; + Maps->WriteTileTypes((x/16),(y/16),z, &tiles); + } + else if(mode == "column") + { + int zzz = z; + int16_t tile; + while ( zzz < z_max ) + { + Maps->ReadTileTypes((x/16),(y/16),zzz, &tiles); + tile = tiles[x%16][y%16]; + if (DFHack::tileTypeTable[tile].c == DFHack::WALL) + break; + tiles[x%16][y%16] = 331; + Maps->WriteTileTypes((x/16),(y/16),zzz, &tiles); + zzz++; + } + } + else + { + // place the magma + Maps->ReadDesignations((x/16),(y/16),z, &designations); + Maps->ReadTemperatures((x/16),(y/16),z, &temp1, &temp2); + if(brush == "point") + { + if(mode != "flowbits") + { + // fix temperatures so we don't produce lethal heat traps + if(amount == 0 || designations[x%16][y%16].bits.liquid_type == DFHack::liquid_magma && mode == "water") + temp1[x%16][y%16] = temp2[x%16][y%16] = 10015; + designations[x%16][y%16].bits.flow_size = amount; + } + if(mode == "magma") + designations[x%16][y%16].bits.liquid_type = DFHack::liquid_magma; + else if(mode == "water") + designations[x%16][y%16].bits.liquid_type = DFHack::liquid_water; + } + else + { + for(uint32_t xx = 0; xx < 16; xx++) for(uint32_t yy = 0; yy < 16; yy++) + { + if(mode != "flowbits") + { + // fix temperatures so we don't produce lethal heat traps + if(amount == 0 || designations[xx][yy].bits.liquid_type == DFHack::liquid_magma && mode == "water") + temp1[xx%16][yy%16] = temp2[xx%16][yy%16] = 10015; + designations[xx][yy].bits.flow_size = amount; + } + if(mode == "magma") + designations[xx][yy].bits.liquid_type = DFHack::liquid_magma; + else if(mode == "water") + designations[xx][yy].bits.liquid_type = DFHack::liquid_water; + } + } + Maps->WriteTemperatures((x/16),(y/16),z, &temp1, &temp2); + Maps->WriteDesignations(x/16,y/16,z, &designations); + } + + // make the magma flow :) + DFHack::t_blockflags bflags; + Maps->ReadBlockFlags((x/16),(y/16),z,bflags); + // 0x00000001 = job-designated + // 0x0000000C = run flows? - both bit 3 and 4 required for making magma placed on a glacier flow + if(flowmode == "f+") + { + bflags.bits.liquid_1 = true; + bflags.bits.liquid_2 = true; + } + else if(flowmode == "f-") + { + bflags.bits.liquid_1 = false; + bflags.bits.liquid_2 = false; + } + else + { + cout << "flow bit 1 = " << bflags.bits.liquid_1 << endl; + cout << "flow bit 2 = " << bflags.bits.liquid_2 << endl; + } + Maps->WriteBlockFlags((x/16),(y/16),z,bflags); + cout << "OK" << endl; + Maps->Finish(); + } while (0); + } + } + DF.Detach(); + #ifndef LINUX_BUILD + cout << "Done. Press any key to continue" << endl; + cin.ignore(); + #endif + return 0; +} diff --git a/tools/magma_create.cpp b/tools/magma_create.cpp deleted file mode 100644 index 9bc78a11e..000000000 --- a/tools/magma_create.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// This will create 7 deep magama on the square the cursor is on. It does not -// enable magma buildings at this time. - -#include -#include -#include -using namespace std; - -#include -#include -#include -#include - -int main (void) -{ - int32_t x,y,z; - DFHack::designations40d designations; - - DFHack::API DF("Memory.xml"); - DFHack::Maps * Maps; - DFHack::Position * Position; - try - { - DF.Attach(); - Maps = DF.getMaps(); - Position = DF.getPosition(); - } - catch (exception& e) - { - cerr << e.what() << endl; - #ifndef LINUX_BUILD - cin.ignore(); - #endif - return 1; - } - - Maps->Start(); - - if(Position->getCursorCoords(x,y,z)) - { - cout << "cursor coords: " << x << "/" << y << "/" << z << endl; - if(Maps->isValidBlock(x/16,y/16,z)) - { - // place the magma - Maps->ReadDesignations((x/16),(y/16),z, &designations); - designations[x%16][y%16].bits.flow_size = 7; - designations[x%16][y%16].bits.liquid_type = DFHack::liquid_magma; - Maps->WriteDesignations(x/16,y/16,z, &designations); - - // make the magma flow :) - DFHack::t_blockflags bflags; - Maps->ReadBlockFlags((x/16),(y/16),z,bflags); - // 0x00000001 = job-designated - // 0x0000000C = run flows? - both bit 3 and 4 required for making magma placed on a glacier flow - bflags.bits.liquid_1 = true; - bflags.bits.liquid_2 = true; - Maps->WriteBlockFlags((x/16),(y/16),z,bflags); - Maps->Finish(); - cout << "Success" << endl; - } - else - cout << "Failure 1" << endl; - } - else - cout << "Failure 2" << endl; - DF.Detach(); - #ifndef LINUX_BUILD - cout << "Done. Press any key to continue" << endl; - cin.ignore(); - #endif - return 0; -} diff --git a/tools/reveal.cpp b/tools/reveal.cpp index de1304e34..82da1b2fe 100644 --- a/tools/reveal.cpp +++ b/tools/reveal.cpp @@ -9,6 +9,15 @@ using namespace std; #include #include + +struct hideblock +{ + uint32_t x; + uint32_t y; + uint32_t z; + uint8_t hiddens [16][16]; +}; + int main (void) { uint32_t x_max,y_max,z_max; @@ -40,8 +49,9 @@ int main (void) } Maps->getSize(x_max,y_max,z_max); - - // walk the map + vector hidesaved; + // walk the map, save the hide bits, reveal. + cout << "Revealing... please wait." << endl; for(uint32_t x = 0; x< x_max;x++) { for(uint32_t y = 0; y< y_max;y++) @@ -50,20 +60,45 @@ int main (void) { if(Maps->isValidBlock(x,y,z)) { + hideblock hb; + hb.x = x; + hb.y = y; + hb.z = z; // read block designations Maps->ReadDesignations(x,y,z, &designations); // change the hidden flag to 0 for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++) { + hb.hiddens[i][j] = designations[i][j].bits.hidden; designations[i][j].bits.hidden = 0; } + hidesaved.push_back(hb); // write the designations back Maps->WriteDesignations(x,y,z, &designations); } } } } + // FIXME: force game pause here! DF.Detach(); + cout << "Map revealed. Close window/force exit to keep it that way." << endl; + cout << "Press any key to unreveal. Don't close DF or unpause in that case!" << endl; + cin.ignore(); + cout << "Unrevealing... please wait." << endl; + // FIXME: do some consistency checks here! + DF.Attach(); + Maps = DF.getMaps(); + Maps->Start(); + for(int i = 0; i < hidesaved.size();i++) + { + hideblock & hb = hidesaved[i]; + Maps->ReadDesignations(hb.x,hb.y,hb.z, &designations); + for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++) + { + designations[i][j].bits.hidden = hb.hiddens[i][j]; + } + Maps->WriteDesignations(hb.x,hb.y,hb.z, &designations); + } #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; cin.ignore(); diff --git a/tools/vdig.cpp b/tools/vdig.cpp index 93eceefce..f1cd1b706 100644 --- a/tools/vdig.cpp +++ b/tools/vdig.cpp @@ -6,6 +6,7 @@ #include #include #include +#include using namespace std; #include @@ -15,53 +16,66 @@ using namespace std; #include #include #include +#include #define MAX_DIM 0x300 class Point { public: - Point(uint32_t x, uint32_t y) + Point(uint32_t x, uint32_t y, uint32_t z) { this->x = x; this->y = y; + this->z = z; + } + Point() + { + x = y = z = 0; } bool operator==(const Point &other) const { - return (other.x == x && other.y == y); + return (other.x == x && other.y == y && other.z == z); } bool operator<(const Point &other) const { - return ( (y*MAX_DIM + x) < (other.y*MAX_DIM + other.x)); + return ( (z*MAX_DIM*MAX_DIM + y*MAX_DIM + x) < (other.z*MAX_DIM*MAX_DIM + other.y*MAX_DIM + other.x)); } Point operator/(int number) const { - return Point(x/number, y/number); + return Point(x/number, y/number, z); } Point operator%(int number) const { - return Point(x%number, y%number); + return Point(x%number, y%number, z); + } + Point operator-(int number) const + { + return Point(x,y,z-number); + } + Point operator+(int number) const + { + return Point(x,y,z+number); } uint32_t x; uint32_t y; + uint32_t z; }; class Block { public: - Block(DFHack::Maps *_m, uint32_t x_, uint32_t y_, uint32_t z_) + Block(DFHack::Maps *_m, Point _bcoord) { vector veins; m = _m; dirty = false; valid = false; - x = x_; - y = y_; - z = z_; - if(m->ReadBlock40d(x_,y_,z_,&raw)) + bcoord = _bcoord; + if(m->ReadBlock40d(bcoord.x,bcoord.y,bcoord.z,&raw)) { memset(materials,-1,sizeof(materials)); memset(bitmap,0,sizeof(bitmap)); - m->ReadVeins(x,y,z,&veins); + m->ReadVeins(bcoord.x,bcoord.y,bcoord.z,&veins); // for each vein for(int i = 0; i < (int)veins.size();i++) { @@ -119,36 +133,31 @@ class Block if(dirty) { //printf("writing %d/%d/%d\n",x,y,z); - m->WriteDesignations(x,y,z, &raw.designation); - m->WriteDirtyBit(x,y,z,true); + m->WriteDesignations(bcoord.x,bcoord.y,bcoord.z, &raw.designation); + m->WriteDirtyBit(bcoord.x,bcoord.y,bcoord.z,true); } return true; } - bool valid; - bool dirty; + volatile bool valid; + volatile bool dirty; DFHack::Maps * m; DFHack::mapblock40d raw; - uint32_t x; - uint32_t y; - uint32_t z; + Point bcoord; int16_t materials[16][16]; int8_t bitmap[16][16]; }; -class Layer +class MapCache { public: - Layer(DFHack::Maps * Maps, uint32_t _z) + MapCache(DFHack::Maps * Maps) { valid = 0; this->Maps = Maps; - z = _z; - uint32_t z_max; Maps->getSize(x_bmax, y_bmax, z_max); - if(z < z_max) - valid = true; + valid = true; }; - ~Layer() + ~MapCache() { map::iterator p; for(p = blocks.begin(); p != blocks.end(); p++) @@ -173,9 +182,13 @@ class Layer } else { - Block * nblo = new Block(Maps,blockcoord.x,blockcoord.y,z); - blocks[blockcoord] = nblo; - return nblo; + if(blockcoord.x < x_bmax && blockcoord.y < y_bmax && blockcoord.z < z_max) + { + Block * nblo = new Block(Maps,blockcoord); + blocks[blockcoord] = nblo; + return nblo; + } + return 0; } } @@ -230,6 +243,15 @@ class Layer } return false; } + bool testCoord (Point tilecoord) + { + Block * b= BlockAt(tilecoord / 16); + if(b && b->valid) + { + return true; + } + return false; + } bool WriteAll() { @@ -242,18 +264,31 @@ class Layer return true; } private: - bool valid; - uint32_t z; + volatile bool valid; uint32_t x_bmax; uint32_t y_bmax; uint32_t x_tmax; uint32_t y_tmax; + uint32_t z_max; DFHack::Maps * Maps; map blocks; }; -int main (int argc, const char* argv[]) +int main (int argc, char* argv[]) { + // Command line options + bool updown = false; + argstream as(argc,argv); + + as >>option('x',"updown",updown,"Dig up and down stairs to reach other z-levels.") + >>help(); + + // sane check + if (!as.isOk()) + { + cout << as.errorLog(); + return 1; + } DFHack::API DF("Memory.xml"); try @@ -287,6 +322,9 @@ int main (int argc, const char* argv[]) int32_t cx, cy, cz; Maps->getSize(x_max,y_max,z_max); + uint32_t tx_max = x_max * 16; + uint32_t ty_max = y_max * 16; + Pos->getCursorCoords(cx,cy,cz); while(cx == -30000) { @@ -296,18 +334,27 @@ int main (int argc, const char* argv[]) DF.Suspend(); Pos->getCursorCoords(cx,cy,cz); } + Point xy ((uint32_t)cx,(uint32_t)cy,cz); + if(xy.x == 0 || xy.x == tx_max - 1 || xy.y == 0 || xy.y == ty_max - 1) + { + cerr << "I won't dig the borders. That would be cheating!" << endl; + DF.Detach(); + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + MapCache * MCache = new MapCache(Maps); - Layer * L = new Layer(Maps,cz); - Point xy ((uint32_t)cx,(uint32_t)cy); - DFHack::t_designation des = L->designationAt(xy); - int16_t tt = L->tiletypeAt(xy); - int16_t veinmat = L->materialAt(xy); + DFHack::t_designation des = MCache->designationAt(xy); + int16_t tt = MCache->tiletypeAt(xy); + int16_t veinmat = MCache->materialAt(xy); if( veinmat == -1 ) { cerr << "This tile is non-vein. Bye :)" << endl; - delete L; + delete MCache; DF.Detach(); #ifndef LINUX_BUILD cin.ignore(); @@ -317,56 +364,111 @@ int main (int argc, const char* argv[]) printf("%d/%d/%d tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole); stack flood; flood.push(xy); - uint32_t tx_max = x_max * 16; - uint32_t ty_max = y_max * 16; + while( !flood.empty() ) { Point current = flood.top(); flood.pop(); - int16_t vmat2 = L->materialAt(current); + int16_t vmat2 = MCache->materialAt(current); if(vmat2!=veinmat) continue; // found a good tile, dig+unset material - DFHack::t_designation des = L->designationAt(current); - des.bits.dig = DFHack::designation_default; - if(L->setDesignationAt(current,des)) + + DFHack::t_designation des = MCache->designationAt(current); + DFHack::t_designation des_minus; + DFHack::t_designation des_plus; + des_plus.whole = des_minus.whole = 0; + int16_t vmat_minus = -1; + int16_t vmat_plus = -1; + bool below = 0; + bool above = 0; + if(updown) + { + if(MCache->testCoord(current-1)) + { + below = 1; + des_minus = MCache->designationAt(current-1); + vmat_minus = MCache->materialAt(current-1); + } + + if(MCache->testCoord(current+1)) + { + above = 1; + des_plus = MCache->designationAt(current+1); + vmat_plus = MCache->materialAt(current+1); + } + } + if(MCache->testCoord(current)) { - L->clearMaterialAt(current); - if(current.x < tx_max) + MCache->clearMaterialAt(current); + if(current.x < tx_max - 2) + { + flood.push(Point(current.x + 1, current.y, current.z)); + if(current.y < ty_max - 2) + { + flood.push(Point(current.x + 1, current.y + 1,current.z)); + flood.push(Point(current.x, current.y + 1,current.z)); + } + if(current.y > 1) + { + flood.push(Point(current.x + 1, current.y - 1,current.z)); + flood.push(Point(current.x, current.y - 1,current.z)); + } + } + if(current.x > 1) { - flood.push(Point(current.x + 1, current.y)); - if(current.y < ty_max) + flood.push(Point(current.x - 1, current.y,current.z)); + if(current.y < ty_max - 2) { - flood.push(Point(current.x + 1, current.y + 1)); - flood.push(Point(current.x, current.y + 1)); + flood.push(Point(current.x - 1, current.y + 1,current.z)); + flood.push(Point(current.x, current.y + 1,current.z)); } - if(current.y != 0) + if(current.y > 1) { - flood.push(Point(current.x + 1, current.y - 1)); - flood.push(Point(current.x, current.y - 1)); + flood.push(Point(current.x - 1, current.y - 1,current.z)); + flood.push(Point(current.x, current.y - 1,current.z)); } } - if(current.x != 0) + if(updown) { - flood.push(Point(current.x - 1, current.y)); - if(current.y < ty_max) + if(current.z > 0 && below && vmat_minus == vmat2) { - flood.push(Point(current.x - 1, current.y + 1)); - flood.push(Point(current.x, current.y + 1)); + flood.push(current-1); + + if(des_minus.bits.dig == DFHack::designation_d_stair) + des_minus.bits.dig = DFHack::designation_ud_stair; + else + des_minus.bits.dig = DFHack::designation_u_stair; + MCache->setDesignationAt(current-1,des_minus); + + des.bits.dig = DFHack::designation_d_stair; } - if(current.y != 0) + if(current.z < z_max - 1 && above && vmat_plus == vmat2) { - flood.push(Point(current.x - 1, current.y - 1)); - flood.push(Point(current.x, current.y - 1)); + flood.push(current+ 1); + + if(des_plus.bits.dig == DFHack::designation_u_stair) + des_plus.bits.dig = DFHack::designation_ud_stair; + else + des_plus.bits.dig = DFHack::designation_d_stair; + MCache->setDesignationAt(current+1,des_plus); + + if(des.bits.dig == DFHack::designation_d_stair) + des.bits.dig = DFHack::designation_ud_stair; + else + des.bits.dig = DFHack::designation_u_stair; } } + if(des.bits.dig == DFHack::designation_no) + des.bits.dig = DFHack::designation_default; + MCache->setDesignationAt(current,des); } } - L->WriteAll(); - delete L; + MCache->WriteAll(); + delete MCache; DF.Detach(); #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl;