This website is still under development!

XContent

XContent is the file system used by the Xbox 360 to store files of all types, such as downloadable content, GPDs, game content, and more. They use three types of formats, STFS (Secure Transacted File System), SVOD(Secure Virtual Offline Disk), and PEC(Profile Encrypted Content). All three versions are protected by multiple signatures to validate the packages.

Header

Header
Name Data Type Position Length
Magic String 0 0x4

Depending on what the value of the magic is, the structure of the header changes. If the package is signed with the public key(CON ), then the first one, otherwise(LIVE, PIRS), the second.

Public
Name Data Type Position Length
Public Key Certificate Size Short 0x4 0x2
Certificate Owner Console ID Byte Array 0x6 0x5
Certificate Owner Console Part Number String 0xB 0x14
Certificate Owner Console Type Byte 0x1F 0x1
Certificate Date Of Generation String 0x20 0x8
Public Exponent Byte Array 0x28 0x4
Public Modulus Byte Array 0x2C 0x80
Certificate Signature Byte Array 0xAC 0x100
Signature Byte Array 0x1AC 0x80

Private
Name Data Type Position Length
Package Signature Byte Array 0x4 0x100
Padding Byte Array 0x104 0x128

The following table is a continuation of the previous ones, meaning it is the same despite the type of package.

'Metadata Hash' is generated from the start of the metadata to the start of the first hash table. You could also use 'Header Size' instead of calculating.

Header
Name Data Type Position Length
License Data License Entry 0x22C 0x10
Metadata Hash SHA-1 0x32C 0x14
Header Size Integer 0x340 0x4

License Entry
Name Data Type Position Length
License Data Long 0 0x8
Unknown Integer 0x8 0x4
License Flags Integer 0xC 0x4

Metadata

Metadata
Name Data Type Position Length
Content Type Content Type 0x344 0x4
Metadata Version Metadata Version 0x348 0x4
Content Size Long 0x34C 0x8
Media ID Unsigned Integer 0x354 0x4
Version Integer 0x358 0x4
Base Version Integer 0x35C 0x4
Title ID Unsigned Integer 0x360 0x4
Platform Platform 0x364 0x1
Executable Type Byte 0x365 0x1
Disc Number Byte 0x366 0x1
Disc In Set Byte 0x367 0x1
Save Game ID Unsigned Integer 0x368 0x4
Console ID Byte Array 0x36C 0x5
Profile ID Byte Array 0x371 0x8
Volume Descriptor Volume Descriptor 0x379 0x1
Data File Count Integer 0x39D 0x4
Total Data Size Long 0x3A1 0x8
Volume Descriptor Type Volume Descriptor Type 0x3A9 0x4
Unknown Integer 0x3AD 0x4

The following tables are dependent on the metadata version.

General
Name Data Type Position Length
Padding Byte Array 0x3B1 0x4C
Device ID Byte Array 0x3FD 0x14
Display Name Unicode String Array 0x411 0xC
Display Description Unicode String Array 0xD11 0xC
Publisher Name Unicode String 0x1611 0x80
Title Name Unicode String 0x1691 0x80
Transfer Flags Byte 0x1711 0x1
Thumbnail Image Size Integer 0x1712 0x4
Title Thumbnail Image Size Integer 0x1716 0x4
Thumbnail Image Byte Array 0x171A 0x4000
Title Thumbnail Image Byte Array 0x571A 0x4000

Media
Name Data Type Position Length
Series ID Byte Array 0x3B1 0x10
Season ID Byte Array 0x3C1 0x10
Season Number Short 0x3D1 0x2
Episode Number Short 0x3D3 0x2
Padding Byte Array 0x3D5 0x28
Device ID Byte Array 0x3FD 0x14
Display Name Unicode String Array 0x411 0xC
Display Description Unicode String Array 0xD11 0xC
Publisher Name Unicode String 0x1611 0x80
Title Name Unicode String 0x1691 0x80
Transfer Flags Byte 0x1711 0x1
Thumbnail Image Size Integer 0x1712 0x4
Title Thumbnail Image Size Integer 0x1716 0x4
Thumbnail Image Byte Array 0x171A 0x3D00
Additional Display Names Unicode String Array 0x541A 0x6
Title Thumbnail Image Byte Array 0x571A 0x4000
Additional Display Descriptions Unicode String Array 0x941A 0x6

