DFHack / dfhack

Memory hacking library for Dwarf Fortress and a set of tools that use it
Other
1.86k stars 471 forks source link

exportlegends: `art_id` is u16 maximum value #1631

Closed ralpha closed 4 years ago

ralpha commented 4 years ago

While testing I found another value that is incorrect. For a HE with type masterpiece_created_item_improvement there is a field art_id. I think this refers to artifact id, but the value is 65535 with is the maximum value of a unsigned 16bit integer (2^16-1). So I think someone wanted to set this value to -1 but it warped around.

<historical_event>
        <id>68953</id>
        <type>masterpiece_created_item_improvement</type>
        <maker>11112</maker>
        <maker_entity>1411</maker_entity>
        <site>391</site>
        <unk_1>-65524</unk_1>
        <item_type>bar</item_type>
        <item_subtype>-1</item_subtype>
        <mat_type>31</mat_type>
        <mat_index>3127</mat_index>
        <unk_2>1</unk_2>
        <improvement_type>unknown -1</improvement_type>
        <improvement_subtype>0</improvement_subtype>
        <imp_mat_type>29</imp_mat_type>
        <imp_mat_index>-1</imp_mat_index>
        <art_id>65535</art_id>
        <art_subid>0</art_subid>
</historical_event>

I also don't know what art_subid is supposed to be? There are also some unk_1 and unk_2 tags. They are unknown values? unk_1 also looks odd -65524 maybe that should be 65535-65524=11?

improvement_type has a value of unknown -1 maybe better to change it to -1 or unknown?

Related issue: https://gitlab.com/df_storyteller/df-storyteller/-/issues/88

quietust commented 4 years ago

The art_id field does not refer to an artifact, but an art image - specifically, it refers to an art_image_chunk object (loaded from art_image-<ID>.dat), and art_subid serves as an index into that object.

The actual problem is that history_event_masterpiece_created_item_improvementst is misaligned - DFHack thinks the structure size is 0x68 bytes on 64-bit Windows, but it's actually only 0x60 bytes.

Edit: the unk_1 field isn't actually part of this class, but of the parent class history_event_masterpiece_createdst (and its proper name is skill_at_time); due to struct alignment rules, this was pushing all of the other fields down 4-8 bytes.