YPF: Difference between revisions
No edit summary |
|||
Line 44: | Line 44: | ||
The table is generated at runtime and swaps around 38 values in the table. | The table is generated at runtime and swaps around 38 values in the table. | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
char lookup(char incoming) | |||
{ | { | ||
switch (incoming) | |||
{ | |||
case 0x09: | |||
return 0x0B; | |||
case 0x0B: | |||
return 0x09; | |||
case 0x0C: | |||
return 0x10; | |||
case 0x10: | |||
return 0x0C; | |||
case 0x11: | |||
return 0x19; | |||
case 0x13: | |||
return 0x0D; | |||
case 0x15: | |||
return 0x1B; | |||
case 0x19: | |||
return 0x11; | |||
case 0x1b: | |||
return 0x15; | |||
case 0x1C: | |||
return 0x1E; | |||
case 0x1E: | |||
return 0x1C; | |||
case 0x20: | |||
return 0x23; | |||
case 0x23: | |||
return 0x20; | |||
case 0x26: | |||
return 0x29; | |||
case 0x29: | |||
return 0x26; | |||
case 0x2C: | |||
return 0x2F; | |||
case 0x2F: | |||
return 0x2C; | |||
default: | |||
return incoming; | |||
} | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Revision as of 06:04, 16 March 2015
Used in the following games:
- Eroge! ~Sex and Games Make Sexy Games~
Structure
Header | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Size | Content | Description | ||||||||||||
4Bytes | Magic/ID | "YPF/0" | ||||||||||||
4Bytes | Unknown1 | Static? | ||||||||||||
4Bytes | File Count | Number of Files in archive | ||||||||||||
4Bytes | Index Size | Size of Index | ||||||||||||
16Bytes | Padding | |||||||||||||
Index Entry | ||||||||||||||
Size | Content | Description | ||||||||||||
4Bytes | Unknown1 | |||||||||||||
1Bytes | Filename Length | XOR 0xFF, then table lookup. | ||||||||||||
?Bytes | Filename | XOR 0xFF then XOR 0x40 | ||||||||||||
2Bytes | Unknown2 | Static? | ||||||||||||
4Bytes | FileSize1 | |||||||||||||
4Bytes | FileSize2 | Suggests compression is supported | ||||||||||||
4Bytes | File Offset | |||||||||||||
4Bytes | Unknown3 |
Comments
To decode the filenames, each byte in the filename is XOR by 0xFF and then 0x40. However, the filenames are not null terminated so 1 byte is stored before the filename that represents the the filename's length. This value is protected like the filename but is slightly different (as far as I can tell). XOR by 0xFF and then do a table lookup. The table is generated at runtime and swaps around 38 values in the table.
char lookup(char incoming)
{
switch (incoming)
{
case 0x09:
return 0x0B;
case 0x0B:
return 0x09;
case 0x0C:
return 0x10;
case 0x10:
return 0x0C;
case 0x11:
return 0x19;
case 0x13:
return 0x0D;
case 0x15:
return 0x1B;
case 0x19:
return 0x11;
case 0x1b:
return 0x15;
case 0x1C:
return 0x1E;
case 0x1E:
return 0x1C;
case 0x20:
return 0x23;
case 0x23:
return 0x20;
case 0x26:
return 0x29;
case 0x29:
return 0x26;
case 0x2C:
return 0x2F;
case 0x2F:
return 0x2C;
default:
return incoming;
}
}
Example: 0xEC ^ 0xFF = 0x13 Table lookup 0x13 -> 0x0D Which means the filename length is 13.
Nothing else appears protected (file sizes and offset) however there is still a few unknown values that will need to be researched if a packing tool is to be made.
Not the most optimized method and I could still be overlooking something or not realizing something important... oh well. It works, right? ^^;