Difference between revisions of "YPF"

From Game Research Wiki
Jump to navigation Jump to search
Line 41: Line 41:


==Comments==
==Comments==
Index data may be protected.
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.
<syntaxhighlight lang="cpp">
unsigned char test[0xFF],
eax, ecx, edx;


XOR by FF then XOR by 40 may work.
for (int a = 0; a < 255; a++)
{
test[a] = a;
}
 
edx = test[0x09];
eax = test[0x0B];
test[0x09] = eax;
test[0x0B] = edx;
eax = test[0x0C];
ecx = test[0x10];
test[0x0C] = ecx;
test[0x10] = eax;
edx = test[0x0D];
eax = test[0x13];
test[0x0D] = eax;
test[0x13] = edx;
edx = test[0x11];
eax = test[0x19];
test[0x11] = eax;
test[0x19] = edx;
edx = test[0x15];
eax = test[0x1B];
test[0x15] = eax;
test[0x1B] = edx;
edx = test[0x1C];
eax = test[0x1E];
test[0x1C] = eax;
test[0x1E] = edx;
edx = test[0x20];
eax = test[0x23];
test[0x20] = eax;
test[0x23] = edx;
edx = test[0x26];
eax = test[0x29];
test[0x26] = eax;
test[0x29] = edx;
edx = test[0x2C];
eax = test[0x0F];
test[0x2C] = eax;
test[0x2F] = edx;
edx = test[0x2E];
eax = test[0x32];
</syntaxhighlight>
 
Example: 0xEC ^ 0xFF = 0x13
Table lookup 0x13 -> 0x0D
Which means the filename length is 13.

Revision as of 05:30, 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.

unsigned char test[0xFF],
	eax, ecx, edx;

for (int a = 0; a < 255; a++)
{
	test[a] = a;
}

edx = test[0x09];
eax = test[0x0B];
test[0x09] = eax;
test[0x0B] = edx;
eax = test[0x0C];
ecx = test[0x10];
test[0x0C] = ecx;
test[0x10] = eax;
edx = test[0x0D];
eax = test[0x13];
test[0x0D] = eax;
test[0x13] = edx;
edx = test[0x11];
eax = test[0x19];
test[0x11] = eax;
test[0x19] = edx;
edx = test[0x15];
eax = test[0x1B];
test[0x15] = eax;
test[0x1B] = edx;
edx = test[0x1C];
eax = test[0x1E];
test[0x1C] = eax;
test[0x1E] = edx;
edx = test[0x20];
eax = test[0x23];
test[0x20] = eax;
test[0x23] = edx;
edx = test[0x26];
eax = test[0x29];
test[0x26] = eax;
test[0x29] = edx;
edx = test[0x2C];
eax = test[0x0F];
test[0x2C] = eax;
test[0x2F] = edx;
edx = test[0x2E];
eax = test[0x32];

Example: 0xEC ^ 0xFF = 0x13 Table lookup 0x13 -> 0x0D Which means the filename length is 13.