YPF
Jump to navigation
Jump to search
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 (see below). | ||||||||||||
?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 a number of values.
char lookup(char incoming)
{
switch (incoming)
{
case 0x09:
return 0x0B;
case 0x0B:
return 0x09;
case 0x0C:
return 0x10;
case 0x0D:
return 0x13;
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 0x2E:
return 0x32;
case 0x2F:
return 0x2C;
case 0x32:
return 0x2E;
default:
return incoming;
}
}
ToDo: Figure out what the unknown values are for repacking function.