Resource Container CXML (RCO, QRC, Theme Files, RAF, CXML)

From Vita Developer wiki
Jump to navigation Jump to search

RCO

  • In PSvita the RCO's uses a cxml structure, with a header size of 0x50 and the magic identifyer RCOF
    • RCOF header is 0x10 bytes bigger than any cxml header in PS3 (this means there are 2 new tables added for the new cxml variant used in vita rco's). And endianess changed
    • Some of the extracted files (after cropped and zlib decompressed) are another variant of a cxml structure with identifyer RCSF. After a second extraction (with a cxml decompiler tool) the resulting file is a .xml containing only text strings (this double cxml method is used for .xml files that stores language translations)

Simply Vita RCO Extractor

Some RCO as Reference

notification_settings_plugin.rco (PSvita)
Offset Size Example Name Notes
CXML Header
0x00 0x04 RCOF Magic
0x04 0x04 10 01 00 00 Version
0x08 0x04 50 00 00 00 Tree absolute start offset, also header size in PS3 = Tree absolute start offset
0x0C 0x04 2C 15 00 00 Tree size in PS3 = Tree size
0x10 0x04 80 15 00 00 ID STR table absolute start offset in PS3 = ID table absolute start offset
0x14 0x04 B0 00 00 00 ID STR table size in PS3 = ID table size
0x18 0x04 30 16 00 00 ID INT table absolute start offset in PS3 = Strings table absolute start offset
0x1C 0x04 98 00 00 00 ID INT table size in PS3 = Strings table size
0x20 0x04 D0 16 00 00 Strings table absolute start offset in PS3 = Integer array absolute start offset
0x24 0x04 F1 01 00 00 Strings table size in PS3 = Integer array size
0x28 0x04 D0 18 00 00 overlapped (not used, but present in the header to keep the structure standards) in PS3 = Float array absolute start offset
0x2C 0x04 00 00 00 00 empty in PS3 = Float array size
0x30 0x04 D0 18 00 00 Styles ID INT table absolute start offset in PS3 = File table absolute start offset
0x34 0x04 34 00 00 00 Styles ID INT table size in PS3 = File table size
0x38 0x04 10 19 00 00 Integer array absolute start offset in PS3 = Unknown area absolute start offset
0x3C 0x04 2C 00 00 00 Integer array size in PS3 = Unknown area size
0x40 0x04 40 19 00 00 Float array absolute start offset in PS3 = Not present
0x44 0x04 8C 00 00 00 Float array size in PS3 = Not present
0x48 0x04 D0 19 00 00 File table absolute start offset in PS3 = Not present
0x4C 0x04 60 89 00 00 File table size in PS3 = Not present
Tables
0x50 Tree starts here

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 idstrtable_offset;
               int idstrtable_size;
               int idinttable_offset;
               int idinttable_size;
               int stringtable_offset;
               int stringtable_size;
               int styleidtable_offset;
               int styleidtable_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 unk = 4;
               int STYLE_ID = 5;
               int INTEGER_ARRAY = 6;
               int FLOAT_ARRAY = 7;
               int DATA = 8;
               int ID_STR_REF = 9;
               int ID_STR_NO_REF = 10;
               int ID_INT_REF = 11;
               int ID_INT_NO_REF = 12;
               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_IDSTRTable,
               AllocationType_Alloc_IDINTTable,
               AllocationType_Alloc_StringTable,
               AllocationType_Alloc_IntArrayTable,
               AllocationType_Alloc_FloatArrayTable,
               AllocationType_Alloc_FileTable,
               AllocationType_Alloc_StyleIDTable,
 
               AllocationType_Free_Tree,
               AllocationType_Free_IDSTRTable,
               AllocationType_Free_IDINTTable,
               AllocationType_Free_StringTable,
               AllocationType_Free_IntArrayTable,
               AllocationType_Free_FloatArrayTable,
               AllocationType_Free_FileTable,
               AllocationType_AFree_StyleIDTable,
       };
      
       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 * idstrtable;
               unsigned int idstrtable_capacity;
               char * idinttable;
               unsigned int idinttable_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;
               char * styleidtable;
               unsigned int styleidtable_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 Root 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.

Attribute

Attribute types structure
Offset Length Name Attribute type
Integer Float String analysing... Style ID INT Integer Array Float Array File Ref ID STR ID STR Ref ID INT ID INT
0x0 0x4 Attribute name offset ________________________________________________________________________ xml tag string from the "strings table" __________________________________________________________________
0x4 0x4 Attribute type 1 2 3 4 5 6 7 8 9 A B C
0x8 0x4 variable 1 Integer value Float value String Offset analysing... Style ID INT offset Integer offset Float offset File offset Ref ID STR offset ID STR offset Ref ID INT offset ID INT offset
0xC 0x4 variable 2 unknown (usually 0) unknown (usually 0) String Length analysing... ID count (usually 4) Integer count Float count File size unknown (usually 0) unknown (usually 0) unknown (usually 0) unknown (usually 0)

