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.
develop
Alexander Gavrilov 2011-04-13 20:36:10 +04:00
parent ced036708f
commit ebc4d21e66
7 changed files with 82 additions and 1 deletions

@ -29,6 +29,9 @@
<Offset name="first" description="Lowercase stl string with the first name. For ex. 'urist'" />
<Offset name="nick" description="Stl string with the nickname. Set by the player." />
<Offset name="second_words" description="Array of 7 indexes into the language vectors."/>
<Offset name="parts_of_speech" description="Array of 7 16-bit indexes into the language vectors."/>
<Offset name="language" description="Language of the name."/>
<Offset name="has_name" description="Boolean flag."/>
</Group>
</Offsets>
</Base>
@ -782,6 +785,9 @@
<Offset name="first" description="Lowercase stl string with the first name. For ex. 'urist'" />
<Offset name="nick" description="Stl string with the nickname. Set by the player." />
<Offset name="second_words" description="Array of 7 indexes into the language vectors."/>
<Offset name="parts_of_speech" description="Array of 7 16-bit indexes into the language vectors."/>
<Offset name="language" description="Language of the name."/>
<Offset name="has_name" description="Boolean flag."/>
</Group>
<Group name="Position" description="Offsets used by the Position module.">
<Address name="window_x" description="X coordinate of the current view (DWORD)" />
@ -1068,6 +1074,9 @@
<Offset name="first" value="0x0" />
<Offset name="nick" value="0x1C" />
<Offset name="second_words" value="0x38" />
<Offset name="parts_of_speech" value="0x54" />
<Offset name="language" value="0x64" />
<Offset name="has_name" value="0x68" />
</Group>
<Group name="Position">
<Address name="window_x" value="0xe32798" />
@ -1605,6 +1614,9 @@
<Offset name="first" value="0x0" />
<Offset name="nick" value="0x1C" />
<Offset name="second_words" value="0x38" />
<Offset name="parts_of_speech" value="0x54" />
<Offset name="language" value="0x64" />
<Offset name="has_name" value="0x68" />
</Group>
<Group name="Position">
<Address name="cursor_xyz" value="0xac77f0" />
@ -2215,6 +2227,9 @@
<Offset name="first" value="0x0" />
<Offset name="nick" value="0x4" />
<Offset name="second_words" value="0x8" />
<Offset name="parts_of_speech" value="0x24" />
<Offset name="language" value="0x34" />
<Offset name="has_name" value="0x3a" />
</Group>
<Group name="Position">
<Address name="window_x" value="0x8cc9b38" />

@ -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));
}

@ -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);

@ -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

@ -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;

@ -686,3 +686,12 @@ bool Creatures::ReadInventoryPtr(const uint32_t temp, std::vector<uint32_t> & 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);
}

@ -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;