I haven't seen a thread related to posting findings on the RPF7 file format, so I thought I would post some findings.
RPF7 (Rage Package Format) File Containter
This is a file container for various items in the game. It contains script files, images, textures, and other essential assets to the game.
File Structure
Code: Select all
typedef struct
{
u32 version; //2FPR or 3FPR
u32 tableSize;
u32 entryCount;
u32 unk;
u32 tab32 encryptedFlag; //encrypted with AES if > 0
} header_t;
typedef struct
{
u32 nameOffset;
u32 dirFlags;
u32 entryIndex;
u32 entryCount;
} directory_t;
typedef struct
{
u32 nameOffset;
u32 dataSize;
u24 dataOffset;
u8 resourceType;
u32 flags; //first bit tells if compressed or not.
} entry_t;
enum resourceType : u8
{
XenonTextDict = 7,
WinTextDict = 8,
ScriptContainer = 9,
Particles_0 = 27,
Bounds = 32,
Particles_1 = 36,
XenonModel = 109,
WinModel = 110,
WinModelFlag = 112
}
Here is one of the assets contained in the RPF File Container.
.sc (Script Container) - Contains scripts to be used in the virtual machine
Script containers are used in the game as compiled code to be ran by the Virtual Machine.
Currently there are two extensions for script containers. XSC (Xenon -xbox) and CSC (Cell -ps3).
Structure
Code: Select all
define CODEPAGEMAX 0x4000
#define Offset( n ) (u32)((n & 0xFFFFFF) + 0x10) //removes first 8 bits which happen to be 0x50
#define PageCount( n ) (u32)(( n + 0x3FFF) >> 0xE)
typedef struct
{
u32 magic; //RSC7
u32 resourceType;
u32 systemFlag;
u32 graphicsFlag; //0x90000000
} header_t; //0x10
typedef struct
{
u32 magic;
u32 unk_t_Offset; //see below
u32 programOffset;
u32 programHash;
u32 programLength;
u32 paramsCount;
u32 staticsCount;
u32 globalsCount;
u32 nativesCount;
u32 staticsOffset;
u32 globalsOffset;
u32 nativesOffset;
u32 unk1; //could be an offset
u32 unk2; //could be an offset
u32 nameHash;
u32 unk3; //looks like a count
u32 scriptNameOffset;
u32 stringPagesOffset;
u32 stringPagesSize;
u32 reserved;
} dataInfo_t; //0x50
typedef struct{
header_t header;
dataInfo_t dataInfo;
} scriptContainer_t; //0x60
NOTE: Some rsc containers are encrypted, in which case use the follow AES key.:
XBOX:
Code: Select all
unsigned char key[0x20] = {
0xa1, 0xe7, 0x29, 0x39, 0x5d, 0x8a, 0xd1, 0x0b, 0x9b, 0x7b, 0xd0, 0x11, 0xd5, 0x28, 0x69, 0x3d,
0x96, 0xe2, 0x2b, 0xd6, 0xa2, 0x8a, 0xab, 0xae, 0xb4, 0xa6, 0x9a, 0xc6, 0xf9, 0x73, 0x62, 0x7f
};
PS3:
Code: Select all
unsigned char key[0x20] = {
0x85, 0x13, 0x6E, 0x1E, 0x37, 0xFC, 0xBC, 0x45, 0x94, 0xE7, 0xF7, 0xBC, 0x5F, 0x18, 0x52, 0x00,
0xB3, 0x2A, 0x67, 0x30, 0x8C, 0xC1, 0xB8, 0x33, 0xB3, 0x2A, 0x67, 0x30, 0x8C, 0xC1, 0xB8, 0x33
};
Offsets need first 8 bits stripped off of them to display current offset (from address of dataInfo_t start), page counts need to be found by adding the codepagemax - 1 to the offset and rshfting it 14 bits.
unk_t_Offset is an offset to a structure which seem to be like this:
Code: Select all
typedef struct {
u32 unk;
u32 count; //little endian
u32 unk1
u32 unkValues[count]; //not valid syntax, but you get the idea.
} unk_t;
You can get page lengths of data (string/code) with the following function.
Code: Select all
unsigned int GetPageLenAtPage(int pgs, int totalLen, int pg) {
return (pg == pgs) ? (totalLen % CODEPAGEMAX) : CODEPAGEMAX;
}
Structure Info
1 - Natives are a bunch of u32 hashes (jenkins hash algo) of native function names in the executable.
2 - String Pages contain a list of cstrings that the script uses to display text.
3 - Script Name is the name of the Script Container
4 - Code Pages are the set of compiled data. It Contains OP Codes to tell the Virtual Machine which operation to do. This means it's low level operations.
I would like to thank Jakes625 for all his time and research. I would also like to thank Good_NTS (creator of OpenIV) for answering questions I had.