Container Common Structure

RCO

ZLIB Compressed level 9 (only container)

RCOF

RCOF (Resources Container Flat?)

  • Example from FW?? notification_settings_plugin.rco:
Offset(h) 00 01 02 03  04 05 06 07
00000000  52 43 4F 46  10 01 00 00 RCOF....
Name Offset Size Example Remark
Magic 0x00 0x04 52 43 4F 46 'RCOF'
Version 0x04 0x04 00 00 01 10* CXML version '1.10'
* reversed little endian


Zlib Header (source)
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.


About Data Compression:

Main Header

The header contains an identifier of the container (magic), his version, and allows to store the "absolute start offset" and "size" of 9 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 PS3 files like .RAF, .QRC and .P3T with some variations) so the usage of this tables can vary, in this example there is 1 "not used table":
    • one of the "not used table" (at offset 0x18D0 with a size of 0) is placed before an used table (also at offset 0x18D0 but with a size of 0x34)


Offset(h) 00 01 02 03  04 05 06 07  08 09 0A 0B  0C 0D 0E 0F
00000000  52 43 4F 46  10 01 00 00  50 00 00 00  2C 15 00 00  RCOF....P...,...
00000010  80 15 00 00  B0 00 00 00  30 16 00 00  98 00 00 00  €...°...0...˜...
00000020  D0 16 00 00  F1 01 00 00  D0 18 00 00  00 00 00 00  Ð...ñ...Ð.......
00000030  D0 18 00 00  34 00 00 00  10 19 00 00  2C 00 00 00  Ð...4.......,...
00000040  40 19 00 00  8C 00 00 00  D0 19 00 00  60 89 00 00  @...Œ...Ð...`‰..


Name Offset Size Example Remark
Magic 0x00 0x04 52 43 4F 46 'RCOF'
Version 0x04 0x04 00 00 01 10* CXML version '1.10'
Tree Table Offset 0x08 0x04 00 00 00 50*
Tree Table Size 0x0C 0x04 00 00 15 2C*
ID String Table Offset 0x10 0x04 00 00 15 80*
ID String Table Size 0x14 0x04 00 00 00 B0*
ID Integer Table Offset 0x18 0x04 00 00 16 30*
ID Integer Table Size 0x1C 0x04 00 00 00 98*
String Table Offset 0x20 0x04 00 00 16 D0*
String Table size 0x24 0x04 00 00 01 F1*
overlapped 0x28 0x04 00 00 18 D0* Overlapped
empty 0x2C 0x04 00 00 00 00 Not used
Styles ID Integer Table Offset 0x30 0x04 00 00 18 D0*
Styles ID Integer Table Size 0x34 0x04 00 00 00 34*
Integer Array Table Offset 0x38 0x04 00 00 19 10*
Integer Array Table Size 0x3C 0x04 00 00 00 2C*
Float Array Table Offset 0x38 0x04 00 00 19 40*
Float Array Table Size 0x3C 0x04 00 00 00 8C*
File Table Offset 0x38 0x04 00 00 19 D0*
File Table Size 0x3C 0x04 00 00 89 60*
* reversed little endian
  • Notes
    • The sizes doesn't includes the (possible) padding at the end of all tables


Tree Table

from notification_settings_plugin.rco FW??

Offset Size Example Remark
0x00 0x04 00 00 00 00 Root Element (Offset within String Table, in this case it will be <resource>)
0x04 0x04 00 00 00 02 Attribute Counter
0x08 0x04 FF FF FF FF Parent
0x0C 0x04 FF FF FF FF Previous Brother
0x10 0x04 FF FF FF FF Next Brother
0x14 0x04 00 00 00 3C First Child within the root Element <resource>
0x18 0x04 00 00 0D 74 Last Child within the root Element <resource> (which will also our Next Base Element to read)
0x1C 0x04 00 00 00 09 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 CD CC CC 3D Float value (0.1) [version="0.1"]
0x28 0x04 00 00 00 00 empty value
0x2C 0x04 00 00 00 11 String Pointer (in this case "type")
0x30 0x04 00 00 00 03 Type descriptor (3 == String)
0x34 0x04 00 00 00 16 Offset within String Table of String to read
0x38 0x04 00 00 00 06 Length of String to read (0x06 == "normal") [type="normal"]
0x3C 0x04 00 00 00 1D Next Element (Offset within String Table, in this case it will be <filetable>)
0x40 0x04 00 00 00 00 Attribute Count
0x44 0x04 00 00 00 00 Parent (Offset within XML Table, pointing to Root Element)
0x48 0x04 FF FF FF FF Previous Brother
0x4C 0x04 00 00 07 88 Next Brother
0x50 0x04 00 00 00 58 Last Child
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