CXML Containers: Difference between revisions

From PS3 Developer wiki
Jump to navigation Jump to search
m (Example of how to remove margins and reduce padding of a <pre> inside a table)
Line 1,423: Line 1,423:
! rowspan=3 | TAGS table
! rowspan=3 | TAGS table
|- bgcolor="#8888ff"
|- bgcolor="#8888ff"
| 0x230 || 0x1B || qrc file-table file src id || Container identifyer (first tag) + other tags from MAKE.XML || style="padding:0px;" | <pre style="margin:0px; padding:3px; background:#8888ff; color:#ffffff; border:1px solid #8888ff;"> <qrc>
| 0x230 || 0x1B || qrc file-table file src id || Container identifyer (first tag) + other tags from MAKE.XML || style="padding:0px;" | <pre style="margin:0px; padding:3px; background:#8888ff; color:#ffffff; border:none;"> <qrc>
<file-table>
<file-table>
<file src=fileaccess id=filename/></pre>
<file src=fileaccess id=filename/></pre>

Revision as of 18:20, 12 September 2021

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

CXML Child Element definition
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
CXML Brother Element definition
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

CXML Attribute definitions
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.

Zlib Header (more info here and here)
byte index bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0
[0] CMF Compression info
  • 7 = indicates a 32K window size
Compression method
  • 8 = denotes the "deflate" compression
[1] FLG FLEVEL
  • 0 - compressor used fastest algorithm
  • 1 - compressor used fast algorithm
  • 2 - compressor used default algorithm
  • 3 - compressor used maximum compression, slowest algorithm
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)

rhm.qrc (v1.00)
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

RAF

RAFO

coldboot.raf (v2.70)
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)
Type This
C:\>cxmldecompiler.py lines.qrcf lines.xml
Type This
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
CXML decompiler v7 alpha (python script)
Edit-copy purple.svg.png
#!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