Saints Row IV (and SRTT) Duplicate & Uneditable tattoo textures?

------WARNING: This post is a real tl;dr, so feel free to skip to the "ACTUAL QUESTION PART"------

Since the tattoo system (as well as a majority of the tattoos) in the game are the same, I hit this issue with both 3 and 4, but am currently only interested in modding SRIV, thus the thread prefix...

In customize_player.vpp_pc are all the tattoo .str2_pc's (as expected), and on extracting, editing, and repacking, and loading the textures inside them, I noticed the same issue (which I think may not be solvable).

There are a few tattoos that appear 2 or 3 times, available on different body areas ("WHEN SAINTS CRY", "CLEAR NIGHT SKY", "HEARTBROKEN", "THE PURPLE FAIRY", "SPIDER BITE", "TWIN SERPENTS", "PURITY", etc.).
Now, that's not surprising; seen it plenty times before, but what's odd, is that for every separate place a duplicate tattoo appears, there actually is a file/texture for each, even though the texture file is 100% the same.
If you extract all the .DDS files from the tattoo .str2_pc's, you'll find a good number of duplicates, but each has their own .str2_pc file.

But here's where the actual "issue" happens...
I've made my own tattoos, am familiar with how their mapped (even have a .psd with most of them mapped exactly how they are in game in their own layers somewhere), yet all I have to do is replace *1* of these .str2_pc files with one that has my texture, and all of the instances of that tattoo are also replaced.
Even stranger, it doesn't seem to matter which instance I replace.

For example, I made a tattoo (specific to the stomach), and used "THE PURPLE FAIRY", because where it was located allowed me to cover the area I wanted to completely, and it wasn't color-customizable.

That tattoo is also available on the forearm, and it's 2 files for each instance are:
Code:
tattoo_Rforarm_5.str2_pc
tattoo_Rforarm_12.str2_pc
I randomly picked Rforarm_5, and as it would in SRTT, when I go to Rusty's Needle, both the stomach and the left forearm instances have been replaced with my texture.

------ACTUAL QUESTION PART------

Since each duplicate tattoo instance has its own texture file, is there any way I could replace one instance and not the other?

If not; why does it not matter which instance I choose to replace? (Just curious)
 
So this gets down into streaming land which is where I spend most of my time. A str2 file is actually a streaming container. We build them for logical things like a vehicle, character, world zone, or tattoo. Internally these things could get loaded into a slot of memory where we don't want to have to worry about memory fragmentation and are willing to eat the duplication. This happens with world zones with level meshes and effects. In that case, even though the mesh might be used in the neighboring zone, that neighboring zone might not be there all the time so we load it anyway. Also, we don't want to have to seek and load thousands of files just to load a single zone, so we bottle them all up into a str2 file. These two things result in the duplication you see.

Now as to the magic of updating a single texture and they all update. I would wager you went with a higher resolution texture for that to happen. Our texture manager is somewhat interesting in how it works. It maintains a list of loaded textures with the same filename. When the renderer wants to render a texture, it will ask the manager for the texture and the manager hands it the highest resolution version of that texture that is loaded. If your texture was the same size as the others, it would depend on load order and fairy dust as to which one was used. The only way to replace one and not the others would be to use a different texture name for that tattoo. You could probably backdoor that with some hackery on the material, but I'm not really sure how the tattoo system works without looking.
 
Wow, that...answers...everything I had...

As for ...
[...]
Now as to the magic of updating a single texture and they all update. I would wager you went with a higher resolution texture for that to happen.
I've made 4 different tattoos, and...(and I can't believe I didn't realize this) they do, in fact, all have higher resolutions from the original. I guess I didn't notice because raising the size of the texture doesn't increase resolution, but rather area coverage (and as a result, only to the right and downward from pixel 1:1)...

My "TWIN SERPENTS" (512 x 256) was upped to 512 x 480,
my "HEARTBROKEN" (256 x 128) was upped to 280 x 288,
my "PURPLE FAIRY" (256 x 256) was upped 320 x 288,
and even my (still-in-testing) "BLACK SWAN" (1024 x 128) was upped to 1024 x 256...

