Difference between revisions of "XDVDFS"
(→Version 4361) |
(→Volume descriptor) |
||
(24 intermediate revisions by 2 users not shown) | |||
Line 12: | Line 12: | ||
=== Volume descriptor === | === Volume descriptor === | ||
− | + | The Volume descriptor islocated at Sector #32 and #33 of the game partition. | |
− | The Volume descriptor | ||
− | * ''' | + | * '''Sector #32:''' |
− | + | {| class="wikitable" | |
+ | ! Offset !! Type !! Field !! Notes | ||
+ | |- | ||
+ | |0x0 || ascii_char[20] || MAGIC|| MICROSOFT*XBOX*MEDIA | ||
+ | |- | ||
+ | |0x14 || u32 || Root Directory Table Sector || Multiply with 0x800 for offset | ||
+ | |- | ||
+ | |0x18 || u32 || Root Directory Table Size || Size in bytes. Always multiple of 0x800 | ||
+ | |- | ||
+ | |0x1C || u64 || || Timestamp (LDAP/Win32 FILETIME) | ||
+ | |- | ||
+ | |0x7EC || ascii_char[20] || MAGIC|| MICROSOFT*XBOX*MEDIA | ||
+ | |} | ||
− | ==== | + | * '''Sector #33:''' The first 24 Bits is the magic. It is always "XBOX_DVD_LAYOUT_TOOL_SIG". {{FIXME|reason=Describe version information}} |
+ | |||
+ | ==== Examples ==== | ||
+ | |||
+ | <!-- The "Wave n" is not a standard naming and I just made it up myself; we should confirm these and possibly find a better name - JayFoxRox --> | ||
+ | {{FIXME|reason=The tool names appearing in this section are guessed by me, we should confirm each of these - JayFoxRox}} | ||
+ | {{FIXME|reason=This lacks a couple of XDK versions}} | ||
+ | {{FIXME|reason=The byte offsets of each version field are missing}} | ||
+ | |||
+ | ===== Wave 1 ===== | ||
+ | |||
+ | Developers used xblayout to create DVD layout. | ||
+ | Then generated the final image using xbpremaster. | ||
+ | The final image was submitted to Microsoft. | ||
+ | |||
+ | * [[Azurik: Rise of Perathia]] (NTSC) | ||
+ | ** xblayout version: 1.0.3926.1 | ||
+ | ** xbpremaster version: 1.0.3926.1 | ||
+ | * [[Genma Onimusha]] (PAL) | ||
+ | ** xblayout version: 1.0.4039.1 | ||
+ | ** xbpremaster version: 1.0.4039.2 | ||
+ | * [[Max Payne]] (PAL) | ||
+ | ** xblayout version: 1.0.4134.1 | ||
+ | ** xbpremaster version: 1.0.4242.1 | ||
+ | * [[Petit Copter]] (Japanese) | ||
+ | ** xblayout version: 1.0.4361.1 | ||
+ | ** xbpremaster version: 1.0.4361.2 | ||
+ | * [[007 - Agent Under Fire]] (PAL) | ||
+ | ** xblayout version: 1.0.4432.1 | ||
+ | ** xbpremaster version: 1.0.4432.1 | ||
+ | |||
+ | ===== Wave 2 ===== | ||
+ | |||
+ | {{FIXME|reason=This is a theory. Confirm please}}. | ||
+ | Developers used a new version of xblayout and submitted the layout + content to Microsoft | ||
+ | |||
+ | Microsoft generated the final image. | ||
+ | |||
+ | Sometime during this wave, the new padding algorithm got introduced. Judging from the examples below, the padding algorithm does not seem to be bound to the xblayout version or to a specific date. | ||
+ | |||
+ | * [[Metal Gear Solid 2 - Substance]] (NTSC) | ||
+ | ** xblayout version: 1.0.4721.1 (old algorithm) | ||
+ | * [[Hitman 2 - Silent Assassin]] (France) (Original) | ||
+ | ** xblayout version: 1.0.4721.1 (new algorithm) | ||
+ | ** DMI Timestamp: 2002/09/18 | ||
+ | * [[Hitman 2 - Silent Assassin]] (France) (Classic Edition) | ||
+ | ** xblayout version: 1.0.4721.1 (old algorithm) | ||
+ | ** DMI Timestamp: 2002/12/03 | ||
+ | * [[Blade II]] (NTSC) | ||
+ | ** xblayout version: 1.0.4808.1 (old algorithm) | ||
+ | * [[Battle Engine Aquila]] (PAL) | ||
+ | ** xblayout version: 1.0.4831.1 (new algorithm) | ||
+ | Other Examples of games with 1.0.4721.1 version that don't use the old algorithm: Mat Hoffman's Pro BMX 2 (France), MLB SlugFest 2003 (USA), NCAA Football 2003 (USA), Phantom Crash (USA), Syberia (USA, Europe) | ||
+ | |||
+ | ===== Wave 3 ===== | ||
+ | |||
+ | {{FIXME|reason=This is a theory. Confirm please}}. | ||
+ | Same as wave 2 | ||
+ | * [[Metal Gear Solid 2 - Substance]] (PAL) | ||
+ | ** xblayout version: 1.0.5120.1 | ||
+ | * [[Shenmue II]] (PAL) | ||
+ | ** xblayout version: 1.0.5120.1 | ||
+ | |||
+ | ===== Wave 4 ===== | ||
+ | |||
+ | {{FIXME|reason=This is a theory. Confirm please}}. | ||
+ | Same as wave 3, but developers now had to use the xbgamedisc tool instead of xblayout. | ||
+ | The mastering tool used by microsoft also leaves a version identifier now. | ||
− | + | * [[Star Wars - Knights of the Old Republic]] (PAL) | |
+ | ** xbgamedisc version: 2.1.0.5233.1 | ||
+ | ** mastering tool version: 2.1.0.5233.1 | ||
+ | * [[Indiana Jones and the Emperor's Tomb]] (PAL) | ||
+ | ** xbgamedisc version: 2.1.0.5233.1 | ||
+ | ** mastering tool version: 2.1.0.5233.1 | ||
+ | * [[Dynasty Warriors 4]] (PAL) | ||
+ | ** xbgamedisc version: 2.1.0.5344.1 | ||
+ | ** mastering tool version: 2.1.0.5344.1 | ||
+ | * [[The Matrix - Path of Neo]] (PAL) | ||
+ | ** xbgamedisc version: 2.1.0.5849.1 | ||
+ | ** mastering tool version: 2.1.0.5849.1 | ||
+ | * [[The Suffering - Ties That Bind]] | ||
+ | ** xbgamedisc version: 2.1.0.5849.1 | ||
+ | ** mastering tool version: 2.1.0.5849.1 | ||
+ | * [[Reservoir Dogs]] (PAL) | ||
+ | ** xbgamedisc version: 2.1.0.5849.1 | ||
+ | ** mastering tool version: 2.1.0.5849.1 | ||
=== Directory Entry === | === Directory Entry === | ||
Line 42: | Line 137: | ||
=== Random blocks === | === Random blocks === | ||
− | ==== Version | + | ==== Version 3926 - 4808 ==== |
Seeded and then starting to emit bytes in data area. | Seeded and then starting to emit bytes in data area. | ||
− | Filled with algorithm 1 (2048 bytes | + | Filled with the following algorithm: |
+ | |||
+ | <pre> | ||
+ | // State | ||
+ | uint32_t a; | ||
+ | uint32_t b; | ||
+ | uint32_t c; | ||
+ | |||
+ | // Helper | ||
+ | static uint32_t Value(void) { | ||
+ | uint64_t result; | ||
+ | result = c; | ||
+ | result += 1; | ||
+ | result *= b; | ||
+ | result %= 0xFFFFFFFB; | ||
+ | c = result & 0xFFFFFFFF; | ||
+ | return c ^ a; | ||
+ | } | ||
+ | |||
+ | // buffer must be at even address, length must be multiple of 2 | ||
+ | void Fill(uint16_t* buffer, size_t length) { | ||
+ | while(length >= 2) { | ||
+ | *buffer++ = Value() >> 8; | ||
+ | length -= 2; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void Seed() { | ||
+ | const uint32_t b_seeds[8] = { | ||
+ | 0x52F690D5, | ||
+ | 0x534D7DDE, | ||
+ | 0x5B71A70F, | ||
+ | 0x66793320, | ||
+ | 0x9B7E5ED5, | ||
+ | 0xA465265E, | ||
+ | 0xA53F1D11, | ||
+ | 0xB154430F | ||
+ | }; | ||
+ | |||
+ | FILETIME ft; | ||
+ | GetSystemTimeAsFileTime(&ft); | ||
+ | uint32_t seed = ft.dwLowDateTime ^ ft.dwHighDateTime; | ||
+ | a = 0; | ||
+ | b = b_seeds[seed & 7]; | ||
+ | c = seed; | ||
+ | a = Value(); | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | The RNG is seeded when the mastering tool / wizard is started. | ||
+ | The first portion of the code to use this random number generator is the code which generates layer 0 and layer 1. | ||
+ | |||
+ | ==== Version 4831 - 5849 ==== | ||
+ | |||
+ | The algorithm was switched to RC4-256-drop-2048. | ||
+ | |||
+ | <pre> | ||
+ | |||
+ | #include <openssl/rc4.h> | ||
+ | |||
+ | RC4_KEY rc4key; | ||
+ | |||
+ | void Fill(uint8_t* buffer, size_t length) { | ||
+ | // We need a zero buffer as OpenSSL will want to XOR the keystream with data. | ||
+ | // The XDVDFS random data is the keystream without changes, so we let XOR OpenSSL XOR with 0x00 bytes. | ||
+ | uint8_t zero_buffer[length]; | ||
+ | memset(zero_buffer, 0x00, length); | ||
+ | RC4(&rc4key, length, zero_buffer, buffer); | ||
+ | } | ||
+ | |||
+ | void Seed() { | ||
+ | union { | ||
+ | uint8_t raw[16]; | ||
+ | struct { | ||
+ | struct _FILETIME SystemTimeAsFileTime; // first 8 bytes, little-endian | ||
+ | uint64_t tsc; // later 8 bytes, little-endian | ||
+ | }; | ||
+ | } key; | ||
+ | |||
+ | // Initialize seed | ||
+ | key.tsc = rdtsc(); | ||
+ | GetSystemTimeAsFileTime(&key.SystemTimeAsFileTime); | ||
+ | RC4_set_key(&rc4key, 16, &key); | ||
+ | |||
+ | // Drop the first 2048 bytes of the RC4 keystream | ||
+ | uint8_t discard_buffer[2048]; | ||
+ | Fill(discard_buffer, 2048); | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | The RNG is seeded when the mastering tool / wizard is started. | ||
+ | The first portion of the code to use this random number generator is the code which generates layer 0 and layer 1. | ||
+ | |||
+ | Edit: This assumption is not true, at least not for all instances. For example, all region variants of Conker Live & Reloaded share the same padding stream. | ||
=== Security blocks === | === Security blocks === |
Latest revision as of 15:47, 6 March 2022
XDVDFS (Also known as XISO) is the image format used for Xbox Game Discs. It is stored in the data area.
Format
Each sector is 2048 bytes.
Filesystem
[FIXME]
Volume descriptor
The Volume descriptor islocated at Sector #32 and #33 of the game partition.
- Sector #32:
Offset | Type | Field | Notes |
---|---|---|---|
0x0 | ascii_char[20] | MAGIC | MICROSOFT*XBOX*MEDIA |
0x14 | u32 | Root Directory Table Sector | Multiply with 0x800 for offset |
0x18 | u32 | Root Directory Table Size | Size in bytes. Always multiple of 0x800 |
0x1C | u64 | Timestamp (LDAP/Win32 FILETIME) | |
0x7EC | ascii_char[20] | MAGIC | MICROSOFT*XBOX*MEDIA |
- Sector #33: The first 24 Bits is the magic. It is always "XBOX_DVD_LAYOUT_TOOL_SIG". [FIXME]
Examples
[FIXME] [FIXME] [FIXME]
Wave 1
Developers used xblayout to create DVD layout. Then generated the final image using xbpremaster. The final image was submitted to Microsoft.
- Azurik: Rise of Perathia (NTSC)
- xblayout version: 1.0.3926.1
- xbpremaster version: 1.0.3926.1
- Genma Onimusha (PAL)
- xblayout version: 1.0.4039.1
- xbpremaster version: 1.0.4039.2
- Max Payne (PAL)
- xblayout version: 1.0.4134.1
- xbpremaster version: 1.0.4242.1
- Petit Copter (Japanese)
- xblayout version: 1.0.4361.1
- xbpremaster version: 1.0.4361.2
- 007 - Agent Under Fire (PAL)
- xblayout version: 1.0.4432.1
- xbpremaster version: 1.0.4432.1
Wave 2
[FIXME]. Developers used a new version of xblayout and submitted the layout + content to Microsoft
Microsoft generated the final image.
Sometime during this wave, the new padding algorithm got introduced. Judging from the examples below, the padding algorithm does not seem to be bound to the xblayout version or to a specific date.
- Metal Gear Solid 2 - Substance (NTSC)
- xblayout version: 1.0.4721.1 (old algorithm)
- Hitman 2 - Silent Assassin (France) (Original)
- xblayout version: 1.0.4721.1 (new algorithm)
- DMI Timestamp: 2002/09/18
- Hitman 2 - Silent Assassin (France) (Classic Edition)
- xblayout version: 1.0.4721.1 (old algorithm)
- DMI Timestamp: 2002/12/03
- Blade II (NTSC)
- xblayout version: 1.0.4808.1 (old algorithm)
- Battle Engine Aquila (PAL)
- xblayout version: 1.0.4831.1 (new algorithm)
Other Examples of games with 1.0.4721.1 version that don't use the old algorithm: Mat Hoffman's Pro BMX 2 (France), MLB SlugFest 2003 (USA), NCAA Football 2003 (USA), Phantom Crash (USA), Syberia (USA, Europe)
Wave 3
[FIXME]. Same as wave 2
- Metal Gear Solid 2 - Substance (PAL)
- xblayout version: 1.0.5120.1
- Shenmue II (PAL)
- xblayout version: 1.0.5120.1
Wave 4
[FIXME]. Same as wave 3, but developers now had to use the xbgamedisc tool instead of xblayout. The mastering tool used by microsoft also leaves a version identifier now.
- Star Wars - Knights of the Old Republic (PAL)
- xbgamedisc version: 2.1.0.5233.1
- mastering tool version: 2.1.0.5233.1
- Indiana Jones and the Emperor's Tomb (PAL)
- xbgamedisc version: 2.1.0.5233.1
- mastering tool version: 2.1.0.5233.1
- Dynasty Warriors 4 (PAL)
- xbgamedisc version: 2.1.0.5344.1
- mastering tool version: 2.1.0.5344.1
- The Matrix - Path of Neo (PAL)
- xbgamedisc version: 2.1.0.5849.1
- mastering tool version: 2.1.0.5849.1
- The Suffering - Ties That Bind
- xbgamedisc version: 2.1.0.5849.1
- mastering tool version: 2.1.0.5849.1
- Reservoir Dogs (PAL)
- xbgamedisc version: 2.1.0.5849.1
- mastering tool version: 2.1.0.5849.1
Directory Entry
Version 4361
File entry flags:
- READONLY = 0x01
- HIDDEN = 0x02
- SYSTEM = 0x04
- DIRECTORY = 0x10
- ARCHIVE = 0x20
- NORMAL = 0x80
File data blocks
Version 4361
Incomplete sectors are padded with 0x00 bytes.
Random blocks
Version 3926 - 4808
Seeded and then starting to emit bytes in data area. Filled with the following algorithm:
// State uint32_t a; uint32_t b; uint32_t c; // Helper static uint32_t Value(void) { uint64_t result; result = c; result += 1; result *= b; result %= 0xFFFFFFFB; c = result & 0xFFFFFFFF; return c ^ a; } // buffer must be at even address, length must be multiple of 2 void Fill(uint16_t* buffer, size_t length) { while(length >= 2) { *buffer++ = Value() >> 8; length -= 2; } } void Seed() { const uint32_t b_seeds[8] = { 0x52F690D5, 0x534D7DDE, 0x5B71A70F, 0x66793320, 0x9B7E5ED5, 0xA465265E, 0xA53F1D11, 0xB154430F }; FILETIME ft; GetSystemTimeAsFileTime(&ft); uint32_t seed = ft.dwLowDateTime ^ ft.dwHighDateTime; a = 0; b = b_seeds[seed & 7]; c = seed; a = Value(); }
The RNG is seeded when the mastering tool / wizard is started. The first portion of the code to use this random number generator is the code which generates layer 0 and layer 1.
Version 4831 - 5849
The algorithm was switched to RC4-256-drop-2048.
#include <openssl/rc4.h> RC4_KEY rc4key; void Fill(uint8_t* buffer, size_t length) { // We need a zero buffer as OpenSSL will want to XOR the keystream with data. // The XDVDFS random data is the keystream without changes, so we let XOR OpenSSL XOR with 0x00 bytes. uint8_t zero_buffer[length]; memset(zero_buffer, 0x00, length); RC4(&rc4key, length, zero_buffer, buffer); } void Seed() { union { uint8_t raw[16]; struct { struct _FILETIME SystemTimeAsFileTime; // first 8 bytes, little-endian uint64_t tsc; // later 8 bytes, little-endian }; } key; // Initialize seed key.tsc = rdtsc(); GetSystemTimeAsFileTime(&key.SystemTimeAsFileTime); RC4_set_key(&rc4key, 16, &key); // Drop the first 2048 bytes of the RC4 keystream uint8_t discard_buffer[2048]; Fill(discard_buffer, 2048); }
The RNG is seeded when the mastering tool / wizard is started. The first portion of the code to use this random number generator is the code which generates layer 0 and layer 1.
Edit: This assumption is not true, at least not for all instances. For example, all region variants of Conker Live & Reloaded share the same padding stream.
Security blocks
Version 4361
Treated like random block.