CXML Containers
Description
.QRC, .P3T, and .RAF (in order of complexity from easier to harder) and .CXML file extensions uses the same container, and are able to use zlib compression, but the zlib compression method and the structure of the container has several variations:
The only way to identify accurate the exact container type is by reading the texts in the "strings table" (are tags and some of his values from the .xml file that was used to build the container) that are related with the building process and defines his internal structure, but their names are too long to use when talking about them
- For QRC there are 2 basic variations: (both of them uses zlib compression, and only contains a "file-table" with "files")
- QRCC - (used by all .qrc files except icontex.qrc) - zlib compression is applied over the whole .qrc file (except his first 8 bytes that are info for the decompression), after decompression the file generated is a QRCF and the internal container structure can be readed (QRCC always contains a QRCF that is the real container)
- QRCF - (used only by icontex.qrc) - zlib compression is applied per-file over each contained file (the container structure can be read directly and every one of the files inside the container structure is compressed individually)
- For this reason is not possible to identify the 2 variations of QRC by reading his magic (both are QRCF) but his structure is different, so is needed to use unofficial names to identify them and to be able to explain his variations here in wiki, the proposed names used in this page are:
- QRCF_1 (the most common and older... used by all .qrc's except icontext.qrc)
- QRCF_2 (the less common and newer... used only by icontex.qrc)
- For P3T there are lot of posible variations:
- The internal structure is dependant of the items included in the theme... some of them can be icons (to be stored inside an icontable) and others can be a wallpaper, the mouse pointers (stored in a pointertable), navigation sounds (stored in a se table), etc...
- Is possible to create themes with the official theme compiler tool with all this items, or only a few of them (e.g: a theme containing only 1 icon... or a theme containing only the name of the theme), this frankenstein themes are really useful for understanding the structure as you can see in this examples ---> https://www.sendspace.com/file/5suokd
- For RAF seems is posible a lot of variations too
- RAF's are used for the animation scene inside dynamic themes, when using them this way it seems the contents is restricted to a list of contained files, but raf is also used in the animation when PS3 boots (coldboot.raf) and although his format is pretty similar than the background of a theme is possible to include multiple files of different types inside the container
All this variations are confusing and hard to explain in the page, but is needed to find a way to represent them as the basic layouts that the firmware expects to find inside the container
Container Structure
XML implicit structure Overview
namespace cxml
{
struct Header { /*header of a cxml document*/
char magic[4];
int version;
int tree_offset;
int tree_size;
int idtable_offset;
int idtable_size;
int stringtable_offset;
int stringtable_size;
int intarraytable_offset;
int intarraytable_size;
int floatarraytable_offset;
int floatarraytable_size;
int filetable_offset;
int filetable_size;
};
struct ChildElementBin
{
int name;
int attr_num;
int parent;
int prev;
int next;
int first_child;
int last_child;
};
struct BrotherElementBin
{
int name;
int attr_num;
int parent;
int prev;
int next;
};
struct AttributeBin
{
int INTEGER = 1;
int FLOAT = 2;
int STRING = 3;
int INTEGER_ARRAY = 4;
int FLOAT_ARRAY = 5;
int DATA = 6;
int ID_REF = 7;
int ID_NO_REF = 8;
int name;
int type;
struct StringData
{
int offset;
int len;
};
struct IntArrayData
{
int offset;
int num;
};
struct FloatArrayData
{
int offset;
int num;
};
struct FileData
{
int offset;
int size;
};
union
{
int i;
float f;
StringData s;
IntArrayData ia;
FloatArrayData fa;
FileData file;
int id;
int idref;
};
};
struct IDBin
{
int entity_offset;
char id[0];
};
enum AllocationType
{
AllocationType_Alloc_Tree,
AllocationType_Alloc_IDTable,
AllocationType_Alloc_StringTable,
AllocationType_Alloc_IntArrayTable,
AllocationType_Alloc_FloatArrayTable,
AllocationType_Alloc_FileTable,
AllocationType_Free_Tree,
AllocationType_Free_IDTable,
AllocationType_Free_StringTable,
AllocationType_Free_IntArrayTable,
AllocationType_Free_FloatArrayTable,
AllocationType_Free_FileTable,
};
enum AccessMode
{
AccessMode_ReadWrite,
AccessMode_ReadOnly_File,
AccessMode_ReadOnly_Memory,
};
class Document {
public:
typedef void (*Allocator)( AllocationType type, void * userdata, void * old_addr, unsigned int required_size, void ** addr, unsigned int * size );
private:
AccessMode access_mode;
Header header;
char * tree;
unsigned int tree_capacity;
char * idtable;
unsigned int idtable_capacity;
char * stringtable;
unsigned int stringtable_capacity;
int * intarraytable;
unsigned int intarraytable_capacity;
float * floatarraytable;
unsigned int floatarraytable_capacity;
char * filetable;
unsigned int filetable_capacity;
Allocator allocator;
void * allocator_userdata;
};
class Element {
private:
Document * doc;
int offset;
};
class Attribute {
private:
Document * doc;
int element_offset;
int offset;
};
};
Element
Offset | Length | usage |
---|---|---|
0x00 | 0x04 | Element name relative offset in TAGS Table |
0x04 | 0x04 | Number of attributes in TOC |
0x08 | 0x04 | Parent relative offset in TOC |
0x0C | 0x04 | Previous Brother relative offset in TOC |
0x10 | 0x04 | Next Brother relative offset in TOC |
0x14 | 0x04 | First Child relative offset in TOC |
0x18 | 0x04 | Last Child relative offset in TOC |
Offset | Length | usage |
---|---|---|
0x00 | 0x04 | Element name relative offset in TAGS Table |
0x04 | 0x04 | Number of attributes in TOC |
0x08 | 0x04 | Parent relative offset in TOC |
0x1C | 0x04 | Previous Brother relative offset in TOC |
0x10 | 0x04 | Next Brother relative offset in TOC |
- NOTE: The Child Element defination describe the Child Element and his Attributes where the Brother Element describe the Brother Element and his Attributes.
So the full order to read will be Child Element >>> Attributes, Brother Element >>> Attributes. The Root (so offset 0x00) of any SonyPlaystation Resource file always start's with a Child Element to read.
Attribute
Attribute name (offset 0x0, length 0x4) |
Attribute name relative offset in TAGS Table | |||||||
---|---|---|---|---|---|---|---|---|
Attribute type (offset 0x4, length 0x4) |
1 (Single Integer) |
2 (Single Float) |
3 (String) |
4 (Integer Array) |
5 (Float Array) |
6 (File) |
7 (ID with loopback ref) |
8 (ID with crossed loopback ref) |
variable 1 (offset 0x8, length 0x4) |
Integer value | Float value | TAGS Table offset | Integer Arrays Table offset | Float Arrays Table offset | Files Table offset | Strings Table offset | Strings Table offset |
variable 2 (offset 0xC, length 0x4) |
Not used (always 0) | Not used (always 0) | String length | Number of integer's to read | Number of float's to read | File size | Not used (always 0) | Not used (always 0) |
- Attribute types 1 and 2 are the only ones that stores the value inside the attribute definition itself (from the point of view of code are defined and given a value at the same time, from the point of view of the structure can be said the value is "embedded" in the cxml TOC). Attributes 1 and 2 doesnt accesses any of the other tables of the cxml structure
- Attribute types 4 and 5 stores an array of values inside an "arrays table". This tables stores multiples arrays in a special format intended to reduce the final size of the table by avoiding duplicated arrays inside it. To recover a single array from a "arrays table" attributes types 4 and 5 specifyes a position in the table by the "offset" (where the array we are trying to recover begins) and the "number" (of consecutive items that composes the array we are trying to recover)
- Attribute type 7 stores a string in the "strings table", in this table next to the string we are trying to recover is defined an offset that "loops back" to the element that owns the attribute.
- Example: in rhm.qrc v1.00 the first "file" element of the TOC (at offset 0x78) has 2 attributes: "src" (at offset 0x94) is a type 6 attribute, and "id" (at offset 0xA4) is a type 7 attribute, "src" points to the "file table" and defines the file by his offset and size (this way you know where is the file, no mistery with attribute type 6). And "id" points to the string table at offset 0x1B0. If you look in the string table, the first string has an offset that points back to the "file" element in the TOC at offset 0x78 (in the runtime we have readed the definition of the element "file" in the TOC----> then the attribute id with the string---> then back to the TOC to the same "file" element so we can read all his attributes again).
- The purpose of this pointer that returns back from the strings table ---> to the TOC is a bit unknown, seems to be related with the other attributes owned by the same element and the way how the structure is accessed in the runtime (maybe the system does a loop to access every one of the attributes that belongs to an element). This special feature is what has been named in the wiki page before as "ID with ref" (and "ID without ref" for att type 8
because doesnt have it), now we are using too the concept of loops, loopback, and crossed loopbacks, but in my oppinion the names of attibute types 7 and 8 cant be decided yet because we dont know exactly what is the purpose of it (is hard to give it a name before knowing exactly how it works)
Container Common Structure
QRC
ZLIB Compressed level 9 (only container)
QRCC
QRCC (Qt Resources Container Compressed)
In the practise and from the point of view of the system, the QRCC has no interest and is needed to decompress the whole QRCC to be able to read the internal structure of the container and to acess individual files, when a QRCC is decompressed it generates an QRCF file (the real container) but this QRCF has a different internal structure than the QRCF used by icontex.qrc (are 2 variations of the same container with some small differences... although both uses the same identifier QRCF)
- Example from 3.55 rhm.qrc:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 51 52 43 43 00 00 28 00 78 DA QRCC..(.xÚ
Name | Offset | Size | Example | Remark |
---|---|---|---|---|
Magic | 0x00 | 0x04 | 51 52 43 43 | 'QRCC' |
QRCF decompressed size | 0x04 | 0x04 | 00 00 28 00 | The size of the QRCF file generated when a QRCC is decompressed |
compressed QRCF | 0x08 | varies, up to the end of the QRCC file | 78 DA... | QRCF file start offset, compressed with ZLIB |
- Notes
- The first 2 bytes of the compressed QRCF is the ZLIB header, being the default/max level 9.
byte index | bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
---|---|---|---|---|---|---|---|---|
[0] CMF | Compression info
|
Compression method
| ||||||
[1] FLG | FLEVEL
|
FDICT
(Preset dictionary) If set, a DICT dictionary identifier is present immediately after the FLG byte. The dictionary is a sequence of bytes which are initially fed to the compressor without producing any compressed output. DICT is the Adler-32 checksum of this sequence of bytes (see the definition of ADLER32 below). The decompressor can use this identifier to determine which dictionary has been used by the compressor. |
FCHECK
value must be such that CMF and FLG, when viewed as a 16-bit unsigned integer stored in MSB order (CMF *256 + FLG), is a multiple of 31. |
QRCF
QRCF (Qt Resources Container Flat?)
Main Header
The header contains an identifier of the container (magic), his version, and allows to store the "absolute start offset" and "size" of 7 tables (or areas)
When a "not used table" is placed before a "used table"... the start offset of the "not used table" and his size (as zero) are stored in the main header to preserve his position in the structure. The "used table" that comes later starts in the same offset than the previously "not used table" (an intuitive way to think in this is imagining are overlapped because starts in the same position but only the one at the top is used)
- The container format is generic (used also by .RAF and .P3T with some variations) so the usage of this tables can vary, in this example there are 3 "not used tables":
- two of the "not used tables" (both at offset 0x460 with a size of 0) are placed before an used table (also at offset 0x460 but with a size of 0x23A0)
- the other "not used table" is placed at the end, so there is no need to store his offset
- Example from fw 3.55 rhm.qrc:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 51 52 43 46 00 00 01 10 00 00 00 40 00 00 02 CC QRCF.......@..%| 00000010 00 00 03 10 00 00 01 2B 00 00 04 40 00 00 00 1B ..%À......9Ð.... 00000020 00 00 04 60 00 00 00 00 00 00 04 60 00 00 00 00 ..9ð......9ð.... 00000030 00 00 04 60 00 00 23 A0 00 00 00 00 00 00 00 00 ..9ð..@p........
Name | Offset | Size | Example | Remark |
---|---|---|---|---|
Magic | 0x00 | 0x04 | 51 52 43 46 | 'QRCF' |
Version | 0x04 | 0x04 | 00 00 01 10 | CXML version '1.10' |
Tree Table Offset | 0x08 | 0x04 | 00 00 00 40 | |
Tree Table Size | 0x0C | 0x04 | 00 00 02 CC | |
ID Table Offset | 0x10 | 0x04 | 00 00 03 10 | |
ID Table Size | 0x14 | 0x04 | 00 00 01 2B | |
String Table Offset | 0x18 | 0x04 | 00 00 04 40 | |
String Table Size | 0x1C | 0x04 | 00 00 00 1B | |
Integer Array Offset | 0x20 | 0x04 | 00 00 04 60 | Overlapped |
Integer Array size | 0x24 | 0x04 | 00 00 00 00 | Not used |
Float Array Offset | 0x28 | 0x04 | 00 00 04 60 | Overlapped |
Float Array Size | 0x2C | 0x04 | 00 00 00 00 | Not used |
File Table Offset | 0x30 | 0x04 | 00 00 04 60 | Overlaps the previous 2 tables |
File Table Size | 0x34 | 0x04 | 00 00 23 A0 | |
Unknown Table Offset | 0x38 | 0x04 | 00 00 00 00 | Not present |
Unknown Table Size | 0x3C | 0x04 | 00 00 00 00 | Not Used |
- Notes
- The sizes doesn't includes the (possible) padding at the end of all tables
Tree Table
Offset (without the 0x40 header in all qrc files) http://666kb.com/i/cib5c7q4y7rpcx9x1.gif
Same on all QRC's till offset 0x70
Offset | Size | Example | Remark |
---|---|---|---|
0x00 | 0x04 | 00 00 00 00 | Root Element (Offset within String Table, in this case it will be <qrc>) |
0x04 | 0x04 | 00 00 00 00 | Attribute Counter |
0x08 | 0x04 | FF FF FF FF | Parent |
0x0C | 0x04 | FF FF FF FF | Previous Element |
0x10 | 0x04 | FF FF FF FF | Next Element |
0x14 | 0x04 | 00 00 00 1C | First Entry within the root Element (qrc) |
0x18 | 0x04 | 00 00 00 1C | Last Entry within the root Element (qrc) |
0x1C | 0x04 | 00 00 00 04 | String Pointer (Offset within String Table, in this case it will be <file-table>) |
0x20 | 0x04 | 00 00 00 00 | Attribute Counter |
0x24 | 0x04 | 00 00 00 00 | Parent |
0x28 | 0x04 | FF FF FF FF | Previous Element |
0x2C | 0x04 | FF FF FF FF | Next Element |
0x30 | 0x04 | 00 00 00 38 | First Entry |
0x34 | 0x04 | 00 00 01 28 | Last Entry |
0x38 | 0x04 | 00 00 00 0F | String Pointer (Offset within String Table, in this case it will be a Element <file>) |
0x3C | 0x04 | 00 00 00 02 | Attribute Counter (0x02 == 2, the 2 Attributes of <file> Element) |
0x40 | 0x04 | 00 00 00 1C | Parent Element (Offset within Tree Table, in this case it will be <file-table>) |
0x44 | 0x04 | FF FF FF FF | Previous Element |
0x48 | 0x04 | 00 00 00 74 | Next Element |
0x4C | 0x04 | FF FF FF FF | First Entry |
0x50 | 0x04 | FF FF FF FF | Last Entry |
0x54 | 0x04 | 00 00 00 14 | String Pointer (Offset within String Table, in this case it will be a Attribute <src>) |
0x58 | 0x04 | 00 00 00 06 | Type Descriptor (6 == File) |
0x5C | 0x04 | 00 00 00 00 | Offset of data within File Table |
0x60 | 0x04 | 00 00 01 50 | Size of data within File Table |
0x64 | 0x04 | 00 00 00 18 | String Pointer (Offset within String Table, in this case it will be a Attribute <id>) |
0x68 | 0x04 | 00 00 00 07 | Type Descriptor (7 == ID) |
0x6C | 0x04 | 00 00 00 00 | Offset of filename within the ID Table |
0x70 | 0x04 | 00 00 00 00 | not used |
On icontex.qrc there are additional 16 bytes added on offset 0x70 within the Tree Table because it has an additional attribute size
Offset | Size | Example | Remark |
---|---|---|---|
0x74 | 0x04 | 00 00 00 1B | String Pointer (Offset within String Table, in this case it will be a Attribute <size>) |
0x78 | 0x04 | 00 00 00 01 | Type Descriptor (1 == Integer) |
0x7C | 0x04 | 00 01 55 D4 | on icontex.qrc (size of .dds uncompressed [Dec = 87508]) |
0x80 | 0x04 | 00 00 00 00 | not used |
Filenames List
This area is composed by a consecutive list of string entries that defines the names of the <file>'s inside <file-table> from the .xml file used to create the container
Every <file> inside <file-table> has assigned 2 attributes in the xml used to create the container: "src" (includes full path + file name + file extension), and "id" (only file name), plus the attribute "size" in QRCF_2 that is added by the program that creates the container ("size" is not present in the original .xml but added automatically when the container is created, this only happens in QRCF_2 and themes and is related with the per-file compression)
- For QRCF_1 containers only is stored the "src" (the file "id" is missing although can be deduced from the "src")
- For QRCF_2 and P3T themes only is stored the "id" (the file "src" is missing so there is no way to read the original path or file extension from the container)
<?xml version="1.0" encoding="UTF-8"?> <qrc> <file-table> <file src="lib/rhm/Clear.fpo" id="Clear"/> </file-table> </qrc>
For QRCF_1 each entry is composed by:
Offset | Length | Example | Name | Notes |
---|---|---|---|---|
0x0 | 0x4 | 00000038 | Filename Table pointer | Same value than in the Tree Table |
0x4 | variable | lib/rhm/Clear.fpo | File name | stored in the .xml as "src" |
variable | 0x1 | 00 | NULL byte |
- Notes
- For QRCF_2 and themes the structure of an entry is the same, but instead of storing: lib/rhm/Clear.fpo (the file "src"), it should store: Clear (the file "id")
- The end of the table has a padding to align to 0x10 bytes
- About the name of this area... for QRCF_1 what is stored is the "src" of the file so we can name it "File SRC table" or "File SRC List", but QRCF_2 and themes stores the "id" of the file so we could name it "File ID table" or "File ID List", but later will be needed to move all this explanations of the structure to a new page and include RAF that is a bit unknown by now if it uses some specific names for storage types inside specific tables. By now we can use a generic name for this area that includes all them like "Filenames List" and decide later if is needed to use specific names
String Table
This area is composed by a consecutive list of all the tags (elements or attributes) from the xml that was used to create the container. Are stored "from-top-to-bottom" in the exact same order that they was ordered in the xml (although it looks in some cases the theme compiler reorders them to his convenience). This list doesn't makes differences of the "directory hierarchy" of the tags neither is specified if the tag is an element or an attribute (this parent-child hierarchy is defined in other place of the container by making references to this area by using "byte counters" to locate a tag)
In all the .qrc files (QRCF_1) except icontex.qrc (QRCF_2). The only difference is QRCF_2 adds the "size" to all the <file> elements (added by the container creator, related with the "per-file" compression) Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000440 71 72 63 00 66 69 6C 65 2D 74 61 62 6C 65 00 66 qrc file-table f 00000450 69 6C 65 00 73 72 63 00 69 64 00 00 00 00 00 00 ile src id......
In icontex.qrc only (QRCF_2). This is similar than themes with the difference that QRC uses a <file-table> containing 1 or more <file>, and themes uses a <icontable> containing 1 or more <icon> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000440 71 72 63 00 66 69 6C 65 2D 74 61 62 6C 65 00 66 qrc file-table f 00000450 69 6C 65 00 73 72 63 00 69 64 00 73 69 7A 65 00 ile src id size.
- Notes:
- yellow: used bytes
- red: padding to align to 0x10 bytes
- The integer values and text strings of some attributes tags from the xml (e.g: "themename=mytheme", or "fontcolor=2") are stored in this area too at the right of his tag, the presence of an integer value displaces the next tag (this only happens in themes and rafs, not in QRC files so is added here as a note but is very important for the structure of the other containers when using "byte counters" to locate the tags)
File Table
The files are concatenated in the same order than in the Tree Table & ID Table
Summary
Table Description
Tree Table of rhm.qrc ID Table of rhm.qrc Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF ........ÿÿÿÿÿÿÿÿ 00000000 00 00 00 38 6C 69 62 2F 72 68 6D 2F 43 6C 65 61 ...8lib/rhm/Clea 00000010 FF FF FF FF 00 00 00 1C 00 00 00 1C 00 00 00 04 ÿÿÿÿ............ 00000010 72 2E 66 70 6F 00 00 00 00 74 6C 69 62 2F 72 68 r.fpo....tlib/rh 00000020 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF ........ÿÿÿÿÿÿÿÿ 00000020 6D 2F 43 6C 65 61 72 2E 76 70 6F 00 00 00 00 B0 m/Clear.vpo....° 00000030 00 00 00 38 00 00 02 90 00 00 00 0F 00 00 00 02 ...8............ 00000030 6C 69 62 2F 72 68 6D 2F 43 6F 70 79 2E 66 70 6F lib/rhm/Copy.fpo 00000040 00 00 00 1C FF FF FF FF 00 00 00 74 FF FF FF FF ....ÿÿÿÿ...tÿÿÿÿ 00000040 00 00 00 00 EC 6C 69 62 2F 72 68 6D 2F 64 65 66 ....ìlib/rhm/def 00000050 FF FF FF FF 00 00 00 14 00 00 00 06 00 00 00 00 ÿÿÿÿ............ 00000050 61 75 6C 74 2E 66 70 6F 00 00 00 01 28 6C 69 62 ault.fpo....(lib 00000060 00 00 01 50 00 00 00 18 00 00 00 07 00 00 00 00 ...P............ 00000060 2F 72 68 6D 2F 64 65 66 61 75 6C 74 2E 76 70 6F /rhm/default.vpo 00000070 00 00 00 00 00 00 00 0F 00 00 00 02 00 00 00 1C ................ 00000070 00 00 00 01 64 6C 69 62 2F 67 6C 75 74 69 6C 73 ....dlib/glutils 00000080 00 00 00 38 00 00 00 B0 FF FF FF FF FF FF FF FF ...8...°ÿÿÿÿÿÿÿÿ 00000080 2F 43 6F 6E 65 46 69 6C 74 65 72 2E 66 70 6F 00 /ConeFilter.fpo. 00000090 00 00 00 14 00 00 00 06 00 00 01 50 00 00 00 E0 ...........P...à 00000090 00 00 01 A0 6C 69 62 2F 67 6C 75 74 69 6C 73 2F ....lib/glutils/ 000000A0 00 00 00 18 00 00 00 07 00 00 00 16 00 00 00 00 ................ 000000A0 43 6F 6E 65 46 69 6C 74 65 72 2E 76 70 6F 00 00 ConeFilter.vpo.. 000000B0 00 00 00 0F 00 00 00 02 00 00 00 1C 00 00 00 74 ...............t 000000B0 00 01 DC 6C 69 62 2F 67 6C 75 74 69 6C 73 2F 43 ..Ülib/glutils/C 000000C0 00 00 00 EC FF FF FF FF FF FF FF FF 00 00 00 14 ...ìÿÿÿÿÿÿÿÿ.... 000000C0 6F 6E 65 46 69 6C 74 65 72 53 69 6D 70 6C 65 2E oneFilterSimple. 000000D0 00 00 00 06 00 00 02 30 00 00 01 20 00 00 00 18 .......0........ 000000D0 66 70 6F 00 00 00 02 18 6C 69 62 2F 67 6C 75 74 fpo.....lib/glut 000000E0 00 00 00 07 00 00 00 2C 00 00 00 00 00 00 00 0F .......,........ 000000E0 69 6C 73 2F 53 63 72 65 65 6E 43 6F 70 79 2E 66 ils/ScreenCopy.f 000000F0 00 00 00 02 00 00 00 1C 00 00 00 B0 00 00 01 28 ...........°...( 000000F0 70 6F 00 00 00 02 54 6C 69 62 2F 67 6C 75 74 69 po....Tlib/gluti 00000100 FF FF FF FF FF FF FF FF 00 00 00 14 00 00 00 06 ÿÿÿÿÿÿÿÿ........ 00000100 6C 73 2F 42 6C 75 72 32 2E 66 70 6F 00 00 00 02 ls/Blur2.fpo.... 00000110 00 00 03 50 00 00 01 F0 00 00 00 18 00 00 00 07 ...P...ð........ 00000110 90 6C 69 62 2F 67 6C 75 74 69 6C 73 2F 42 6C 75 .lib/glutils/Blu 00000120 00 00 00 41 00 00 00 00 00 00 00 0F 00 00 00 02 ...A............ 00000120 72 32 4D 61 73 6B 2E 66 70 6F r2Mask.fpo 00000130 00 00 00 1C 00 00 00 EC 00 00 01 64 FF FF FF FF .......ì...dÿÿÿÿ 00000140 FF FF FF FF 00 00 00 14 00 00 00 06 00 00 05 40 ÿÿÿÿ...........@ 00000150 00 00 08 10 00 00 00 18 00 00 00 07 00 00 00 59 ...............Y 00000160 00 00 00 00 00 00 00 0F 00 00 00 02 00 00 00 1C ................ 00000170 00 00 01 28 00 00 01 A0 FF FF FF FF FF FF FF FF ...(....ÿÿÿÿÿÿÿÿ String Table of rhm.qrc 00000180 00 00 00 14 00 00 00 06 00 00 0D 50 00 00 05 50 ...........P...P Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000190 00 00 00 18 00 00 00 07 00 00 00 71 00 00 00 00 ...........q.... 00000000 71 72 63 00 66 69 6C 65 2D 74 61 62 6C 65 00 66 qrc file-table f 000001A0 00 00 00 0F 00 00 00 02 00 00 00 1C 00 00 01 64 ...............d 00000010 69 6C 65 00 73 72 63 00 69 64 00 73 69 7A 65 00 ile src id size. 000001B0 00 00 01 DC FF FF FF FF FF FF FF FF 00 00 00 14 ...Üÿÿÿÿÿÿÿÿ.... 000001C0 00 00 00 06 00 00 12 A0 00 00 03 D0 00 00 00 18 ...........Ð.... 000001D0 00 00 00 07 00 00 00 90 00 00 00 00 00 00 00 0F ................ 000001E0 00 00 00 02 00 00 00 1C 00 00 01 A0 00 00 02 18 ................ 000001F0 FF FF FF FF FF FF FF FF 00 00 00 14 00 00 00 06 ÿÿÿÿÿÿÿÿ........ 00000200 00 00 16 70 00 00 01 C0 00 00 00 18 00 00 00 07 ...p...À........ 00000210 00 00 00 AF 00 00 00 00 00 00 00 0F 00 00 00 02 ...¯............ 00000220 00 00 00 1C 00 00 01 DC 00 00 02 54 FF FF FF FF .......Ü...Tÿÿÿÿ 00000230 FF FF FF FF 00 00 00 14 00 00 00 06 00 00 18 30 ...............0 00000240 00 00 03 10 00 00 00 18 00 00 00 07 00 00 00 D4 ...............Ô 00000250 00 00 00 00 00 00 00 0F 00 00 00 02 00 00 00 1C ................ 00000260 00 00 02 18 00 00 02 90 FF FF FF FF FF FF FF FF ........ÿÿÿÿÿÿÿÿ 00000270 00 00 00 14 00 00 00 06 00 00 1B 40 00 00 04 20 ...........@.... 00000280 00 00 00 18 00 00 00 07 00 00 00 F3 00 00 00 00 ...........ó.... 00000290 00 00 00 0F 00 00 00 02 00 00 00 1C 00 00 02 54 ...............T 000002A0 FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 14 ÿÿÿÿÿÿÿÿÿÿÿÿ.... 000002B0 00 00 00 06 00 00 1F 60 00 00 04 40 00 00 00 18 .......`...@.... 000002C0 00 00 00 07 00 00 01 0D 00 00 00 00 ............
Typ Description
Value | Typ | Notes |
---|---|---|
0x00000006 | File | Composed of Offset and Size each 4 bytes long |
0x00000007 | ID with ref | Composed of Offset 4 bytes long |
The Typ File is used to descripe two integer values, the Offset and Size for a File which will be readed from File Table. The Typ ID with ref is used to descripe the Offset of a Filename within the ID Table with the use of a 4 byte long reference, starting from the Offset given. The Size value from ID seems not to be used in Containers.
- ID with ref (0x00000007) is using the entry Offset from the Element (to which the Attribute belongs) as reference byte to compare if it is using the correct Filename for the processing File.
First Element (in root of xml) Points to a Offset within Tree Table which represents a string
Last Element (in root of xml) Points to a Offset within Tree Table which represents a string
String Pointer Points to a Offset within String Table which represents a string
Previous Element Points to a Offset within Tree Table which represents a string
Next Element Points to a Offset within Tree Table which represents a string
First Element
Last Element
String Pointer
Attribute Counter Integer value which describe the amount of Attributes for the current processing Element
Parent Points to a Offset within Tree Table which represents a string and describe the Parent Element
Previous Element (also used as a 4 byte long value which points to a Filename within ID Table)
Next Element (also used as a 4 byte long value which points to a Filename within ID Table)
First Entry Points to a Offsset within Tree Table which describe the first file of current processing Element
Last Entry Points to a Offsset within Tree Table which describe the last file of current processing Element
Stringt Pointer
Typ Descriptor A Integer value which describe the Typ of the Attribute
Offset of Filedata A Integer value, points to a Offset within File Table which describe the Start of a File to read from
Size of Filedata A Integer value which describe the Length of the File to read from File Table
String Pointer
Typ Descriptor
ID Offset A Integer value which describe the Offset of a Filename within ID Table
Container Structure variations
P3T
P3TF
P3TF (Playstation 3 Theme Flat?)
Main Header
The header contains an identifyer of the container (magic), his version, and allows to store the "absolute start offset" and "size" of 7 tables (or areas)
When a "not used table" is placed before a "used table"... the start offset of the "not used table" and his size (as zero) are stored in the main header to preserve his position in the structure. The "used table" that comes later starts in the same offset than the previouslly "not used table" (an intuitive way to think in this is imagining are overlapped because starts in the same position but only the one at the top is used)
- The container format is generic (used also by .RAF and .QRC with some variations) so the usage of this tables can vary, in this example there are 3 "not used tables":
- two of the "not used tables" (both at offset 0x460 with a size of 0) are placed before an used table (also at offset 0x460 but with a size of 0x23A0)
- the other "not used table" is placed at the end, so there is no need to store his offset
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 50 33 54 46 00 00 01 10 00 00 00 40 00 00 02 CC P3TF.......@..%| 00000010 00 00 03 10 00 00 01 2B 00 00 04 40 00 00 00 1B ..%À......9Ð.... 00000020 00 00 04 60 00 00 00 00 00 00 04 60 00 00 00 00 ..9ð......9ð.... 00000030 00 00 04 60 00 00 23 A0 00 00 00 00 00 00 00 00 ..9ð..@p........
Name | Offset | Size | Example | Remark |
---|---|---|---|---|
Magic | 0x00 | 0x04 | 51 52 43 46 | 'P3TF' |
Version | 0x04 | 0x04 | 00 00 01 10 | |
Tree Table Offset | 0x08 | 0x04 | 00 00 00 40 | |
Tree Table Size | 0x0C | 0x04 | 00 00 02 CC | |
ID Table Offset | 0x10 | 0x04 | 00 00 03 10 | |
ID Table Size | 0x14 | 0x04 | 00 00 01 2B | |
String Table Offset | 0x18 | 0x04 | 00 00 04 40 | |
String Table Size | 0x1C | 0x04 | 00 00 00 1B | |
Integer Array Offset | 0x20 | 0x04 | 00 00 04 60 | Overlapped |
Integer Array size | 0x24 | 0x04 | 00 00 00 00 | Not used |
Float Array Offset | 0x28 | 0x04 | 00 00 04 60 | Overlapped |
Float Array Size | 0x2C | 0x04 | 00 00 00 00 | Not used |
File Table Offset | 0x30 | 0x04 | 00 00 04 60 | Overlaps the previous 2 tables |
File Table Size | 0x34 | 0x04 | 00 00 23 A0 | |
Unknown Table Offset | 0x38 | 0x04 | 00 00 00 00 | Not present |
Unknown Table Size | 0x3C | 0x04 | 00 00 00 00 | Not Used |
- Notes
- The sizes doesnt includes the (posible) padding at the end of all tables
Tree Table
Offset | Size | Example | Remark |
---|---|---|---|
0x00 | 0x04 | 00 00 00 00 | Root Element (Offset within String Table, in this case it will be <p3t>) |
0x04 | 0x04 | 00 00 00 00 | Attribute Counter |
0x08 | 0x04 | FF FF FF FF | Parent |
0x0C | 0x04 | FF FF FF FF | Previous Element |
0x10 | 0x04 | FF FF FF FF | Next Element |
0x14 | 0x04 | 00 00 00 1C | First Element within the root Element (p3t) |
0x18 | 0x04 | 00 00 18 B4 | Last Element within the root Element (p3t) |
0x1C | 0x04 | 00 00 00 06 | String Pointer (Offset within String Table, in this case it will be <infotable>) |
0x20 | 0x04 | 00 00 00 00 | Attribute Counter |
0x24 | 0x04 | 00 00 00 00 | Parent |
0x28 | 0x04 | FF FF FF FF | Previous ELement |
0x2C | 0x04 | 00 00 01 AC | Next Element |
0x30 | 0x04 | 00 00 00 38 | First Entry |
0x34 | 0x04 | 00 00 01 60 | Last Entry |
0x38 | 0x04 | 00 00 00 10 | String Pointer (Offset within String Table, in this case it will be <info>) |
0x3C | 0x04 | 00 00 00 0D | Attribute Counter (0x0D == 13, the 13 Attributes of <info> Element) |
0x40 | 0x04 | 00 00 00 1C | Parent Element (Offset withing Tree Table, in this case it will be <infotable>) |
0x44 | 0x04 | FF FF FF FF | Previous Element |
0x48 | 0x04 | 00 00 01 24 | Next Element |
0x4C | 0x04 | FF FF FF FF | First Entry |
0x50 | 0x04 | FF FF FF FF | Last Entry |
String Table
This area is composed by a consecutive list of all the tags (elements or attributes) from the xml that was used to create the container. Are stored "from-top-to-bottom" in the exact same order that they was ordered in the xml (althougth it looks in some cases the theme compiler reorders them to his convenience). This list doesn't makes differences of the "directory hierarchy" of the tags neither is specified if the tag is an element or an attribute (this parent-child hierarchy is defined in other place of the container by making references to this area by using "byte counters" to locate a tag)
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 74 68 65 6D 65 00 69 6E 66 6F 74 61 62 6C 65 00 theme.infotable. 00000010 69 6E 66 6F 00 63 6F 6D 6D 65 6E 74 00 45 6E 6A info.comment.Enj 00000020 6F 79 2E 00 70 72 65 76 69 65 77 73 69 7A 65 00 oy..previewsize. 00000030 6E 61 6D 65 00 48 45 41 56 59 20 52 61 69 6E 20 name.HEAVY.Rain. 00000040 74 68 65 6D 65 00 61 75 74 68 6F 72 00 51 75 61 theme.author.Qua 00000050 6E 74 69 63 44 72 65 61 6D 00 75 72 6C 00 68 74 nticDream.url.ht 00000060 74 70 3A 2F 2F 77 77 77 2E 71 75 61 6E 74 69 63 tp://www.quantic 00000070 64 72 65 61 6D 2E 63 6F 6D 00 61 75 74 68 6F 72 dream.com.author 00000080 69 63 6F 6E 73 69 7A 65 00 61 75 74 68 6F 72 69 iconsize.authori 00000090 63 6F 6E 00 69 63 6F 6E 73 69 7A 65 00 76 65 72 con.iconsize.ver 000000A0 73 69 6F 6E 00 76 65 72 73 69 6F 6E 20 31 2E 30 sion.version.1.0 000000B0 00 6D 74 69 6D 65 00 32 30 30 39 31 30 33 30 31 .mtime.200910301 000000C0 36 31 33 34 33 00 67 65 6E 72 65 00 6F 74 68 65 61343.genre.othe 000000D0 72 73 00 70 72 65 76 69 65 77 00 69 63 6F 6E 00 re.preview.icon. 000000E0 6C 6F 63 61 6C 69 7A 65 64 69 6E 66 6F 00 6C 6F localizedinfo.lo 000000F0 63 61 6C 65 00 E3 81 93 E3 82 8C E3 81 AF E3 82 cale.ã“ã‚Œã¯ã‚ 00000100 B5 E3 83 B3 E3 83 97 E3 83 AB E3 83 86 E3 83 BC µãƒ³ãƒ—ルテー 00000110 E3 83 9E E3 83 95 E3 82 A1 E3 82 A4 E3 83 AB E3 マファイルã 00000120 81 A7 E3 81 99 E3 80 82 00 69 63 6F 6E 74 61 62 §ã™ã€‚.icontab 00000130 6C 65 00 73 72 63 00 69 64 00 73 69 7A 65 00 70 le.src.id.size.p 00000140 6F 69 6E 74 65 72 74 61 62 6C 65 00 70 6F 69 6E ointertable.poin 00000150 74 65 72 00 62 61 73 65 5F 78 00 62 61 73 65 5F ter.base_X.base_ 00000160 79 00 6E 6F 74 69 66 69 63 61 74 69 6F 6E 00 62 y.notification.b 00000170 67 69 6D 61 67 65 74 61 62 6C 65 00 62 67 69 6D gimagetable.bgim 00000180 61 67 65 00 61 6E 69 6D 00 66 6F 6E 74 00 73 65 age.anim.font.se 00000190 6C 65 63 74 69 6F 6E 00 63 6F 6C 6F 72 00 00 00 lection.color
- Notes:
- yellow: used bytes
- red: padding to align to 0x10 bytes
- The integer values and text strings of some attributes tags from the xml (e.g: "themename=mytheme", or "fontcolor=2") are stored in this area too at the right of his tag, the presence of an integer value displaces the next tag (this only happens in themes and rafs, not in QRC files so is added here as a note but is very important for the structure of the other containers when using "byte counters" to locate the tags)
ID Table
The ID Table of a P3T also can hold additional information for the <localizedinfo> Element.
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 00 00 01 24 65 6E 00 00 00 01 60 6A 70 00 00 00 ...$en....`jp... 00000010 01 C8 69 63 6F 6E 5F 75 73 65 72 00 00 00 02 14 .Èicon_user..... 00000020 69 63 6F 6E 5F 73 65 74 74 69 6E 67 00 00 00 02 icon_setting.... 00000030 60 69 63 6F 6E 5F 70 68 6F 74 6F 00 00 00 02 AC `icon_photo....¬ 00000040 69 63 6F 6E 5F 6D 75 73 69 63 00 00 00 02 F8 69 icon_music....øi 00000050 63 6F 6E 5F 76 69 64 65 6F 00 00 00 03 44 69 63 con_video....Dic 00000060 6F 6E 5F 67 61 6D 65 00 [...] on_game
File Table
The files are not concatenated in the same order than in the Tree Table & ID Table. There are even some file within the File Table which are not contained in ID Table(anim.raf, authoricon, ect.,...).
Summary
Table Description
For P3T i will use the Info Array to describe (place where all the infos from the <info> Element will be stored). The other File's follow the same handling like for QRC. (Well the Info Array does also follow the same handling but we have here 13 Attributes and it will also read some values not present in a QRC Container.) Also you can see here again that if a ID is readed then the entry Offset of a Element is also used as a 4 byte long pointer within ID Table. You start from the Offset the Tree Table is given you and the next readed 4 bytes should match the entry offset of the Element in Tree Table.
Tree Table of HeavyRain.p3t ID Table of HeavyRain.p3t Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000050 [...] 00 00 00 15 00 00 00 03 00 00 00 1D ............ 00000000 00 00 01 24 65 6E 00 00 00 01 60 6A 70 00 00 00 ...$en....`jp... 00000060 00 00 00 06 00 00 00 24 00 00 00 01 00 07 E9 80 .......$......é€ 00000010 01 C8 69 63 6F 6E 5F 75 73 65 72 00 00 00 02 14 .Èicon_user..... 00000070 00 00 00 00 00 00 00 30 00 00 00 03 00 00 00 35 .......0.......5 00000020 69 63 6F 6E 5F 73 65 74 74 69 6E 67 00 00 00 02 icon_setting.... 00000080 00 00 00 10 00 00 00 46 00 00 00 03 00 00 00 4D .......F.......M 00000030 60 69 63 6F 6E 5F 70 68 6F 74 6F 00 00 00 02 AC `icon_photo....¬ 00000090 00 00 00 0C 00 00 00 5A 00 00 00 03 00 00 00 5E .......Z.......^ 00000040 69 63 6F 6E 5F 6D 75 73 69 63 00 00 00 02 F8 69 icon_music....øi 000000A0 00 00 00 1B 00 00 00 7A 00 00 00 01 00 00 40 80 .......z......@€ 00000050 63 6F 6E 5F 76 69 64 65 6F 00 00 00 03 44 69 63 con_video....Dic 000000B0 00 00 00 00 00 00 00 89 00 00 00 06 00 00 00 00 .......‰........ 00000060 6F 6E 5F 67 61 6D 65 00 [...] on_game [...] 000000C0 00 00 1A 0B 00 00 00 94 00 00 00 01 00 00 40 80 .......”......@€ 000000D0 00 00 00 00 00 00 00 9D 00 00 00 03 00 00 00 A5 ...............¥ String Table of HeavyRain.p3t 000000E0 00 00 00 0B 00 00 00 B1 00 00 00 03 00 00 00 B7 .......±.......· 000000F0 00 00 00 0E 00 00 00 C6 00 00 00 03 00 00 00 CC .......Æ.......Ì Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000100 00 00 00 06 00 00 00 D3 00 00 00 06 00 00 1A 10 .......Ó........ 00000000 74 68 65 6D 65 00 69 6E 66 6F 74 61 62 6C 65 00 theme.infotable. 00000110 00 02 12 99 00 00 00 DB 00 00 00 06 00 02 2C B0 ...™...Û......,° 00000010 69 6E 66 6F 00 63 6F 6D 6D 65 6E 74 00 45 6E 6A info.comment.Enj 00000120 00 00 1F CE 00 00 00 E0 00 00 00 02 00 00 00 1C ...Î...à........ 00000020 6F 79 2E 00 70 72 65 76 69 65 77 73 69 7A 65 00 oy..previewsize. 00000130 00 00 00 38 00 00 01 60 FF FF FF FF FF FF FF FF ...8...`ÿÿÿÿÿÿÿÿ 00000030 6E 61 6D 65 00 48 45 41 56 59 20 52 61 69 6E 20 name.HEAVY.Rain. 00000140 00 00 00 EE 00 00 00 07 00 00 00 00 00 00 00 00 ...î............ 00000040 74 68 65 6D 65 00 61 75 74 68 6F 72 00 51 75 61 theme.author.Qua 00000150 00 00 00 30 00 00 00 03 00 00 00 35 00 00 00 10 ...0.......5.... 00000050 6E 74 69 63 44 72 65 61 6D 00 75 72 6C 00 68 74 nticDream.url.ht 00000160 00 00 00 E0 00 00 00 03 00 00 00 1C 00 00 01 24 ...à...........$ 00000060 74 70 3A 2F 2F 77 77 77 2E 71 75 61 6E 74 69 63 tp://www.quantic 00000170 FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 EE ÿÿÿÿÿÿÿÿÿÿÿÿ...î 00000070 64 72 65 61 6D 2E 63 6F 6D 00 61 75 74 68 6F 72 dream.com.author 00000180 00 00 00 07 00 00 00 07 00 00 00 00 00 00 00 15 ................ 00000080 69 63 6F 6E 73 69 7A 65 00 61 75 74 68 6F 72 69 iconsize.authori 00000190 00 00 00 03 00 00 00 F5 00 00 00 33 00 00 00 30 .......õ...3...0 00000090 63 6F 6E 00 69 63 6F 6E 73 69 7A 65 00 76 65 72 con.iconsize.ver 000001A0 00 00 00 03 00 00 00 35 00 00 00 10 00 00 01 29 .......5.......) 000000A0 73 69 6F 6E 00 76 65 72 73 69 6F 6E 20 31 2E 30 sion.version.1.0 000000B0 00 6D 74 69 6D 65 00 32 30 30 39 31 30 33 30 31 .mtime.200910301 000000C0 36 31 33 34 33 00 67 65 6E 72 65 00 6F 74 68 65 61343.genre.othe 000000D0 72 73 00 70 72 65 76 69 65 77 00 69 63 6F 6E 00 re.preview.icon. 000000E0 6C 6F 63 61 6C 69 7A 65 64 69 6E 66 6F 00 6C 6F localizedinfo.lo 000000F0 63 61 6C 65 00 E3 81 93 E3 82 8C E3 81 AF E3 82 cale.ã“ã‚Œã¯ã‚ 00000100 B5 E3 83 B3 E3 83 97 E3 83 AB E3 83 86 E3 83 BC µãƒ³ãƒ—ルテー 00000110 E3 83 9E E3 83 95 E3 82 A1 E3 82 A4 E3 83 AB E3 マファイルã 00000120 81 A7 E3 81 99 E3 80 82 00 69 63 6F 6E 74 61 62 §ã™ã€‚.icontab 00000130 6C 65 00 73 72 63 00 69 64 00 73 69 7A 65 00 70 le.src.id.size.p 00000140 6F 69 6E 74 65 72 74 61 62 6C 65 00 70 6F 69 6E ointertable.poin 00000150 74 65 72 00 62 61 73 65 5F [...] ter.base_ [...]
Typ Description
Value | Typ | Notes |
---|---|---|
0x00000001 | Integer | Composed of Value 4 bytes long |
0x00000003 | String | Composed of Offset and Length each 4 bytes long |
0x00000006 | File | Composed of Offset and Size each 4 bytes long |
0x00000007 | ID with ref | Composed of Offset 4 bytes long |
The Typ File is used to descripe two integer values, the Offset and Size for a File which will be readed from File Table. The Typ ID with ref is used to descripe the Offset of a Filename within the ID Table with the use of a 4 byte long reference, starting from the Offset given. The Second value from ID seems not to be used in Containers. Similar to ID, the Integer Typ only use one value the second one seems not to be used. String describe the Offset and Length of a string to read from String Table.
- ID with ref (0x00000007) is using the entry Offset from the Element (to which the Attribute belongs) as reference byte to compare if it is using the correct Filename for the processing File.
String Pointer Points to a Offset within String Table which represents a string (in this case a Attribute <comment>) Previous Element Typ Descriptor A Integer value which describe the Typ of the Attribute (3 == String) Next Element String Offset A Integer value which describe the Offset of a String within String Table First Entry Length of String A Integer value which describe the Length of the String to read from String Table Last Entry String Pointer -"- (in this case a Attribute <previewsize>) String Pointer -"- (in this case a Attribute <local>) Typ Descriptor A Integer value which describe the Typ of the Attribute (1 == Integer) Typ Descriptor -"- (7 == ID) Integer Hex Value A Integer Value which describe the size of the icon "preview" ID Offset String Pointer -"- (in this case a Attribute <name>) String Pointer -"- (in this case a Attribute <name>) Typ Descriptor -"- (3 == String) Typ Descriptor -"- (3 == String) String Offset String Offset Length of String Length of String String Pointer -"- (in this case a Attribute <author>) String Pointer -"- (in this case a Element <localizedinfo>) Typ Descriptor -"- (3 == String) Attribute Counter (0x03 == 3) String Offset Parent Length of String Previous Element String Pointer -"- (in this case a Attribute <url> Next Element Typ Descriptor -"- (3 == String)) First Entry String Offset Last Entry Length of String String Pointer -"- (in this case a Attribute <local>) String Pointer -"- (in this case a Attribute <authoriconsize>) Typ Descriptor -"- (7 == ID) Typ Descriptor -"- (1 == Integer) ID Offset Integer Hex Value -"- "authoriconsize" String Pointer -"- (in this case a Attribute <comment>) String Pointer -"- (in this case a Attribute <authoricon>) Typ Descriptor -"- (3 == String) Typ Descriptor -"- (6 == File) String Offset Offset of Filedata Length of String Size of Filedata String Pointer -"- (in this case a Attribute <name>) [...] this repeats till the last Attribute. I will describe on the right side the <localizedinfo> Elements. So we jump back in on Offset 0x124 [...] String Pointer -"- (in this case a Element <localizedinfo>) Typ Descriptor -"- (3 == String) Attribute Counter (0x02 == 2) String Offset Parent Length of String
Container Structure variations 2
RAF
ZLIB Compressed level 9 (only container)
_RAF
_RAF (_? Rich Appearance Format)
In practise and from the point of view of the system, the _RAF has no interest and is needed to decompress the whole _RAF to be able to read the internal structure of the container and to acess individual files, when a _RAF is decompressed it generates an RAFO file (the real container).
- Example from anim.raf of HeavyRain.p3t:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 51 52 43 43 00 00 28 00 78 DA _RAF..(.xÚ
Name | Offset | Size | Example | Remark |
---|---|---|---|---|
Magic | 0x00 | 0x04 | 5F 52 41 46 | '_RAF' |
_RAF decompressed size | 0x04 | 0x04 | 00 00 28 00 | The size of the _RAF file generated when a RAFO is decompressed |
compressed RAFO | 0x08 | varies, up to the end of the _RAF file | 78 DA... | RAFO file start offset, compressed with ZLIB |
- Notes
- The first 2 bytes of the compressed _RAF is the ZLIB header, in this example: 0x78DA
- default/max level 9
RAFO
RAFO (Rich Appearance Format O?)
Main Header
The header contains an identifyer of the container (magic), his version, and allows to store the "absolute start offset" and "size" of 7 tables (or areas)
When a "not used table" is placed before a "used table"... the start offset of the "not used table" and his size (as zero) are stored in the main header to preserve his position in the structure. The "used table" that comes later starts in the same offset than the previouslly "not used table" (an intuitive way to think in this is imagining are overlapped because starts in the same position but only the one at the top is used). Addition: Unlike an QRC Container a RAF can hold much more CXML Elements. The QRC only have <file-table> or <icontable> if it is the icontex.qrc.
- The container format is generic (used also by .QRC and .P3T with some variations) so the usage of this tables can vary, in this example there is 1 "not used tables":
- one of the "not used tables" (at offset 0x6F0 with a size of 0) is placed before an used table (also at offset 0x6F0 but with a size of 0x7C)
- the other "not used table" is placed at the end, so there is no need to store his offset
- Example from anim.raf of HeavyRain.p3t:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 52 41 46 4F 00 00 01 10 00 00 00 40 00 00 63 E0 [email protected]à 00000010 00 00 64 20 00 00 08 C2 00 00 6C F0 00 00 01 FC ..d...Â...lð...ü 00000020 00 00 6E F0 00 00 00 00 00 00 6E F0 00 00 00 7C ..nð......nð...| 00000030 00 00 6F 70 00 3B 2A 70 00 00 00 00 00 00 00 00 ..op.;*p........
Name | Offset | Size | Example | Remark |
---|---|---|---|---|
Magic | 0x00 | 0x04 | 51 41 46 4F | 'RAFO' |
Version | 0x04 | 0x04 | 00 00 01 10 | |
Tree Table Offset | 0x08 | 0x04 | 00 00 00 40 | |
Tree Table Size | 0x0C | 0x04 | 00 00 63 E0 | |
ID Table Offset | 0x10 | 0x04 | 00 00 64 20 | |
ID Table Size | 0x14 | 0x04 | 00 00 08 C2 | |
String Table Offset | 0x18 | 0x04 | 00 00 6C F0 | |
String Table Size | 0x1C | 0x04 | 00 00 01 FC | |
Integer Array Offset | 0x20 | 0x04 | 00 00 06 F0 | Overlapped |
Integer Array size | 0x24 | 0x04 | 00 00 00 00 | Not used |
Float Array Offset | 0x28 | 0x04 | 00 00 06 F0 | |
Float Array Size | 0x2C | 0x04 | 00 00 00 7C | |
File Table Offset | 0x30 | 0x04 | 00 00 6F 70 | |
File Table Size | 0x34 | 0x04 | 00 3B 2A 70 | |
Unknown Table Offset | 0x38 | 0x04 | 00 00 00 00 | Not present |
Unknown Table Size | 0x3C | 0x04 | 00 00 00 00 | Not Used |
- Notes
- The sizes doesn't includes the (posible) padding at the end of all tables
Tree Table
Offset | Size | Example | Remark |
---|---|---|---|
0x00 | 0x04 | 00 00 00 00 | Root Element (Offset within String Table, in this case it will be <raf>) |
0x04 | 0x04 | 00 00 00 01 | Attribute Counter |
0x08 | 0x04 | FF FF FF FF | Parent |
0x0C | 0x04 | FF FF FF FF | Previous Element |
0x10 | 0x04 | FF FF FF FF | Next Element |
0x14 | 0x04 | 00 00 00 2C | First Entry within the root Element (raf) |
0x18 | 0x04 | 00 00 57 3C | Last Entry within the root Element (raf) |
0x1C | 0x04 | 00 00 00 04 | String Pointer (Offset within String Table, in this case it will be <version>) |
0x20 | 0x04 | 00 00 00 02 | Type descriptor (2 == Float) |
0x24 | 0x04 | 3F 80 00 00 | Float value (1.1E0) |
0x28 | 0x04 | 00 00 00 00 | empty value |
0x2C | 0x04 | 00 00 00 0C | String Pointer (in this case <scene>) |
0x30 | 0x04 | 00 00 00 04 | Attribute Counter |
0x34 | 0x04 | 00 00 00 00 | Parent |
0x38 | 0x04 | FF FF FF FF | Previous Element |
0x3C | 0x04 | 00 00 3F AC | Next Element |
0x40 | 0x04 | 00 00 00 88 | First Entry |
0x44 | 0x04 | 00 00 3F 70 | Next Entry |
0x48 | 0x04 | 00 00 00 12 | String Pointer (in this case <camera_num>) |
0x4C | 0x04 | 00 00 00 01 | Type descriptor (1 == Integer) |
0x50 | 0x04 | 00 00 00 01 | Integer value |
0x54 | 0x04 | 00 00 00 00 | empty value |
0x58 | 0x04 | 00 00 00 1D | String Pointer (in this case <light_num>) |
0x5C | 0x04 | 00 00 00 01 | Type descriptor (1 == Integer) |
0x60 | 0x04 | 00 00 00 01 | Integer value |
0x64 | 0x04 | 00 00 00 00 | empty value |
0x68 | 0x04 | 00 00 00 27 | String Pointer (in this case <script_num>) |
0x6C | 0x04 | 00 00 00 01 | Type descriptor (1 == Integer) |
0x70 | 0x04 | 00 00 00 01 | Integer value |
0x74 | 0x04 | 00 00 00 00 | empty value |
0x78 | 0x04 | 00 00 00 32 | String Pointer (in this case <actor_num>) |
0x7C | 0x04 | 00 00 00 01 | Type descriptor (1 == Integer) |
0x80 | 0x04 | 00 00 00 48 | Integer value |
0x84 | 0x04 | 00 00 00 00 | empty value |
0x88 | 0x04 | 00 00 00 3C | String Pointer (in this case <actor>) |
0x8C | 0x04 | 00 00 00 0C | Attribute Counter (0x0C == 12) |
0x90 | 0x04 | 00 00 00 2C | Parent |
0x94 | 0x04 | FF FF FF FF | Previous Element |
0x98 | 0x04 | 00 00 01 64 | Next Element |
0x9C | 0x04 | FF FF FF FF | Firs Entry |
0xA0 | 0x04 | FF FF FF FF | Last Entry |
String Table
This area is composed by a consecutive list of all the tags (elements or attributes) from the xml that was used to create the container. Are stored "from-top-to-bottom" in the exact same order that they was ordered in the xml. This list doesnt makes differences of the "directory hierarchy" of the tags neither is specified if the tag is an element or an attribute (this parent-child hierarchy is defined in other place of the container by making references to this area by using "byte counters" to locate a tag)
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 72 61 66 00 76 65 72 73 69 6F 6E 00 73 63 65 6E raf.version.scen 00000010 65 00 63 61 6D 65 72 61 5F 6E 75 6D 00 6C 69 67 e.camera_num.lig 00000020 68 74 5F 6E 75 6D 00 73 63 72 69 70 74 5F 6E 75 ht_num.script_nu 00000030 6D 00 61 63 74 6F 72 5F 6E 75 6D 00 61 63 74 6F m.actor_num.acto 00000040 72 00 61 6E 69 6D 5F 73 70 65 65 64 [...] r.anim_speed[..]
- Notes:
- yellow: used bytes
ID Table
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 00 00 49 A8 6D 74 72 6C 5F 62 67 00 00 00 00 88 ..I¨mtrl_bg....ˆ 00000010 62 61 63 6B 67 72 6F 75 6E 64 00 00 00 3F D8 70 background...?Øp 00000020 6C 61 6E 65 00 00 00 4A 10 6D 74 72 6C 5F 72 75 lane...J.mtrl_ru 00000030 69 73 73 00 00 00 01 64 72 75 69 73 73 65 6C 00 iss....druissel. 00000040 00 00 40 7C 73 63 72 6F 6C 6C 5F 70 6C 61 6E 65 ..@|scroll_plane 00000050 [...] [...]
Float Array
Used from the Attribute Type Describtor 0x00000005 Float Array
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F Coverted Float Value (4 values each 4bytes) 00000000 3F 80 00 00 3F 80 00 00 3F 80 00 00 3F 80 00 00 ?€..?€..?€..?€.. 1.0E0, 1.0E0, 1.0E0, 1.0E0 00000010 00 00 00 00 00 00 00 00 3F 80 00 00 00 00 00 00 ........?€...... 0.0E0, 0.0E0, 1.0E0, 0.0E0 00000020 00 00 00 00 00 00 00 00 3F 80 00 00 BF 80 00 00 ........?€..¿€.. 0.0E0, 0.0E0, 1.0E0, -1.0E0 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0.0E0, 0.0E0, 0.0E0, 0.0E0 00000040 41 00 00 00 41 00 00 00 41 08 00 00 40 87 CF D5 A...A...A...@‡ÏÕ 8.0E0, 8.0E0, 8.5E0, 4.244120121002197265625E0 00000050 C0 8D 49 7B C1 09 9E ED 3F C0 00 00 00 00 00 00 À.I{Á.ží?À...... -4.415219783782958984375E0, -8.60130023956298828125E0, 1.5E0, 0.0E0 00000060 00 00 00 00 3D AE 14 7B BC 93 74 BC 3F 59 99 9A ....=®.{¼“t¼?Y™š 0.0E0, 8.5000000894069671630859375E-2, -1.7999999225139617919921875E-2, 8.5000002384185791015625E-1 00000070 40 E2 45 A2 BF 80 00 00 C1 CA A5 E3 @âE¢¿€..ÁÊ¥ã 7.07100009918212890625E0, -1.0E0, -2.53309993743896484375E1
File Table
The files are not concatenated in the same order than in the Tree Table & ID Table. There are even some ID String's withing the Table which are not any file from the container at all.
Summary
Table Description
Type Description
Value | Typ | Notes |
---|---|---|
0x00000001 | Integer | Composed of Value 4 bytes long |
0x00000002 | Float | Composed of Value 4 bytes long |
0x00000005 | Float Array | Composed of Offset and Count each 4 bytes long |
0x00000006 | File | Composed of Offset and Size each 4 bytes long |
0x00000007 | ID with ref | Composed of Offset 4 bytes long |
0x00000008 | ID without ref | Composed of Offset 4 bytes long |
The Typ File is used to descripe two integer values, the Offset and Size for a File which will be readed from File Table. The Typ ID with ref is used to descripe the Offset of a Filename within the ID Table with the use of a 4 byte long reference, starting from the Offset given. The Second value from ID seems not to be used in Containers. So ID without ref is the same but it doesn't use an reference byte (aka. the Offset of Element). Similar to ID, the Integer Typ only use one value the second one seems not to be used. Float is identical to Integer. Float Array is used to describe the offset and count of float values. But offset will be readed as a float count just like the second var float count it self, only with the diff it is meant as offset and you start to read the given Float count from there. Example: offset 7, float_count 2 == offset 7 (7 float values to jump, á 4 bytes * 7 = 28 so Offset = 0x28) float_count 2 (2 float values to take from offset 0x28 á 4 byts long so 8 bytes to read). Result in bytes: offset == 0x28, float_count == 0x08.
- ID with ref (0x00000007) is using the entry Offset from the Element (to which the Attribute belongs) as reference byte to compare if it is using the correct Filename for the processing File.
- ID without ref (0x00000008) doesn't. Or at least if it does it, it knows that the returned value will be a false one.
CXML
HKNW
Magic of the container is HKNW (acronym of hakoniwa)
Hakoniwa is the "Photo Gallery" official app (NPIA00006) that comes partially preinstalled in the firmwares (there is a mandatory icon in XMB photo column and is dependant of hknw_plugin.sprx, but the program itself is not installed with the firmware). To use the program it is needed to install the .PKG that installs the rest of the files in dev_hdd0/game/NPIA00006/USRDIR/EBOOT.PBP
In path: dev_flash/vsh/resource/hknw_plugin/jacket/ index.cxml, frame_01.cxml, and frame_05.cxml
- Example of the string table from frame_01.cxml
root.version.1.00.jacket.id.normal.base.position.rotation.scale.name.frame_01.filetable.num.file.src.frame_01_lo.gim.lod.frame_01_parallax_512.gtf.shadow_square_1.gtf.shadow_square_2.gtf.shadow_3.gtf.frame_01_mi.gim.frame_01_hi.gim.vptable.vp.vp_jacket_ezprim.vpo.optional.vp_jacket_normalmap.vpo.vp_jacket_ezshadow.vpo.fptable.fp.fp_jacket_ezprim_rgb.fpo.fp_jacket_normalmap_specL.fpo.fp_jacket_ezshadow.fpo.modeltable.model.color.uv.vertex.tangent.binormal.layertable.layer.priority.type.image-frame-static.order.duration.image-thumbnail-auto
- Notes:
- The main tag is <root> like in a standard .xml
- Contains some attribute types (e.g: the second tag <version> has an "attribute type 3" that points to the value "1.00" stored inside the string table) not present in the examples in this wiki page (usefull for completion of the lists of data types numbers)
Examples
QRC
The structure of QRCF_1 (same structure used by rhm.qrc in the example below and all .qrc files except icontex.qrc) is composed by a element table named file-table containing one or more elements file that are associated with the attributes src and id
QRC doesnt makes any difference of the stored file type, all them are considered generic files and stored in the same table, this is why QRCF_1 is considered one of the most simple CXML structure variations (a container for generic files). The example used here is rhm.qrc from firmware 1.00 because is the smallest version of rhm.qrc only containing 5 files
For QRCF_1 every entry is composed by the element file (28 bytes) and his associated attributes: src (16 bytes), and id (16 bytes), for a total size of 60 bytes (or 0x3C)
For QRCF_2 every entry is composed by the element file (28 bytes) and his associated attributes: src (16 bytes), id (16 bytes), and size (16 bytes) for a total size of 76 bytes (or 0x4C)
In other words... the only difference between QRCF_1 and QRCF_2 is the added attribute size in every file entry that makes entries 16 bytes longer in QRCF_2... there is no need for an example of QRCF_2 because are almost the same
The .xml below represents the structure of rhm.qrc used in firmwares from 1.00 up to 1.32 ready to be compiled (compiled hash should be MD5: D1E7281246EC8A46EB6D368BD4B332BD)
<?xml version="1.0" encoding="UTF-8"?> <qrc> <file-table> <file src="C:/workdir/Clear_old.fpo" id="lib/rhm/Clear.fpo"/> <file src="C:/workdir/Clear_test12.vpo" id="lib/rhm/Clear.vpo"/> <file src="X:/DontCopyMe.fap" id="lib/rhm/Copy.fpo"/> <file src="D:/anotherworkdir/default_v12.fpo" id="lib/rhm/default.fpo"/> <file src="D:/anotherworkdir/default_v34.vpo" id="lib/rhm/default.vpo"/> </file-table> </qrc>
When the file is compiled the info from the .xml is stored in the TOC (at offset 0x40, colored in red in the example below). It starts with the main element qrc and his only children file-table that has his own 5 childrens file (all them are elements). Every file element has 2 attributes src and id.
The attribute src stores the information needed to locate the file, either in PC (before compiled) or locally inside the CXML container (after compiled). In the .xml example above the value of src are PC paths (used by the compiler to locate the file inside the PC), but when compiled the value is lost, the file is stored inside the container Files table (at offset 0x250, colored in orange in the example below), and is indexed in the container TOC by using an entry with data type 6 composed of file offset + file size (used by PS3 firmware to locate the file inside the container Files table)
The value of attribute id is stored inside the container Strings table (at offset 0x0x1B0, colored in green in the example below), and is indexed in the container TOC by using an entry with data type 7 composed by filename offset + unknown (used by the PS3 to locate the text string inside the container Strings table)
Areas | Offset | Size | Example | Name | Notes |
---|---|---|---|---|---|
CXML header | |||||
0x00 | 0x04 | QRCF | Magic | ||
0x04 | 0x04 | 00000110 | Version | ||
0x08 | 0x04 | 00000040 | TOC absolute offset, also header size | Stores CXML ELEMENTS and ATTRIBUTES definitions and the VALUES of attribute types 1 (single integer), and 2 (single float) | |
0x0C | 0x04 | 00000164 | TOC size | ||
0x10 | 0x04 | 000001B0 | Strings table absolute offset | Stores the VALUES of XML attributes type 7 and 8 | |
0x14 | 0x04 | 00000071 | Strings table size | ||
0x18 | 0x04 | 00000230 | TAGS table absolute offset | Stores the NAMES of XML elements and attributes] and the VALUES of attribute types 3 (string) | |
0x1C | 0x04 | 0000001B | TAGS table size | ||
0x20 | 0x04 | 00000250 | Integer arrays table absolute offset | Stores the VALUES of XML attributes type 4 (integer array) | |
0x24 | 0x04 | 00000000 | Integer arrays table size | ||
0x28 | 0x04 | 00000250 | Float arrays table absolute offset | Stores the VALUES of XML attributes type 5 (float array) | |
0x2C | 0x04 | 00000000 | Float arrays table size | ||
0x30 | 0x04 | 00000250 | Files table absolute offset | Stores the FILES indexed in the TOC by attribute type 6 (file) | |
0x34 | 0x04 | 00000DD0 | Files table size | ||
0x38 | 0x04 | 00000000 | Unknown area absolute offset | Unknown | |
0x3C | 0x04 | 00000000 | Unknown area size | ||
TOC | |||||
0x40 | 0x04 | 00000000 | element name relative offset | qrc | |
0x44 | 0x04 | 00000000 | number of attributes | no attributes | |
0x48 | 0x04 | FFFFFFFF | parent element relative offset | parent doesnt exists | |
0x4C | 0x04 | FFFFFFFF | previous brother element relative offset | previous brother doesnt exists | |
0x50 | 0x04 | FFFFFFFF | next brother element relative offset | next brother doesnt exists | |
0x54 | 0x04 | 0000001C | first child element relative offset | 0x40 + 0x1C = first child at 0x5C absolute | |
0x58 | 0x04 | 0000001C | last child element relative offset | 0x40 + 0x1C = last child at 0x5C absolute | |
0x5C | 0x04 | 00000004 | element name relative offset | file-table | |
0x60 | 0x04 | 00000000 | number of attributes | no attributes | |
0x64 | 0x04 | 00000000 | parent element relative offset | 0x40 + 0x0 = 0x40 absolute = parent is qrc | |
0x68 | 0x04 | FFFFFFFF | previous brother element relative offset | previous brother doesnt exists | |
0x6C | 0x04 | FFFFFFFF | next brother element relative offset | next brother doesnt exists | |
0x70 | 0x04 | 00000038 | first child element relative offset | 0x40 + 0x38 = first child at 0x78 absolute | |
0x74 | 0x04 | 00000128 | last child element relative offset | 0x40 + 0x128 = last child at 0x168 absolute | |
0x78 | 0x04 | 0000000F | element name relative offset | file | |
0x7C | 0x04 | 00000002 | number of attributes | 2 attributes = src and id | |
0x80 | 0x04 | 0000001C | parent element relative offset | 0x40 + 0x1C = 0x5C absolute = parent is file-table | |
0x84 | 0x04 | FFFFFFFF | previous brother element relative offset | previous brother doesnt exists | |
0x88 | 0x04 | 00000074 | next brother element relative offset | 0x40 + 0x74 = next brother at 0xB4 absolute | |
0x8C | 0x04 | FFFFFFFF | first child element relative offset | first child doesnt exists | |
0x90 | 0x04 | FFFFFFFF | last child element relative offset | last child doesnt exists | |
0x94 | 0x04 | 00000014 | attribute name relative offset | src | |
0x98 | 0x04 | 00000006 | attribute type | 6 = file offset + file size | |
0x9C | 0x04 | 00000000 | attribute variable 1 | 0x250 + 0x0 = file at offset 0x250 absolute | |
0xA0 | 0x04 | 00000150 | attribute variable 2 | file size is 0x150 | |
0xA4 | 0x04 | 00000018 | attribute name relative offset | id | |
0xA8 | 0x04 | 00000007 | attribute type | 7 = filename offset + unknown | |
0xAC | 0x04 | 00000000 | attribute variable 1 | 0x1B0 + 0x0 = filename at offset 0x1B0 absolute | |
0xB0 | 0x04 | 00000000 | attribute variable 2 | ||
0xB4 | 0x04 | 0000000F | element name relative offset | file | |
0xB8 | 0x04 | 00000002 | number of attributes | 2 attributes = src and id | |
0xBC | 0x04 | 0000001C | parent element relative offset | 0x40 + 0x1C = 0x5C absolute = parent is file-table | |
0xC0 | 0x04 | 00000038 | previous brother element relative offset | 0x40 + 0x38 = previous brother at 0x78 absolute | |
0xC4 | 0x04 | 000000B0 | next brother element relative offset | 0x40 + 0xB0 = next brother at 0xF0 absolute | |
0xC8 | 0x04 | FFFFFFFF | first child element relative offset | first child doesnt exists | |
0xCC | 0x04 | FFFFFFFF | last child element relative offset | last child doesnt exists | |
0xD0 | 0x04 | 00000014 | attribute name relative offset | src | |
0xD4 | 0x04 | 00000006 | attribute type | 6 = file offset + file size | |
0xD8 | 0x04 | 00000150 | attribute variable 1 | 0x250 + 0x150 = file at offset 0x3A0 absolute | |
0xDC | 0X04 | 000000E0 | attribute variable 2 | file size is 0xE0 | |
0xE0 | 0x04 | 00000018 | attribute name relative offset | id | |
0xE4 | 0x04 | 00000007 | attribute type | 7 = filename offset + unknown | |
0xE8 | 0x04 | 00000016 | attribute variable 1 | 0x1B0 + 0x16 = filename at offset 0x1C6 absolute | |
0xEC | 0x04 | 00000000 | attribute variable 2 | ||
0xF0 | 0x04 | 0000000F | element name relative offset | file | |
0xF4 | 0x04 | 00000002 | number of attributes | 2 attributes = src and id | |
0xF8 | 0x04 | 0000001C | parent element relative offset | 0x40 + 0x1C = 0x5C absolute = parent is file-table | |
0xFC | 0x04 | 00000074 | previous brother element relative offset | 0x40 + 0x74 = previous brother at 0xB4 absolute | |
0x100 | 0x04 | 000000EC | next brother element relative offset | 0x40 + 0xEC = next brother at 0x12C absolute | |
0x104 | 0x04 | FFFFFFFF | first child element relative offset | first child doesnt exists | |
0x108 | 0x04 | FFFFFFFF | last child element relative offset | last child doesnt exists | |
0x10C | 0x04 | 00000014 | attribute name relative offset | src | |
0x110 | 0x04 | 00000006 | attribute type | 6 = file offset + file size | |
0x114 | 0x04 | 00000230 | attribute variable 1 | 0x250 + 0x230 = file at offset 0x480 absolute | |
0x118 | 0x04 | 00000120 | attribute variable 2 | file size is 0x120 | |
0x11C | 0x04 | 00000018 | attribute name relative offset | id | |
0x120 | 0x04 | 00000007 | attribute type | 7 = filename offset + unknown | |
0x124 | 0x04 | 0000002C | attribute variable 1 | 0x1B0 + 0x2C = filename at offset 0x1DC absolute | |
0x128 | 0x04 | 00000000 | attribute variable 2 | ||
0x12C | 0x04 | 0000000F | element name relative offset | file | |
0x130 | 0x04 | 00000002 | number of attributes | 2 attributes = src and id | |
0x134 | 0x04 | 0000001C | parent element relative offset | 0x40 + 0x1C = 0x5C absolute = parent is file-table | |
0x138 | 0x04 | 000000B0 | previous brother element relative offset | 0x40 + 0xB0 = previous brother at 0xF0 absolute | |
0x13C | 0x04 | 00000128 | next brother element relative offset | 0x40 + 0x128 = next brother at 0x168 absolute | |
0x140 | 0x04 | FFFFFFFF | first child element relative offset | first child doesnt exists | |
0x144 | 0x04 | FFFFFFFF | last child element relative offset | last child doesnt exists | |
0x148 | 0x04 | 00000014 | attribute name relative offset | src | |
0x14C | 0x04 | 00000006 | attribute type | 6 = file offset + file size | |
0x150 | 0x04 | 00000350 | attribute variable 1 | 0x250 + 0x350 = file at offset 0x5A0 absolute | |
0x154 | 0x04 | 000001F0 | attribute variable 2 | file size is 0x1F0 | |
0x158 | 0x04 | 00000018 | attribute name relative offset | id | |
0x15C | 0x04 | 00000007 | attribute type | 7 = filename offset + unknown | |
0x160 | 0x04 | 00000041 | attribute variable 1 | 0x1B0 + 0x41 = filename at offset 0x1F1 absolute | |
0x164 | 0x04 | 00000000 | attribute variable 2 | ||
0x168 | 0x04 | 0000000F | element name relative offset | file | |
0x16C | 0x04 | 00000002 | number of attributes | 2 attributes = src and id | |
0x170 | 0x04 | 0000001C | parent element relative offset | 0x40 + 0x1C = 0x5C absolute = parent is file-table | |
0x174 | 0x04 | 000000EC | previous brother element relative offset | 0x40 + 0xEC = previous brother at 0x12C absolute | |
0x178 | 0x04 | FFFFFFFF | next brother element relative offset | next brother doesnt exists | |
0x17C | 0x04 | FFFFFFFF | first child element relative offset | first child doesnt exists | |
0x180 | 0x04 | FFFFFFFF | last child element relative offset | last child doesnt exists | |
0x184 | 0x04 | 00000014 | attribute name relative offset | src | |
0x188 | 0x04 | 00000006 | attribute type | 6 = file offset + file size | |
0x18C | 0x04 | 00000540 | attribute variable 1 | 0x250 + 0x540 = file at offset 0x790 absolute | |
0x190 | 0x04 | 00000890 | attribute variable 2 | file size is 0x890 | |
0x194 | 0x04 | 00000018 | attribute name relative offset | id | |
0x198 | 0x04 | 00000007 | attribute type | 7 = filename offset + unknown | |
0x19C | 0x04 | 00000059 | attribute variable 1 | 0x1B0 + 0x59 = filename at offset 0x209 absolute | |
0x1A0 | 0x04 | 00000000 | attribute variable 2 | ||
0x1A4 | 0x0C | 000000000000000000000000 | padding | aligned to a multiply of 0x10 | |
Strings Table | |||||
0x1B0 | 0x04 | 00000038 | 1st element relative offset | 0x40 + 0x38 = element at offset 0x78 absolute | |
0x1B4 | 0x12 | lib/rhm/Clear.fpo | 1st file name | ||
0x1C6 | 0x04 | 00000074 | 2nd element relative offset | 0x40 + 0x74 = element at offset 0xB4 absolute | |
0x1CA | 0x12 | lib/rhm/Clear.vpo | 2nd file name | ||
0x1DC | 0x04 | 000000B0 | 3rd element relative offset | 0x40 + 0xB0 = element at offset 0xF0 absolute | |
0x1E0 | 0x11 | lib/rhm/Copy.fpo | 3rd file name | ||
0x1F1 | 0x04 | 000000EC | 4th element relative offset | 0x40 + 0xEC = element at offset 0x12C absolute | |
0x1F5 | 0x14 | lib/rhm/default.fpo | 4th file name | ||
0x209 | 0x04 | 00000128 | 5th element relative offset | 0x40 + 0x128 = element at offset 0x168 absolute | |
0x20D | 0x14 | lib/rhm/default.vpo | 5th file name | ||
0x221 | 0xF | 00000000000000000000000000000000 | padding | aligned to a multiply of 0x10 | |
TAGS table | |||||
0x230 | 0x1B | qrc file-table file src id | Container identifyer (first tag) + other tags from MAKE.XML | <qrc> <file-table> <file src=fileaccess id=filename/> | |
0x24B | 0x5 | 0000000000 | padding | aligned to a multiply of 0x10 | |
Integer arrays table | 0x250 | 0x00 | Empty | ||
Float arrays table | 0x250 | 0x00 | Empty | ||
Files Table | |||||
0x250 | 0x150 | 00001B5C... | 1st file | ||
0x3A0 | 0x1E0 | 00001B5B... | 2nd file | ||
0x480 | 0x120 | 00001B5C... | 3rd file | ||
0x5A0 | 0x1F0 | 00001B5C... | 4th file | ||
0x790 | 0x890 | 00001B5B... | 5th file | ||
Unknown area | 0x1020 | 0x00 | Empty |
rhm.qrc (from firmware 1.00)
Offset(h) 00 04 08 0C 00000000 51524346 00000110 00000040 00000164 [email protected] 00000010 000001B0 00000071 00000230 0000001B ...°...q...0.... 00000020 00000250 00000000 00000250 00000000 ...P.......P.... 00000030 00000250 00000DD0 00000000 00000000 ...P...Ð........ 00000040 00000000 00000000 FFFFFFFF FFFFFFFF ........ÿÿÿÿÿÿÿÿ 00000050 FFFFFFFF 0000001C 0000001C 00000004 ÿÿÿÿ............ 00000060 00000000 00000000 FFFFFFFF FFFFFFFF ........ÿÿÿÿÿÿÿÿ 00000070 00000038 00000128 0000000F 00000002 ...8...(........ 00000080 0000001C FFFFFFFF 00000074 FFFFFFFF ....ÿÿÿÿ...tÿÿÿÿ 00000090 FFFFFFFF 00000014 00000006 00000000 ÿÿÿÿ............ 000000A0 00000150 00000018 00000007 00000000 ...P............ 000000B0 00000000 0000000F 00000002 0000001C ................ 000000C0 00000038 000000B0 FFFFFFFF FFFFFFFF ...8...°ÿÿÿÿÿÿÿÿ 000000D0 00000014 00000006 00000150 000000E0 ...........P...à 000000E0 00000018 00000007 00000016 00000000 ................ 000000F0 0000000F 00000002 0000001C 00000074 ...............t 00000100 000000EC FFFFFFFF FFFFFFFF 00000014 ...ìÿÿÿÿÿÿÿÿ.... 00000110 00000006 00000230 00000120 00000018 .......0... .... 00000120 00000007 0000002C 00000000 0000000F .......,........ 00000130 00000002 0000001C 000000B0 00000128 ...........°...( 00000140 FFFFFFFF FFFFFFFF 00000014 00000006 ÿÿÿÿÿÿÿÿ........ 00000150 00000350 000001F0 00000018 00000007 ...P...ð........ 00000160 00000041 00000000 0000000F 00000002 ...A............ 00000170 0000001C 000000EC FFFFFFFF FFFFFFFF .......ìÿÿÿÿÿÿÿÿ 00000180 FFFFFFFF 00000014 00000006 00000540 ÿÿÿÿ...........@ 00000190 00000890 00000018 00000007 00000059 ...............Y 000001A0 00000000 00000000 00000000 00000000 ................ 000001B0 00000038 6C69622F 72686D2F 436C6561 ...8lib/rhm/Clea 000001C0 722E6670 6F000000 00746C69 622F7268 r.fpo....tlib/rh 000001D0 6D2F436C 6561722E 76706F00 000000B0 m/Clear.vpo....° 000001E0 6C69622F 72686D2F 436F7079 2E66706F lib/rhm/Copy.fpo 000001F0 00000000 EC6C6962 2F72686D 2F646566 ....ìlib/rhm/def 00000200 61756C74 2E66706F 00000001 286C6962 ault.fpo....(lib 00000210 2F72686D 2F646566 61756C74 2E76706F /rhm/default.vpo 00000220 00000000 00000000 00000000 00000000 ................ 00000230 71726300 66696C65 2D746162 6C650066 qrc.file-table.f 00000240 696C6500 73726300 69640000 00000000 ile.src.id...... 00000250 00001B5C 00000006 00000150 00000003 ...\.......P.... 00000260 00000020 000000F0 00000040 00000110 ... ...ð...@.... 00000270 00000418 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 00000280 000000BC 00000000 000000B0 00000000 ...¼.......°.... 00000290 00001001 00000000 00000001 00000000 ................ 000002A0 00000418 00000AC5 00001005 FFFFFFFF .......Å....ÿÿÿÿ 000002B0 000000CC 00000000 00000000 000000C6 ...Ì...........Æ 000002C0 00001002 FFFFFFFF 00000001 00000000 ....ÿÿÿÿ........ 000002D0 00000418 00000AC6 00001005 FFFFFFFF .......Æ....ÿÿÿÿ 000002E0 000000DC 00000000 00000000 000000D5 ...Ü...........Õ 000002F0 00001002 FFFFFFFF 00000001 00000000 ....ÿÿÿÿ........ 00000300 00000002 00000030 00000010 5F436C65 .......0...._Cle 00000310 6172436F 6C00434F 4C4F5200 6D61696E arCol.COLOR.main 00000320 2E636F6C 00434F4C 4F523100 6D61696E .col.COLOR1.main 00000330 2E636F6C 31000000 00000000 00000000 .col1........... 00000340 00000004 00000000 00000000 0000FFFF ..............ÿÿ 00000350 00000300 00000000 00000000 00000000 ................ 00000360 1E000100 C8021C9D C8000001 C8000001 ....È...È...È... 00000370 00000000 00000000 00000000 00000000 ................ 00000380 1E050100 C8021C9D C8000001 C8000001 ....È...È...È... 00000390 00000000 00000000 00000000 00000000 ................ 000003A0 00001B5B 00000006 000000E0 00000002 ...[.......à.... 000003B0 00000020 000000B0 00000010 000000D0 ... ...°.......Ð 000003C0 00000418 00000841 00001005 FFFFFFFF .......A....ÿÿÿÿ 000003D0 00000089 00000000 00000000 00000080 ...‰...........€ 000003E0 00001001 00000000 00000001 00000000 ................ 000003F0 00000418 000008C3 00001005 FFFFFFFF .......Ã....ÿÿÿÿ 00000400 00000099 00000000 00000000 00000090 ...™............ 00000410 00001002 00000001 00000001 00000000 ................ 00000420 504F5349 54494F4E 00706F73 5F696E00 POSITION.pos_in. 00000430 504F5349 54494F4E 00706F73 5F6F7574 POSITION.pos_out 00000440 00000000 00000000 00000000 00000000 ................ 00000450 00000001 00000000 00000001 00000001 ................ 00000460 00000000 00000000 00000000 00000000 ................ 00000470 401F9C6C 0040000D 8106C083 6041FF81 @.œl.@....Àƒ`Aÿ. 00000480 00001B5C 00000006 00000120 00000003 ...\....... .... 00000490 00000020 000000F0 00000010 00000110 ... ...ð........ 000004A0 00000417 00000C94 00001005 FFFFFFFF .......”....ÿÿÿÿ 000004B0 000000BA 00000000 00000000 000000B0 ...º...........° 000004C0 00001001 00000000 00000001 00000000 ................ 000004D0 0000042A 00000800 00001006 FFFFFFFF ...*........ÿÿÿÿ 000004E0 000000CC 00000000 00000000 000000C3 ...Ì...........à 000004F0 00001001 00000001 00000001 00000000 ................ 00000500 00000418 00000AC5 00001005 FFFFFFFF .......Å....ÿÿÿÿ 00000510 000000DB 00000000 00000000 000000D5 ...Û...........Õ 00000520 00001002 FFFFFFFF 00000001 00000000 ....ÿÿÿÿ........ 00000530 54455843 4F4F5244 30007465 78636F6F TEXCOORD0.texcoo 00000540 72640054 4558554E 49543000 5F436F70 rd.TEXUNIT0._Cop 00000550 79546578 00434F4C 4F52006D 61696E2E yTex.COLOR.main. 00000560 636F6C00 00000000 00000000 00000000 col............. 00000570 00000001 00004000 00000000 0001FFFE ......@.......ÿþ 00000580 00000200 00000000 00000000 00000000 ................ 00000590 9E011700 C8011C9D C8000001 C8003FE1 ž...È...È...È.?á 000005A0 00001B5C 00000006 000001F0 00000005 ...\.......ð.... 000005B0 00000020 00000170 00000060 00000190 ... ...p...`.... 000005C0 00000418 00000AC5 00001005 FFFFFFFF .......Å....ÿÿÿÿ 000005D0 00000117 00000000 00000000 00000110 ................ 000005E0 00001001 00000000 00000001 00000000 ................ 000005F0 00000418 00000C94 00001005 FFFFFFFF .......”....ÿÿÿÿ 00000600 00000128 00000000 00000000 0000011E ...(............ 00000610 00001001 00000001 00000001 00000000 ................ 00000620 00000418 00000AC5 00001005 FFFFFFFF .......Å....ÿÿÿÿ 00000630 00000136 00000000 00000000 0000012F ...6.........../ 00000640 00001002 00000002 00000001 00000000 ................ 00000650 0000042A 00000800 00001006 FFFFFFFF ...*........ÿÿÿÿ 00000660 00000147 00000000 00000000 0000013E ...G...........> 00000670 00001001 00000003 00000001 00000000 ................ 00000680 00000415 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 00000690 00000158 00000000 00000150 00000000 ...X.......P.... 000006A0 00001001 00000004 00000001 00000000 ................ 000006B0 434F4C4F 52300063 6F6C5F69 6E005445 COLOR0.col_in.TE 000006C0 58434F4F 52443000 7465785F 696E0043 XCOORD0.tex_in.C 000006D0 4F4C4F52 3000636F 6C5F6F75 74005445 OLOR0.col_out.TE 000006E0 58554E49 5430005F 54657800 00000000 XUNIT0._Tex..... 000006F0 00000001 00000050 5F546578 456E6162 .......P_TexEnab 00000700 6C656400 00000000 00000000 00000000 led............. 00000710 00000006 00004005 00000000 0001FFFE ......@.......ÿþ 00000720 00000200 00000000 00000000 00000000 ................ 00000730 3F800140 C8011C9D C8000001 C8003FE1 ?€.@È...È...È.?á 00000740 9E021700 C8011C95 C8000001 C8003FE1 ž...È..•È...È.?á 00000750 1E020400 C9001C9D C8040001 C9000003 ....É...È...É... 00000760 1E7E7E00 C8001C9D C8000001 C8000001 .~~.È...È...È... 00000770 1E010400 C8041C9D 00020000 C9000001 ....È.......É... 00000780 00000000 00000000 00000000 00000000 ................ 00000790 00001B5B 00000006 00000890 0000001D ...[............ 000007A0 00000020 000007F0 00000080 00000810 ... ...ð...€.... 000007B0 00000418 00000841 00001005 FFFFFFFF .......A....ÿÿÿÿ 000007C0 0000059A 00000000 00000000 00000590 ...š............ 000007D0 00001001 00000000 00000001 00000000 ................ 000007E0 00000418 00000844 00001005 FFFFFFFF .......D....ÿÿÿÿ 000007F0 000005A8 00000000 00000000 000005A1 ...¨...........¡ 00000800 00001001 00000001 00000001 00000000 ................ 00000810 00000418 00000843 00001005 FFFFFFFF .......C....ÿÿÿÿ 00000820 000005B6 00000000 00000000 000005AF ...¶...........¯ 00000830 00001001 00000002 00000000 00000000 ................ 00000840 00000418 00000849 00001005 FFFFFFFF .......I....ÿÿÿÿ 00000850 000005C7 00000000 00000000 000005BD ...Ç...........½ 00000860 00001001 00000003 00000001 00000000 ................ 00000870 00000418 000008C3 00001005 FFFFFFFF .......Ã....ÿÿÿÿ 00000880 000005D8 00000000 00000000 000005CE ...Ø...........Î 00000890 00001002 00000004 00000001 00000000 ................ 000008A0 00000418 000008C5 00001005 FFFFFFFF .......Å....ÿÿÿÿ 000008B0 000005E7 00000000 00000000 000005E0 ...ç...........à 000008C0 00001002 00000005 00000001 00000000 ................ 000008D0 00000418 00000C94 00001005 FFFFFFFF .......”....ÿÿÿÿ 000008E0 000005F9 00000000 00000000 000005EF ...ù...........ï 000008F0 00001002 00000006 00000001 00000000 ................ 00000900 00000417 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 00000910 00000601 00000000 00000000 00000000 ................ 00000920 00001001 00000007 00000000 00000000 ................ 00000930 00000418 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 00000940 00000611 00000000 00000000 00000000 ................ 00000950 00001001 00000008 00000000 00000000 ................ 00000960 00000415 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 00000970 0000061E 00000000 00000000 00000000 ................ 00000980 00001001 00000009 00000000 00000000 ................ 00000990 00000418 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 000009A0 00000632 00000000 00000000 00000000 ...2............ 000009B0 00001001 0000000A 00000000 00000000 ................ 000009C0 00000418 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 000009D0 0000063B 00000000 00000000 00000000 ...;............ 000009E0 00001001 0000000B 00000000 00000000 ................ 000009F0 00000418 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 00000A00 00000644 00000000 00000000 00000000 ...D............ 00000A10 00001001 0000000C 00000000 00000000 ................ 00000A20 00000428 00000882 00001006 00000100 ...(...‚........ 00000A30 0000064E 00000000 00000000 00000000 ...N............ 00000A40 00001001 0000000D 00000001 00000000 ................ 00000A50 00000418 00000882 00001006 00000100 .......‚........ 00000A60 00000663 00000000 00000000 00000000 ...c............ 00000A70 00001001 0000000D 00000001 00000000 ................ 00000A80 00000418 00000882 00001006 00000101 .......‚........ 00000A90 0000067B 00000000 00000000 00000000 ...{............ 00000AA0 00001001 0000000D 00000001 00000000 ................ 00000AB0 00000418 00000882 00001006 00000102 .......‚........ 00000AC0 00000693 00000000 00000000 00000000 ...“............ 00000AD0 00001001 0000000D 00000001 00000000 ................ 00000AE0 00000418 00000882 00001006 00000103 .......‚........ 00000AF0 000006AB 00000000 00000000 00000000 ...«............ 00000B00 00001001 0000000D 00000001 00000000 ................ 00000B10 00000428 00000CB8 00001006 FFFFFFFF ...(...¸....ÿÿÿÿ 00000B20 000006C3 00000000 00000000 00000000 ...Ã............ 00000B30 00001001 0000000E 00000000 00000000 ................ 00000B40 00000418 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 00000B50 000006DE 00000000 00000000 00000000 ...Þ............ 00000B60 00001001 0000000E 00000000 00000000 ................ 00000B70 00000418 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 00000B80 000006FC 00000000 00000000 00000000 ...ü............ 00000B90 00001001 0000000E 00000000 00000000 ................ 00000BA0 00000418 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 00000BB0 0000071A 00000000 00000000 00000000 ................ 00000BC0 00001001 0000000E 00000000 00000000 ................ 00000BD0 00000418 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 00000BE0 00000738 00000000 00000000 00000000 ...8............ 00000BF0 00001001 0000000E 00000000 00000000 ................ 00000C00 00000428 00000CB8 00001006 FFFFFFFF ...(...¸....ÿÿÿÿ 00000C10 00000756 00000000 00000000 00000000 ...V............ 00000C20 00001001 0000000F 00000000 00000000 ................ 00000C30 00000418 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 00000C40 00000768 00000000 00000000 00000000 ...h............ 00000C50 00001001 0000000F 00000000 00000000 ................ 00000C60 00000418 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 00000C70 0000077D 00000000 00000000 00000000 ...}............ 00000C80 00001001 0000000F 00000000 00000000 ................ 00000C90 00000418 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 00000CA0 00000792 00000000 00000000 00000000 ...’............ 00000CB0 00001001 0000000F 00000000 00000000 ................ 00000CC0 00000418 00000CB8 00001006 FFFFFFFF .......¸....ÿÿÿÿ 00000CD0 000007A7 00000000 00000000 00000000 ...§............ 00000CE0 00001001 0000000F 00000000 00000000 ................ 00000CF0 00000443 00000882 00001007 000001D3 ...C...‚.......Ó 00000D00 000007D0 000007C0 00000000 00000000 ...Ð...À........ 00000D10 00001001 FFFFFFFE 00000001 00000000 ....ÿÿÿþ........ 00000D20 504F5349 54494F4E 3000706F 735F696E POSITION0.pos_in 00000D30 00434F4C 4F523000 636F6C5F 696E004E .COLOR0.col_in.N 00000D40 4F524D41 4C006E6F 725F696E 00544558 ORMAL.nor_in.TEX 00000D50 434F4F52 44300074 65785F69 6E00504F COORD0.tex_in.PO 00000D60 53495449 4F4E3000 706F735F 6F757400 SITION0.pos_out. 00000D70 434F4C4F 52300063 6F6C5F6F 75740054 COLOR0.col_out.T 00000D80 4558434F 4F524430 00746578 5F6F7574 EXCOORD0.tex_out 00000D90 005F4C69 67687444 69726563 74696F6E ._LightDirection 00000DA0 005F476C 6F62616C 436F6C6F 72005F47 ._GlobalColor._G 00000DB0 6C6F6261 6C436F6C 6F72456E 61626C65 lobalColorEnable 00000DC0 64005F41 6D626961 6E74005F 44696666 d._Ambiant._Diff 00000DD0 75736500 5F537065 63756C61 72005F4D use._Specular._M 00000DE0 6F64656C 76696577 50726F6A 65637469 odelviewProjecti 00000DF0 6F6E005F 4D6F6465 6C766965 7750726F on._ModelviewPro 00000E00 6A656374 696F6E5B 305D005F 4D6F6465 jection[0]._Mode 00000E10 6C766965 7750726F 6A656374 696F6E5B lviewProjection[ 00000E20 315D005F 4D6F6465 6C766965 7750726F 1]._ModelviewPro 00000E30 6A656374 696F6E5B 325D005F 4D6F6465 jection[2]._Mode 00000E40 6C766965 7750726F 6A656374 696F6E5B lviewProjection[ 00000E50 335D005F 4D6F6465 6C766965 77496E76 3]._ModelviewInv 00000E60 65727365 5472616E 73706F73 65005F4D erseTranspose._M 00000E70 6F64656C 76696577 496E7665 72736554 odelviewInverseT 00000E80 72616E73 706F7365 5B305D00 5F4D6F64 ranspose[0]._Mod 00000E90 656C7669 6577496E 76657273 65547261 elviewInverseTra 00000EA0 6E73706F 73655B31 5D005F4D 6F64656C nspose[1]._Model 00000EB0 76696577 496E7665 72736554 72616E73 viewInverseTrans 00000EC0 706F7365 5B325D00 5F4D6F64 656C7669 pose[2]._Modelvi 00000ED0 6577496E 76657273 65547261 6E73706F ewInverseTranspo 00000EE0 73655B33 5D005F54 65787475 72655472 se[3]._TextureTr 00000EF0 616E7366 6F726D00 5F546578 74757265 ansform._Texture 00000F00 5472616E 73666F72 6D5B305D 005F5465 Transform[0]._Te 00000F10 78747572 65547261 6E73666F 726D5B31 xtureTransform[1 00000F20 5D005F54 65787475 72655472 616E7366 ]._TextureTransf 00000F30 6F726D5B 325D005F 54657874 75726554 orm[2]._TextureT 00000F40 72616E73 666F726D 5B335D00 00000000 ransform[3]..... 00000F50 3F800000 00000000 00000000 00000000 ?€.............. 00000F60 696E7465 726E616C 2D636F6E 7374616E internal-constan 00000F70 742D3000 00000000 00000000 00000000 t-0............. 00000F80 00000008 00000000 00000001 00000109 ................ 00000F90 00004001 00000000 00000000 00000000 ..@............. 00000FA0 401F9C6C 0040030D 8106C083 6041FF84 @.œl.@....Àƒ`Aÿ„ 00000FB0 401F9C6C 0040080D 8106C083 6041FF9C @.œl.@....Àƒ`Aÿœ 00000FC0 00001C6C 005D3000 0186C083 60403FFC ...l.]0..†Àƒ`@?ü 00000FD0 00001C6C 0040000C 0106C083 6041DFFC ...l.@....Àƒ`Aßü 00000FE0 401F9C6C 01D0300D 8086C0C3 60403F80 @.œl.Ð0.€†ÀÃ`@?€ 00000FF0 401F9C6C 01D0200D 8086C0C3 60405F80 @.œl.Ð .€†ÀÃ`@_€ 00001000 401F9C6C 01D0100D 8086C0C3 60409F80 @.œl.Ð..€†ÀÃ`@Ÿ€ 00001010 401F9C6C 01D0000D 8086C0C3 60411F81 @.œl.Ð..€†ÀÃ`A..
P3T
P3TF
There are several variations of the CXML container structure used by themes, but one of the tables used by themes is a icontable containing one of more icon, where every entry is composed by the element icon (28 bytes) and his associated attributes: src (16 bytes), id (16 bytes), and size (16 bytes) for a total size of 76 bytes (or 0x4C)
This icontable substructure containing one of more icon is exactly the same than the file-table containing one or more file used by QRCF_2
- Notes:
- See: http://www.psdevwiki.com/ps3/Themes_%28.p3t%29#Theme_Name_.28.XML.29 for an example of an XML before compilation, and see: http://www.psdevwiki.com/ps3/Talk:Themes_%28.p3t%29#p3t_format.2C_p3tcompiler.2C_and_p3textractor_notes for a list of tags added by the compiler
RAF
RAFO
Offset | Size | Example | Name | Notes |
---|---|---|---|---|
CXML Header | ||||
0x00 | 0x04 | RAFO | Magic | |
0x04 | 0x04 | 00000110 | Version | 110 |
0x08 | 0x04 | 00000040 | Data table absolute start offset | 40 |
0x0C | 0x04 | 00001288 | Data table size | 1288 |
0x10 | 0x04 | 000012D0 | Filename table absolute start offset | 12D0 |
0x14 | 0x04 | 0000021C | Filename table size | 21C |
0x18 | 0x04 | 000014F0 | Strings table absolute start offset | 14F0 |
0x1C | 0x04 | 000001B1 | Strings table size | 1B1 |
0x20 | 0x04 | 000016B0 | Integer array absolute start offset | 16B0 (overlapped) |
0x24 | 0x04 | 00000000 | Integer array size | 0 |
0x28 | 0x04 | 000016B0 | Float array absolute start offset | 16B0 |
0x2C | 0x04 | 000000A0 | Float array size | A0 |
0x30 | 0x04 | 00001750 | File table absolute start offset | 1750 |
0x34 | 0x04 | 0018F9F0 | File table size | 18F9F0 |
0x38 | 0x04 | 00000000 | Unknown area absolute start offset | 0 |
0x3C | 0x04 | 00000000 | Unknown area size | 0 |
Data Table | ||||
element start (raf) | ||||
0x40 | 0x04 | 00000000 | xml element TAG name relative offset | 0 = raf |
0x44 | 0x04 | 00000001 | xml element number of attributes | 1 attribute |
0x48 | 0x04 | FFFFFFFF | parent element relative start offset | FFFFFFFF = parent doesnt exists |
0x4C | 0x04 | FFFFFFFF | previous brother element relative start offset | FFFFFFFF = previous brother doesnt exists |
0x50 | 0x04 | FFFFFFFF | next brother element relative start offset | FFFFFFFF = next brother doesnt exists |
0x54 | 0x04 | 0000002C | first children element relative start offset | 0x40 + 0x2C = 0x6C absolute |
0x58 | 0x04 | 00000FB0 | last children element relative start offset | 0x40 + 0xFB0 = 0xFF0 absolute |
attribute start "version" (is an attribute of "raf" element) | ||||
0x5C | 0x04 | 00000004 | xml attribute TAG name relative offset | 4 = version |
0x60 | 0x04 | 00000002 | xml attribute TAG type | 2 |
0x64 | 0x04 | 3F800000 | float | 3F800000 = 1.0 |
0x68 | 0x04 | 00000000 | Not used | 0 |
element start "scene" (is the 1st children of "raf" element) | ||||
0x6C | 0x04 | 0000000C | xml element TAG name relative offset | C = scene |
0x70 | 0x04 | 00000004 | xml element number of attributes | 4 attributes (camera_num, light_num, script_num, and actor_num) |
0x74 | 0x04 | 00000000 | parent element relative start offset | 0 = parent is raf |
0x78 | 0x04 | FFFFFFFF | previous brother element relative start offset | FFFFFFFF = previous brother doesnt exists |
0x7C | 0x04 | 00000750 | next brother element relative start offset | 0x40 + 0x750 = 0x790 absolute |
0x80 | 0x04 | 00000088 | first children element relative start offset | 0x40 + 0x88 = C8 absolute = first children is actor |
0x84 | 0x04 | 00000714 | last children element relative start offset | 0x40 + 714 = 754 absolute |
attribute start "camera_num" (is an attribute of "scene" element) | ||||
0x88 | 0x04 | 00000012 | xml attribute TAG name relative offset | 12 = camera_num |
0x8C | 0x04 | 00000001 | xml attribute TAG type | 1 |
0x90 | 0x04 | 00000001 | integer | 1 |
0x94 | 0x04 | 00000000 | Not used | 0 |
attribute start "light_num" (is an attribute of "scene" element) | ||||
0x98 | 0x04 | 0000001D | xml attribute TAG name relative offset | 1D = light_num |
0x9C | 0x04 | 00000001 | xml attribute TAG type | 1 |
0xA0 | 0x04 | 00000002 | integer | 2 |
0xA4 | 0x04 | 00000000 | Not used | 0 |
attribute start "script_num" (is an attribute of "scene" element) | ||||
0xA8 | 0x04 | 00000027 | xml attribute TAG name relative offset | 27 = script_num |
0xAC | 0x04 | 00000001 | xml attribute TAG type | 1 |
0xB0 | 0x04 | 00000001 | integer | 1 |
0xB4 | 0x04 | 00000000 | Not used | 0 |
attribute start "actor_num" (is an attribute of "scene" element) | ||||
0xB8 | 0x04 | 00000032 | xml attribute TAG name relative offset | 32 = actor_num |
0xBC | 0x04 | 00000001 | xml attribute TAG type | 1 |
0xC0 | 0x04 | 00000006 | integer | 6 |
0xC4 | 0x04 | 00000000 | Not used | 0 |
element start "actor" (is the children of "scene" element) | ||||
0xC8 | 0x04 | 0000003C | xml element TAG name relative offset | 3C = actor |
0xCC | 0x04 | 0000000C | xml element number of attributes | C = 12 attributes |
0xD0 | 0x04 | 0000002C | parent element relative start offset | 0x40 + 0x2C = 0x6C absolute = parent is scene |
0xD4 | 0x04 | FFFFFFFF | previous brother element relative start offset | FFFFFFFF = previous brother doesnt exists |
0xD8 | 0x04 | 00000164 | next brother element relative start offset | 0x40 + 0x164 = 1C4 absolute |
0xDC | 0X04 | FFFFFFFF | first children element relative start offset | FFFFFFFF = first children doesnt exists |
0xE0 | 0x04 | FFFFFFFF | last children element relative start offset | FFFFFFFF = last children doesnt exists |
attribute start "anim_speed" (is an attribute of "actor" element) | ||||
0xE4 | 0x04 | 00000042 | xml attribute TAG name relative offset | 42 = anim_speed |
0xE8 | 0x04 | 00000005 | xml attribute TAG type | 5 |
0xEC | 0x04 | 00000000 | Float Arrays Table offset | 0 |
0xF0 | 0x04 | 00000004 | Array size | 4 = 1.0,1.0,1.0,1.0 |
attribute start "scale" (is an attribute of "actor" element) | ||||
0xF4 | 0x04 | 0000004D | xml attribute TAG name relative offset | 4D = scale |
0xF8 | 0x04 | 00000005 | xml attribute TAG type | 5 |
0xFC | 0x04 | 00000004 | Float Arrays Table offset | 4 |
0x100 | 0x04 | 00000003 | Array size | 3 = 1.28,0.64,0.64 |
attribute start "uv_offset" (is an attribute of "actor" element) | ||||
0x104 | 0x04 | 00000053 | xml attribute TAG name relative offset | 53 = uv_offset |
0x108 | 0x04 | 00000005 | xml attribute TAG type | 5 |
0x10C | 0x04 | 00000007 | Float Arrays Table offset | 7 |
0x110 | 0x04 | 00000002 | Array size | 2 = 0.0,0.0 |
attribute start "color" (is an attribute of "actor" element) | ||||
0x114 | 0x04 | 0000005D | xml attribute TAG name relative offset | 5D = color |
0x118 | 0x04 | 00000005 | xml attribute TAG type | 5 |
0x11C | 0x04 | 00000000 | Float Arrays Table offset | 0 |
0x120 | 0x04 | 00000004 | Array size | 4 = 1.0,1.0,1.0,1.0 |
attribute start "anim_weight" (is an attribute of "actor" element) | ||||
0x124 | 0x04 | 00000063 | xml attribute TAG name relative offset | 63 = anim_weight |
0x128 | 0x04 | 00000005 | xml attribute TAG type | 5 |
0x12C | 0x04 | 00000009 | Float Arrays Table offset | 9 |
0x130 | 0x04 | 00000004 | Array size | 4 = 1.0,0.0,0.0,0.0 |
attribute start "material" (is an attribute of "actor" element) | ||||
0x134 | 0x04 | 0000006F | xml attribute TAG name relative offset | 6F = material |
0x138 | 0x04 | 00000008 | xml attribute TAG type | 8 |
0x13C | 0x04 | 00000000 | strings table offset | 0 = mtrl_logo |
0x140 | 0x04 | 00000000 | Not used | 0 |
attribute start "uv_scale" (is an attribute of "actor" element) | ||||
0x144 | 0x04 | 00000078 | xml attribute TAG name relative offset | 78 = uv_scale |
0x148 | 0x04 | 00000005 | xml attribute TAG type | 5 |
0x14C | 0x04 | 0000000D | Float Arrays Table offset | D |
0x150 | 0x04 | 00000002 | Array size | 2 = 1.0,-1.0 |
attribute start "id" (is an attribute of "actor" element) | ||||
0x154 | 0x04 | 00000081 | xml attribute TAG name relative offset | 6F = id |
0x158 | 0x04 | 00000007 | xml attribute TAG type | 7 |
0x15C | 0x04 | 0000000E | strings table offset | E = logo |
0x160 | 0x04 | 00000000 | Not used | 0 |
You can compare this table with the xml representation of colboot.raf contents in coldboot.raf talk page
- Attribute 8 means there is another element in the xml (a different element than the one who owns the attribute) with the same name (so the loopback of his string points to a different element). In this case coldboot.raf uses the name mtrl_logo 2 times (but is only stored one time in the string table):
<raf> <!-- this is a reduced version of coldboot.raf.cxml --> <scene> <actor material="mtrl_logo"/> </scene> <material-table> <material id="mtrl_logo"> </material-table> </raf>
Tools
CXML decompiler
Experimental python script made by flatz for research purposes, there was several versions of it where some minor changes where made, to read about that changes check the history of the page
The tool extracts the files inside a CXML container (CXML, QRCF, P3TF, RAFO, etc...), the extracted filenames contains the hexcodes for fileoffset and filelenght, additionally it generates an .xml that represents the original CXML structure where can be seen the order of the files and all the other data inside it
- Usage:
- You can copypaste the python code below and save it in your PC as cxmdecompiler.py then run it in command line without arguments to verify that it works fine (you need python v2.7 installed)
- The original files lines.qrc and coldboot.raf are zlib compressed (and the CXML decompiler cant read zlib compressed files). The command line examples below considers the files has been decompressed in a previous step (using a zlib tool), in that previous step the file-extension was renamed to "qrcf" and "rafo" (which are the decompressed versions where the cxml structure is fully readable and the tool can process it)
C:\>cxmldecompiler.py lines.qrcf lines.xml
C:\>cxmldecompiler.py coldboot.rafo coldboot.xml
Changelog --------- v1 alpha - Basic .cxml support v2 alpha - Fixed a bug related with RAFO header (coldboot.raf support added) v3 alpha - Fixed offset/length displacements in the function that locates float values (xml tag attributes related with x,y,z axis in 3D space now looks correct) v4 alpha - Floats precission increased v5 alpha - Floats precission adjusted (previous versions had errors in the output of coldboot.raf) v6 alpha - Now the extracted filenames contains the hexcodes for fileoffset and filelength, both values are needed for the SEARCH/REPLACE patterns to remap them in the internal .QRC structure, as can be seen in the experiments made here and here v7 alpha - Filenames simplifyed, is better to have the filenames standarized for automated/mass comparison purposes in between official and custom files
#!python2 import sys, os, struct from io import BytesIO from pprint import pprint def read_cstring(f): bytes = [] while True: byte = f.read(1) if byte == b'\x00': break elif byte == '': raise EOFError() else: bytes.append(byte) return b''.join(bytes) def check_file_magic(f, expected_magic): old_offset = f.tell() try: magic = f.read(len(expected_magic)) except: return False finally: f.seek(old_offset) return magic == expected_magic script_file_name = os.path.split(sys.argv[0])[1] script_file_base = os.path.splitext(script_file_name)[0] if len(sys.argv) < 2: print('CXML decompiler (c) flatz') print('Usage: {0} <cxml file> <xml file>'.format(script_file_name)) sys.exit() ENDIANNESS = '>' def write_raw(f, data): if type(data) == str: f.write(data) elif type(data) == unicode: f.write(data.decode('utf-8')) else: f.write(data) def write_indent(f, depth): write_raw(f, '\t' * depth) def write_line(f, data): write_raw(f, data) write_raw(f, '\n') INT_FMT = ENDIANNESS + 'i' FLOAT_FMT = ENDIANNESS + 'f' STRING_FMT = ENDIANNESS + 'ii' INT_ARRAY_FMT = ENDIANNESS + 'ii' FLOAT_ARRAY_FMT = ENDIANNESS + 'ii' FILE_FMT = ENDIANNESS + 'ii' ID_FMT = ENDIANNESS + 'i' ID_REF_FMT = ENDIANNESS + 'i' class Attribute(object): HEADER_FMT = ENDIANNESS + 'ii' HEADER_SIZE = struct.calcsize(HEADER_FMT) SIZE = HEADER_SIZE + max(struct.calcsize(INT_FMT), struct.calcsize(FLOAT_FMT), struct.calcsize(STRING_FMT), struct.calcsize(INT_ARRAY_FMT), struct.calcsize(FLOAT_ARRAY_FMT), struct.calcsize(FILE_FMT), struct.calcsize(ID_FMT), struct.calcsize(ID_REF_FMT)) TYPE_NONE = 0 TYPE_INT = 1 TYPE_FLOAT = 2 TYPE_STRING = 3 TYPE_INT_ARRAY = 4 TYPE_FLOAT_ARRAY = 5 TYPE_FILE = 6 TYPE_ID = 7 TYPE_ID_REF = 8 def __init__(self, element): self.element = element self.start = None self.name = None self.type = None self.offset = None self.length = None self.value = None def load(self, f): self.start = f.tell() data = f.read(self.HEADER_SIZE) self.name, self.type = struct.unpack(self.HEADER_FMT, data) data = f.read(self.SIZE - self.HEADER_SIZE) if self.type == self.TYPE_NONE: pass elif self.type == self.TYPE_INT: self.value, = struct.unpack(INT_FMT, data[:struct.calcsize(INT_FMT)]) elif self.type == self.TYPE_FLOAT: self.value, = struct.unpack(FLOAT_FMT, data[:struct.calcsize(FLOAT_FMT)]) elif self.type == self.TYPE_STRING: self.offset, self.length = struct.unpack(STRING_FMT, data[:struct.calcsize(STRING_FMT)]) elif self.type == self.TYPE_INT_ARRAY: self.offset, self.length = struct.unpack(INT_ARRAY_FMT, data[:struct.calcsize(INT_ARRAY_FMT)]) elif self.type == self.TYPE_FLOAT_ARRAY: self.offset, self.length = struct.unpack(FLOAT_ARRAY_FMT, data[:struct.calcsize(FLOAT_ARRAY_FMT)]) elif self.type == self.TYPE_FILE: self.offset, self.length = struct.unpack(FILE_FMT, data[:struct.calcsize(FILE_FMT)]) elif self.type == self.TYPE_ID: self.offset, = struct.unpack(ID_FMT, data[:struct.calcsize(ID_FMT)]) elif self.type == self.TYPE_ID_REF: self.offset, = struct.unpack(ID_REF_FMT, data[:struct.calcsize(ID_REF_FMT)]) return True def get_name(self): return self.element.document.get_string(self.name) def get_int(self): if self.type != self.TYPE_INT: return None return self.value def get_float(self): if self.type != self.TYPE_FLOAT: return None return self.value def get_string(self): if self.type != self.TYPE_STRING: return None value = self.element.document.get_string(self.offset) if len(value) != self.length: return None return value def get_int_array(self): if self.type != self.TYPE_INT_ARRAY: return None value = self.element.document.get_int_array(self.offset, self.length) if len(value) != self.length: return None return value def get_float_array(self): if self.type != self.TYPE_FLOAT_ARRAY: return None value = self.element.document.get_float_array(self.offset, self.length) if len(value) != self.length: return None return value def get_file(self): if self.type != self.TYPE_FILE: return None value = self.element.document.get_file(self.offset, self.length) return value def get_id(self): if self.type != self.TYPE_ID: return None id = self.element.document.get_id_string(self.offset) return id def get_id_ref(self): if self.type != self.TYPE_ID_REF: return None id = self.element.document.get_id_string(self.offset) element = Element(self.element.document) return [id, element] def dump(self, f, depth): pass #print(' ' * depth + 'Attribute:' + 'name:{0} type:{1}'.format(self.name, self.type), end='\n', file=f) class Element(object): HEADER_FMT = ENDIANNESS + 'iiiiiii' SIZE = struct.calcsize(HEADER_FMT) TAG_NAME = 0 ATTR_NUM = 1 PARENT = 2 PREV = 3 NEXT = 4 FIRST_CHILD = 5 LAST_CHILD = 6 def __init__(self, document): self.document = document self.start = None self.name = None self.num_attributes = None self.parent = None self.prev = None self.next = None self.first_child = None self.last_child = None def load(self, f): self.start = f.tell() self.name, self.num_attributes, self.parent, self.prev, self.next, self.first_child, self.last_child = struct.unpack(self.HEADER_FMT, f.read(self.SIZE)) return True def get_name(self): return self.document.get_string(self.name) def get_attribute(self, index): if index < 0 or index >= self.num_attributes: return None offset = self.start + Element.SIZE + index * Attribute.SIZE if not is_valid_attribute(self.document, offset): return None attribute = Attribute(self) f = BytesIO(self.document.tree_bin) f.seek(offset) attribute.load(f) return attribute def get_parent(self): if not is_valid_element(self.document, self.parent): return None element = Element(self.document) f = BytesIO(self.document.tree_bin) f.seek(parent) element.load(f) return element def get_first_child(self): if not is_valid_element(self.document, self.first_child): return None element = Element(self.document) f = BytesIO(self.document.tree_bin) f.seek(self.first_child) element.load(f) return element def get_last_child(self): if not is_valid_element(self.document, self.last_child): return None element = Element(self.document) f = BytesIO(self.document.tree_bin) f.seek(self.last_child) element.load(f) return element def get_prev_sibling(self): if not is_valid_element(self.document, self.prev): return None element = Element(self.document) f = BytesIO(self.document.tree_bin) f.seek(self.prev) element.load(f) return element def get_next_sibling(self): if not is_valid_element(self.document, self.next): return None element = Element(self.document) f = BytesIO(self.document.tree_bin) f.seek(self.next) element.load(f) return element def dump(self, f, depth): write_indent(f, depth) name = self.get_name() write_raw(f, '<' + name) for i in range(self.num_attributes): attribute = self.get_attribute(i) if attribute is None: return False write_raw(f, ' {0}='.format(attribute.get_name())) if attribute.type == Attribute.TYPE_NONE: write_raw(f, '\"null\"') elif attribute.type == Attribute.TYPE_INT: write_raw(f, '\"{0}\"'.format(attribute.get_int())) elif attribute.type == Attribute.TYPE_FLOAT: write_raw(f, '\"{0:3.7}\"'.format(attribute.get_float())) elif attribute.type == Attribute.TYPE_STRING: write_raw(f, '\"{0}\"'.format(attribute.get_string())) elif attribute.type == Attribute.TYPE_INT_ARRAY: write_raw(f, '\"') array = attribute.get_int_array() array_length = len(array) for j in range(array_length): write_raw(f, '{0:3.7}'.format(array[j])) if j + 1 < array_length: write_raw(f, ',') write_raw(f, '\"') elif attribute.type == Attribute.TYPE_FLOAT_ARRAY: write_raw(f, '\"') array = attribute.get_float_array() array_length = len(array) for j in range(array_length): write_raw(f, '{0}'.format(array[j])) if j + 1 < array_length: write_raw(f, ',') write_raw(f, '\"') elif attribute.type == Attribute.TYPE_FILE: file_name = 'Offset=0x{0:08X}, Length=0x{1:08X}.bin'.format(attribute.offset, attribute.length) file_data = attribute.get_file() with open(file_name, 'wb') as of: of.write(file_data) write_raw(f, '\"{0}\"'.format(file_name)) elif attribute.type == Attribute.TYPE_ID: write_raw(f, '\"{0}\"'.format(attribute.get_id())) elif attribute.type == Attribute.TYPE_ID_REF: id_entity = attribute.get_id_ref() write_raw(f, '\"{0}\"'.format(id_entity[0])) child_element = self.get_first_child() if not child_element is None: write_raw(f, '>\n') while not child_element is None: child_element.dump(f, depth + 1) child_element = child_element.get_next_sibling() write_indent(f, depth) write_raw(f, '</' + name + '>\n') else: write_raw(f, ' />\n') def is_valid_element(document, offset): if offset < 0 or offset + Element.SIZE > document.tree_size: return False element = Element(document) f = BytesIO(document.tree_bin) f.seek(offset) element.load(f) if element.num_attributes < 0 or offset + Element.SIZE + element.num_attributes * Attribute.SIZE > document.tree_size: return False return True def is_valid_attribute(document, offset): if offset < 0 or offset + Attribute.SIZE > document.tree_size: return False return True class Document(object): HEADER_FMT = ENDIANNESS + '4siiiiiiiiiiiii8x' HEADER_SIZE = struct.calcsize(HEADER_FMT) def __init__(self, file_prefix=''): self.file_prefix = file_prefix self.magic = None self.version = None self.tree_offset = None self.tree_size = None self.id_table_offset = None self.id_table_size = None self.string_table_offset = None self.string_table_size = None self.int_array_table_offset = None self.int_array_table_size = None self.float_array_table_offset = None self.float_array_table_size = None self.file_table_offset = None self.file_table_size = None self.tree_bin = None self.id_table_bin = None self.string_table_bin = None self.int_array_table_bin = None self.float_array_table_bin = None self.file_table_bin = None self.root = None def get_document_element(self): if not is_valid_element(self, 0): return None element = Element(self) f = BytesIO(self.tree_bin) element.load(f) return element def get_id_string(self, offset): if offset < 0 or offset >= self.id_table_size: return None f = BytesIO(self.id_table_bin) f.seek(offset) entity_offset, = struct.unpack(INT_FMT, f.read(struct.calcsize(INT_FMT))) return read_cstring(f) def get_string(self, offset): if offset < 0 or offset >= self.string_table_size: return None f = BytesIO(self.string_table_bin) f.seek(offset) return read_cstring(f) def get_int_array(self, offset, length): if offset < 0 or (offset + length) * struct.calcsize(INT_FMT) > self.int_array_table_size: return None f = BytesIO(self.int_array_table_bin) f.seek(offset * struct.calcsize(INT_FMT)) array = [] for i in range(length): value, = struct.unpack(INT_FMT, f.read(struct.calcsize(INT_FMT))) array.append(value) return array def get_float_array(self, offset, length): if offset < 0 or (offset + length) * struct.calcsize(FLOAT_FMT) > self.float_array_table_size: return None f = BytesIO(self.float_array_table_bin) f.seek(offset * struct.calcsize(FLOAT_FMT)) array = [] for i in range(length): value, = struct.unpack(FLOAT_FMT, f.read(struct.calcsize(FLOAT_FMT))) array.append(value) return array def get_file(self, offset, length): if offset < 0 or offset + length > self.file_table_size: return None return self.file_table_bin[offset:offset + length] def load(self, f): self.magic, self.version, self.tree_offset, self.tree_size, self.id_table_offset, self.id_table_size, self.string_table_offset, self.string_table_size, self.int_array_table_offset, self.int_array_table_size, self.float_array_table_offset, self.float_array_table_size, self.file_table_offset, self.file_table_size = struct.unpack(self.HEADER_FMT, f.read(self.HEADER_SIZE)) f.seek(self.tree_offset) self.tree_bin = f.read(self.tree_size) f.seek(self.id_table_offset) self.id_table_bin = f.read(self.id_table_size) f.seek(self.string_table_offset) self.string_table_bin = f.read(self.string_table_size) f.seek(self.int_array_table_offset) self.int_array_table_bin = f.read(self.int_array_table_size) f.seek(self.float_array_table_offset) self.float_array_table_bin = f.read(self.float_array_table_size) f.seek(self.file_table_offset) self.file_table_bin = f.read(self.file_table_size) self.root = self.get_document_element() return True def check(self, f): return check_file_magic(f, 'CXML') def dump(self, f=sys.stdout, depth=0): if self.root is None: return self.root.dump(f, depth) if len(sys.argv) < 3: print('error: insufficient options specified') sys.exit() cxml_file_path = sys.argv[1] if not os.path.isfile(cxml_file_path): print('error: invalid cxml file specified') sys.exit() xml_file_path = sys.argv[2] if os.path.exists(xml_file_path) and not os.path.isfile(xml_file_path): print('error: invalid xml file specified') sys.exit() cxml_file_base = os.path.splitext(cxml_file_path)[0] document = Document(cxml_file_base) with open(cxml_file_path, 'rb') as f: #if not document.check(f): # print 'error: invalid CXML file format' # sys.exit() document.load(f) with open(xml_file_path, 'wb') as f: write_raw(f, '<?xml version="1.0" encoding="utf-8"?>\n') document.dump(f)
CXML decompiler (exe for windows)
There are tools to pack a python script together with some python libraries into an executable .exe to run it in windows. Some versions of the CXML decompiler script was distributed in this format but most probably the download inks are dead or are old versions, if someone wants to upload some of them post the links here
- CXML decompiler v3 alpha, download links: http://multiupload.biz/dnsipf0dkssz/cxml_decompiler_v3_alpha_MultiUpload.biz.7z.html
|