[...]
Our texture manager is somewhat interesting in how it works. It maintains a list of loaded textures with the same filename. When the renderer wants to render a texture, it will ask the manager for the texture and the manager hands it the highest resolution version of that texture that is loaded. If your texture was the same size as the others, it would depend on load order and fairy dust as to which one was used. The only way to replace one and not the others would be to use a different texture name for that tattoo. You could probably backdoor that with some hackery on the material, but I'm not really sure how the tattoo system works without looking.

As for this (and this may not need to be answered, can be checked by simply trying it on my end, just need to stop playing it for long enough): If both instances are replaced by a texture of higher resolution, both textures having the exact same resolutions, but having different textures, would the game then load them each? Or would it prioritize one over the other based on something other than resolution (like file size)?

Either way, thanks, really really appreciate it.
 
As for this (and this may not need to be answered, can be checked by simply trying it on my end, just need to stop playing it for long enough): If both instances are replaced by a texture of higher resolution, both textures having the exact same resolutions, but having different textures, would the game then load them each? Or would it prioritize one over the other based on something other than resolution (like file size)?
The game sees a texture file as exactly the same as another if it has the same filename. So in your case, it would load one of them. The higher res version would be used, but if they're both the same resolution, it would probably pick the first one loaded as the one to display. I would try to rename one, but that might be a little tricky depending on where it is referenced. Should be doable though.
 
[...]
I would try to rename one, but that might be a little tricky depending on where it is referenced. Should be doable though.

Well, I tried changing a name by doing this, and the game froze on loading a save:

Files used:
tattoo_Rforarm_12.str2_pc
customization_compositing.xtbl