Metadata Version
Name Value
General 0x1
Media 0x2

Platform
Name Value
Xbox 360 0x2
PC 0x4

Volume Descriptor Type
Name Value
STFS 0
SVOD 0x1

Volume Descriptor

The structure you'd like to use depends on the value of 'Volume Descriptor Type'.

STFS
Name Data Type Position Length
Volume Descriptor Size Byte 0 0x1
Unknown Byte 0x1 0x1
Block Seperation Byte 0x2 0x1
File Table Block Count Short 0x3 0x2
File Table Block Index 24-Bit Integer 0x5 0x3
Top Hash Table Hash SHA-1 0x8 0x14
Total Allocated Block Count Integer 0x1C 0x4
Total Unallocated Block Count Byte 0x20 0x4

SVOD
Name Data Type Position Length
Volume Descriptor Size Byte 0 0x1
Block Cache Element Count Byte 0x1 0x1
Worker Thread Processor Byte 0x2 0x1
Worker Thread Priority Byte 0x3 0x1
Hash SHA-1 0x4 0x14
Device Features Byte 0x18 0x1
Data Block Count 24-Bit Integer 0x19 0x3
Data Block Position 24-Bit Integer 0x1C 0x3
Padding Byte Array 0x1F 0x5

File Table

The 'File Table Block Index' value indicates where exactly you'd find this collection of bytes. These blocks are only filled with the following structure that directs you to the locations of actual file data.

File Table Entry
Name Data Type Position Length
File Name String 0 0x28
Flags Byte 0x28 0x1
Allocated Block Count 24-Bit Integer 0x29 0x3
Total Block Count 24-Bit Integer 0x2C 0x3
Block Index 24-Bit Integer 0x2F 0x3
Directory Index Short 0x32 0x2
Length Of File Integer 0x34 0x4
Last Updated Timestamp XeTimestamp 0x38 0x4
Last Accessed Timestamp XeTimestamp 0x3C 0x4

'Flags' contains both the length of the filename and extra flags, meaning that this value is important when editing the filename. The table below describes the bitfield.

Flags
Name Bit
Length 0 - 5
Consecutive Blocks 6
Directory 7

All three variables, 'Allocated Block Count', 'Total Block Count', and 'Block Index', are little-endian.

'Directory Index' refers to the zero-indexed file entry that is the parent or directory of the current. A value of -1 (0xFFFF) means that it is in the root directory.

Blocks

In all XContent packages, information outside the header is stored in blocks. Each block is 0x1000 (4096) bytes large. Every 0xAA (170) blocks, there is a hash table that contains a hash of each previous block. Every 0x70E4 (0xAA2) blocks, there is a hash table that contains a hash of each hash table before it. Hash tables are not included in the block indices, meaning you'll need to skip them. The following equation should help better comprehension of this subject:

location = firstBlock + ((blockIndex + (blockIndex / 0xAA)) * 0x1000)

Keep in mind that you should not use any decimals or fractions. For example, if blockIndex were 0x5, it divided by 0xAA is a decimal, but it rounds to 0, meaning no hash table has been present, yet if it were 0x216:

0x216 / 0xAA = 3.14117647059

If you round it (3), then 0x3 hash blocks have been passed.

Since files are not always consecutive, meaning you cannot always just go to the first block and read however many bytes it has, you'll need to find the next block. This is possible by going to the current hash table entry, and using the 'Next Block' variable.

Hash Table
Name Data Type Position Length
Hash SHA-1 0 0x14
Status Status 0x14 0x1
Next Block Index 24-Bit Integer 0x15 0x3

Take key note of the 'Status' variable. You need to utilize it to correctly format packages. It can also be used to help determine what can be cleaned to make the file smaller.

Status
Name Value
Unused 0
Unused (Previously Used) 0x40
Used (Currently) 0x80
Used (Newly Created) 0xC0