From ebc4d21e661651c42d9bbc4ba5ae8d2fb9c33b78 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Wed, 13 Apr 2011 20:36:10 +0400 Subject: [PATCH] Improve name structure handling, and support duplicating them (on linux). The name structure actually contains additional linguistical data, ignoring which produces wrong renderings for non-dwarfish names. This data also obviously has to be copied with the structure. Copying STL strings works by replicating the shared copy logic (i.e. incrementing the reference counter), but leaks memory owned by the string being overwritten. --- Memory.xml | 15 +++++++++++++ library/ContextShared.cpp | 25 +++++++++++++++++++++- library/DFProcess-linux.cpp | 24 +++++++++++++++++++++ library/include/dfhack/DFProcess.h | 4 ++++ library/include/dfhack/modules/Creatures.h | 2 ++ library/modules/Creatures.cpp | 9 ++++++++ library/private/ContextShared.h | 4 ++++ 7 files changed, 82 insertions(+), 1 deletion(-) 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;