1. Extracted tattoo_Rforarm_12.str2_pc
Contents of tattoo_Rforarm_12.str2_pc said:
tat_arm_fair.cvbm_pc
tat_arm_fair.gvbm_pc
2. Extracted .cvbm/.gvbm to get tat_arm_fair.tga.DDS file.
---EDITED .DDS FILE...---
3. Renamed all 3 files, replacing "fair" with "swam"
4. Opened up (newly renamed) tat_arm_swam.cvbm_pc with hex editor, updating the values for the texture name to read the new "swam" name, not the original "fair" name, thus not changing filename's length of ASCII characters (just to be safe).
5. Repacked .DDS in to .cvbm/.gvbm (without issue; size updated to match that of DDS', signifying success)
6. Repacked newly updated .cvbm/.gvbm back in to tattoo_Rforarm_12.str2_pc (had to be done without GUI version of Minimaul's SRIV Packfile tool, which would freeze/crash)
7. Placed .str2_pc file in game root, like always

8. Edited customization_compositing.xtbl (line 6634) in the <Filename> tag to have the new name change ("swam" over "fair")
9. Saved .xtbl to game root (again, like always, though I've never used an .xtbl with a tattoo before; only found it with "search in files" command of Notepad++ for the text "tattoo_Rforarm_12" when I extracted all of misc_tables.vpp_pc)

10. Ran Mini's rev-17 Stream2Update to update all .asm_pc's (not sure if necessary, but never a bad idea)

...Game freeze/crash on loading a save (mid-audio log recital that accompanies loading a save).

It must also be reference somewhere else, I guess. Couldn't find anything in trying to hex edit the .gvbm, or anything of note in any other file inside misc_tables.vpp_pc.


If anyone who isn't -V- staff wants to throw in their two cents, I'll take any help I can get!

Thanks for the help. Also was glad to find in customization_compositing.xtbl actual coordinates to where each tattoo is placed on the body's diffuse map! HUGE time-saver.
 
I'm not sure if minimaul's str2 editor will allow creation of a new file like this. Can you do the extract as xml, rename and repackage that way? I'm not even sure if this is available yet on the SR4 community tools.
 
I'm not sure if minimaul's str2 editor will allow creation of a new file like this. Can you do the extract as xml, rename and repackage that way? I'm not even sure if this is available yet on the SR4 community tools.
I remember when using the SRTT tools (made by Rick/Gibbed), it would always spit out a @streams.xml file along with the .cvbm and .gvbm, but since the new SRIV tools by Minimaul (I believe largely based from Rick's initial work), that file hasn't come with them, but it also has command line options that may allow that.

As far as "Can you do the extract as xml, rename and repackage that way?", if you mean the entire extraction, then I really don't know. I'll ask Mini to take a look at our discussion, maybe even Rick, to see if that can be done.

Closest thing I hit to that in the past was Rick's SRTT, as detailed below:

In SRTT I was using the same texture I had made, but replaced the ROBOTO-SAN lower chest tattoo, and it would come with this:
ROBOTO-SAN's (SRTT) @streams.xml file said:
<?xml version="1.0" encoding="utf-8"?>
<streams endian="Little" compressed="True" condensed="True">

<entry name="tat_stomach_robot.cvbm_pc">tat_stomach_robot.cvbm_pc</entry>
<entry
name="tat_stomach_robot.gvbm_pc">tat_stomach_robot.gvbm_pc</entry>
</streams>
But that appears to just be an index, and if you mean the entire extraction in XML, then, well, no, that's not it.

Again, I'll ask Minimaul & Rick to take a look if I can catch them.
Thanks again.
 
Ultimately, you need to replace the file in the str2 with a new file. Most of the tools seem to be extract, edit, pack which is the problem here. Since the tools didn't know most of the flags and things, they would just leave them alone and update the filesize. Creating entirely new str2 files was pretty much out back then. I haven't gotten to the point where I can release SR4 tools yet, but you could potentially do some hacky things to get around it.

  • hex edit the filename in the str2/asm before you extract it to play the extract, update repackage game
  • use vpkg in the SR3 tools to build your str2/asm, extract it and repackage with SR4 tools somehow
  • take your existing str2 package with the original filenames and hex edit the str2/asm to change the filename
 
Ultimately, you need to replace the file in the str2 with a new file. Most of the tools seem to be extract, edit, pack which is the problem here. Since the tools didn't know most of the flags and things, they would just leave them alone and update the filesize. Creating entirely new str2 files was pretty much out back then. I haven't gotten to the point where I can release SR4 tools yet, but you could potentially do some hacky things to get around it.

  • hex edit the filename in the str2/asm before you extract it to play the extract, update repackage game
  • use vpkg in the SR3 tools to build your str2/asm, extract it and repackage with SR4 tools somehow
  • take your existing str2 package with the original filenames and hex edit the str2/asm to change the filename
Awesome! Will do. Then I'll report back with my results.

Thanks again for the help so far, really appreciate it.
 
It worked! I can't believe it!

Here's the steps I took to get this working for anyone who is wondering, though outside of custom tattoo duplicates, I don't see how this will be too useful. >_<

Files I used said:
tattoo_Rforarm_12.str2_pc
customize_player.asm_pc
customization_compositing.xtbl

#1. Hex edit .str2_pc file to change the name of both the .cvbm_pc and .gvbm_pc file, without adding/inserting new characters (try to keep it the same length as vanilla).

#2. Extract newly edited .str2_pc file.

#3. Open up resulting .cvbm_pc file in hex editor, and change the name of the .tga file accordingly.

#4. Unpack .cvbm_pc file (using Scanti's texture utilities for SRTT) to get a .DDS file.

--EDIT .DDS FILE--

#5. Repack .cvbm_pc (again using Scanti's texture utilities).

#6. Repack .str2_pc file

#7. Open up relevant .asm_pc file in hex editor (in my case, customize_player.asm_pc), find the old texture name (since mine is a duplicate, the 2nd instance was the one I wanted; it was immediately after the .str2_pc's name), edit it accordingly. Save.

#8. Open up relevant .xtbl (for me, customization_compositing.xtbl), find correct reference, edit accordingly. Save.

#9. Put all in game directory. Done!

I've attached a .7z with the exact files I'm using in my game directory, so feel free to pick 'em apart to see what I did, and consider the tattoo a pre-release (not to be distributed anywhere else other than this post in this thread on this forum). It replaces the "PURPLE FAIRY" lower chest tattoo, but not the one for the right lower arm! :D

Though, if you are running a mod that uses customize_player.asm_pc (many do), you'll have to hex edit the one (AFTER you back it up!) you're using and locate the 2nd instance of the text "tat_arm_fair" (should be after the text "tattoo_Rforarm_12"), and replace the letters "fair" with "swam", so it matches the texture. Otherwise, either you'll crash on load, or the tattoo will be invisible.

Can't thank you enough for guiding me, Mike, really appreciate it.
 

Attachments

  • it_worked!.7z
    23.6 KB · Views: 494
Back
Top