diff --git a/Memory.xml b/Memory.xml index bb0c78fdd..775eee771 100644 --- a/Memory.xml +++ b/Memory.xml @@ -29,6 +29,9 @@ + + + @@ -782,6 +785,9 @@ + + +
@@ -1068,6 +1074,9 @@ + + +
@@ -1605,6 +1614,9 @@ + + +
@@ -2215,6 +2227,9 @@ + + +
diff --git a/library/ContextShared.cpp b/library/ContextShared.cpp index 0dd099b3c..840acec64 100644 --- a/library/ContextShared.cpp +++ b/library/ContextShared.cpp @@ -35,6 +35,9 @@ bool DFContextShared::InitReadNames() name_firstname_offset = OG->getOffset("first"); name_nickname_offset = OG->getOffset("nick"); name_words_offset = OG->getOffset("second_words"); + name_parts_offset = OG->getOffset("parts_of_speech"); + name_language_offset = OG->getOffset("language"); + name_set_offset = OG->getOffset("has_name"); return true; } @@ -42,5 +45,25 @@ void DFContextShared::readName(t_name & name, uint32_t address) { 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 ,28, (uint8_t *) name.words); + p->read(address + name_words_offset, 7*4, (uint8_t *)name.words); + p->read(address + name_parts_offset, 7*2, (uint8_t *)name.parts_of_speech); + name.language = p->readDWord(address + name_language_offset); + name.has_name = p->readByte(address + name_set_offset); +} + +void DFContextShared::copyName(uint32_t address, uint32_t target) +{ + uint8_t buf[28]; + + if (address == target) + return; + + p->copySTLString(address + name_firstname_offset, target + name_firstname_offset); + p->copySTLString(address + name_nickname_offset, target + name_nickname_offset); + p->read(address + name_words_offset, 7*4, buf); + p->write(target + name_words_offset, 7*4, buf); + p->read(address + name_parts_offset, 7*2, buf); + p->write(target + name_parts_offset, 7*2, buf); + p->writeDWord(target + name_language_offset, p->readDWord(address + name_language_offset)); + p->writeByte(target + name_set_offset, p->readByte(address + name_set_offset)); } diff --git a/library/DFProcess-linux.cpp b/library/DFProcess-linux.cpp index 6d91b162d..ca8d835f4 100644 --- a/library/DFProcess-linux.cpp +++ b/library/DFProcess-linux.cpp @@ -66,6 +66,7 @@ namespace { const std::string readSTLString (uint32_t offset); size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity); void writeSTLString(const uint32_t address, const std::string writeString){}; + void copySTLString(const uint32_t address, const uint32_t target); // get class name of an object with rtti/type info std::string readClassName(uint32_t vptr); }; @@ -161,6 +162,29 @@ const string NormalProcess::readSTLString (uint32_t offset) return ret; } +void NormalProcess::copySTLString (uint32_t offset, uint32_t target) +{ + _Rep_base header; + + offset = Process::readDWord(offset); + uint32_t old_target = Process::readDWord(target); + + if (offset == old_target) + return; + + read(offset - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header); + + // destroying the leaked state + if (header._M_refcount == -1) + header._M_refcount = 1; + else + header._M_refcount++; + + write(offset - sizeof(_Rep_base),sizeof(_Rep_base),(uint8_t *)&header); + + writeDWord(target, offset); +} + string NormalProcess::readClassName (uint32_t vptr) { int typeinfo = Process::readDWord(vptr - 0x4); diff --git a/library/include/dfhack/DFProcess.h b/library/include/dfhack/DFProcess.h index f8c12a22f..12e82ae22 100644 --- a/library/include/dfhack/DFProcess.h +++ b/library/include/dfhack/DFProcess.h @@ -163,6 +163,10 @@ namespace DFHack virtual size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity) = 0; /// write an STL string virtual void writeSTLString(const uint32_t address, const std::string writeString) = 0; + /// share the string at source with target; may leak target + virtual void copySTLString(const uint32_t address, const uint32_t target) { + writeSTLString(target, readSTLString(address)); + } /// read a STL vector virtual void readSTLVector(const uint32_t address, t_vecTriplet & triplet) = 0; /// get class name of an object with rtti/type info diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h index 6a1218dd8..3d0520c40 100644 --- a/library/include/dfhack/modules/Creatures.h +++ b/library/include/dfhack/modules/Creatures.h @@ -341,6 +341,8 @@ namespace DFHack bool WritePos(const uint32_t index, const t_creature &creature); bool WriteCiv(const uint32_t index, const int32_t civ); + void CopyNameTo(t_creature &creature, uint32_t address); + private: struct Private; Private *d; diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index 9e91a1e76..daa31ead9 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -686,3 +686,12 @@ bool Creatures::ReadInventoryPtr(const uint32_t temp, std::vector & it item[i] = p->readDWord(citem[i]); return true; } + +void Creatures::CopyNameTo(t_creature &creature, uint32_t address) +{ + Private::t_offsets &offs = d->creatures; + + if(d->Ft_basic) + d->d->copyName(creature.origin + offs.name_offset, address); +} + diff --git a/library/private/ContextShared.h b/library/private/ContextShared.h index 727bb8a0e..f8b24491e 100644 --- a/library/private/ContextShared.h +++ b/library/private/ContextShared.h @@ -56,11 +56,15 @@ namespace DFHack // names, used by a few other modules. void readName(t_name & name, uint32_t address); + void copyName(uint32_t address, uint32_t target); // get the name offsets bool InitReadNames(); uint32_t name_firstname_offset; uint32_t name_nickname_offset; uint32_t name_words_offset; + uint32_t name_parts_offset; + uint32_t name_language_offset; + uint32_t name_set_offset; bool namesInited; ProcessEnumerator* pm;