morkt / GARbro

Visual Novels resource browser
MIT License
2.3k stars 244 forks source link

YPF implementation doesn't work for some YU-RIS versions #452

Open Xorboth opened 3 years ago

Xorboth commented 3 years ago

I'm trying to study the YPF file format, so I looked for every tool available on GitHub. Among them, this was the best I found, since it's complete and does more controls than others. I noticed a few cases where this tool doesn't work, so I investigated to understand what was wrong.

Apparently, some YPF versions use 64 bit (8 bytes) for the offsets, but this isn't really a problem since you can just change UInt32 to UInt64 and change the number of bytes read for it. When the game uses 32 bit offsets, all is fine and this tool works fine. But when there are 64 bits offsets, name_checksum and data_crc are wrong. I'm not sure what the game is actually doing, but apparently the game isn't using CRC32 for name_checksum and Adler32 for data_crc. I'm not sure if these are somehow crypted or the game is just using some other algorithms.

I hope someone can help me to understand better what is happening.

The games I tested:

Trap Shrine (Fakku Uncensored Version / ENG) YPF Version: 474 Offset Bits: 32 Everything is working fine and name_crc and data_crc are correctly calculated.

Trap Shrine (Steam Censored Version / JP-ENG) YPF Version: 479 Offset Bits: 64 name_crc and data_crc are giving different results than the ones in the YPF header.

Fraternite HD (JP) YPF Version: 490 Offset Bits: 64 name_crc and data_crc are giving different results than the ones in the YPF header.

Euphoria HD (JP) YPF Version: 474 Offset Bits: 32 Everything is working fine and name_crc and data_crc are correctly calculated.

Euphoria (ENG) YPF Version: 474 Offset Bits: 32 Everything is working fine and name_crc and data_crc are correctly calculated.

Trap Shrine was an interesting case because the game has two different versions released at the same time, but use different versions of the YU-RIS engine. I manually checked the data_crc and name_crc between the two versions for a few assets that are the same, but for some unknown reason have different check values. This is the main reason I'm thinking the game is using different algorithms or is somehow crypting these values.

Example: Trap Shrine (Steam) | test.png | data_crc = 11 | name_crc = 22 Trap Shrine (Fakku) | test.png | data_crc = 55 | name_crc = 88 test.png is the same and wasn't even compressed in the YPF file. (data_crc and name_crc values are just indicative to let you understand what I meant, they are not real values)

imKota commented 3 years ago

Hi @Xorboth you can try this https://github.com/fengberd/YuRISTools

Xorboth commented 3 years ago

Hi @Xorboth you can try this https://github.com/fengberd/YuRISTools

THANK YOU! It's exactly what I was looking for, I feel very stupid because I thought I checked every projects on GitHub, but for some unknown reason I did not find it on Google.

The solution to the problem above is pretty simple: the game is using different algorithms than CRC32 / Adler32 as I thought. After analyzing the YuRISTools source code, I find out that the game is using Murmur2, here you can find the implementation: https://github.com/fengberd/YuRISTools/blob/fec7ad0659150aee04597219d3d4dbf2465f830b/YuRISLib/CheckSum.cs#L123 The game is using Murmur2 for name_crc and data_crc.

Now I can complete the tool I was developing for myself. I started to work on it because I wanted to test my programming skills, and wanted to create an injector. If I want to change some textures, extraction and recompression requires time, since it's heavily I/O bound, so I thought that I could just copy the header & files into a new YPF, just replacing the few files I needed.

Xorboth commented 3 years ago

Woops, I accidentally closed it, even though I find out the algorithm, this tool still doesn't support it, so I hope the devs will update it.