Jump to content

[Android] My Talking Tom 2 root.assets file (Not Unity)


Recommended Posts

  • 4 weeks later...

I think it is unity. If you are still using assetstudiogui, and it's not loading, you will have to specify the unity version it uses. Right click on the asset file, and open it in either a hex editor or notepad. Find the strong that relates to the unity version. Copy that, then in assetstudiogui, go to option > specify unity version, then paste it and load the file

Link to comment
Share on other sites

  • 4 weeks later...
On 12/2/2024 at 4:36 PM, scratchcat579 said:

the asset metadata is in root.project. it is zstandard chunk compressed and the decompressed data contains bundle source names, guids, project file names and compiled paths 

Goddamn it. It totally is just zsd compressed. I have also been reversing the files and hit a wall with the root.project file specifically. All the files I have start with O7PR and I thought that was a file signature that meant "Outfit 7 project" and maybe it does, but after reading this post, I just tried running 7zip on it and it worked 😩

Link to comment
Share on other sites

I'm not sure if you're want help with the newer version of the root.assets and root.bundle files, but the older(?) version from 2023 has a fairly straightforward structure:

The file in in little-endian order
 

u32 uncompressed_length
u32 compressed_length
u64 hash(?)
compressed_length bytes of data

the file is compressed in 64-kilobyte blocks (0xFFFF or 65535 bytes). If uncompressed_length == compressed_length, then the block is uncompressed.

If uncompressed_length is exactly 65535 bytes, then concatenate the next uncompressed block onto this uncompressed block. Continue concatenating until you get a block that is less than 65535 bytes. The compression used on the blocks is zstd.

The reason I've marked the 64-bit value as a hash is because blocks that have the same contents have the same hash. Also all bits of the value occur at about 50% frequency. (i.e. for 10000 data blocks, every bit of the hash value is 1 about 5000 times). I have not been able to figure out what the hashing function is.

I have managed to reverse engineer the native binary enough that it definitely uses XXHash for hashing some string snippets (snippets like "Instant" "Animate" "_PatternColor" "_LiquidColor0"), but I don't understand what they are used for. Maybe for the meta data/file paths?

My file concatenation process might not be flawless because some of the png files i have managed to extract have been corrupt. But only a few files have been corrupt, the vast majority of files come out fine. Sometimes the uncompressed files have "extra" data, but chopping off 4 or 8 bytes usually fixes them. After looking at the code at https://github.com/nj-josh-man/Moonlite I was inspired to do the same thing it does where I just check for known file signatures at various offsets and if I find something, lop off the preceding bytes. Seems to work fine.

I have found pngs, jpegs and ktx files in the data and from some file listings I have been able to assign some textures to the extracted data blocks. Since the textures are in the same order as the file names, I have also been able to find meshes, but I haven't figured out their format.

As for the textures, anything with _MASK01 seems to have the following format:

Alpha channel is the general visibility/base color mask of the texture. Red channel is the secondary/accent color mask.

So for example if your primary color is pink and secondary color is sky blue: If A = 1, show pink, but if R is also 1, show sky blue.

Green channel is shadow/AO and blue channel is highlight. None of the channels are restricted to binary 0/1 and in fact gradients are very common, as is translucency.

_MASK02 files seem to just have some extra masks for extra accent colors.

Link to comment
Share on other sites

3 hours ago, yarcunham said:

I have also been able to find meshes, but I haven't figured out their format.

Well, now that I found hex2obj and Model Researcher, I was able to figure out some of the format at least for static meshes (files ending in _MESH, as opposed to _SKINNEDMESH for example)

Before finding the above tools, I was already able to find the face definitions from the file (3 * vertex index). I was also able to get the number of vertices. I was able to independently verify that both the vertex and face counts were correct from a model rip someone had already made. But I was unable to figure out the format of the vertex data. I could see that the per-vertex data was 16 bytes, because that fit the file, but the format and order was a mystery. I figured there would be at least x,y,z coordinates and uv-coordinates. I figured that it wouldn't have normals, because those can be calculated. Turns out I was wrong.

With model researcher I was able to figure out that the vertex data is X,Y,Z; nX,nY,nZ; U,V and the data type is signed short.

Like, the data length makes sense, that's 16 bytes, but I had tried fitting half floats on there without success.

The model isn't perfect coming out of the Model Researcher conversion process. The geometry seems to be fine, but the UV map seems to have a slightly wrong scale, it's a little bit stretched on the Y axis. Scaling it down to .9 almost fixes it.

Maybe there is a global scaling factor hiding in the file?

man... "signed short"

Link to comment
Share on other sites

9 hours ago, testing4562145 said:

i can't use moonlite because of some frame descriptor error, i tried command line and drag and dropping

I can't help with running it unfortunately. I only read its source code for ideas.

Link to comment
Share on other sites

On 12/31/2024 at 4:13 PM, yarcunham said:

The model isn't perfect coming out of the Model Researcher conversion process. The geometry seems to be fine, but the UV map seems to have a slightly wrong scale, it's a little bit stretched on the Y axis. Scaling it down to .9 almost fixes it.

Maybe there is a global scaling factor hiding in the file?

I think this is Model researcher's doing. It seems to stretch the uv values it finds so that the largest value both on the U and V axis is equal to 1.0. when you define UVs in "short" format. I suppose it's a default value because it can't really know how the uv values it reads are scaled.

Seems like in Starlite's case the (short) UV values have to be divided by 2**15 (or 32768).

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...