DVDFormat: Difference between revisions

From GC-Forever Wiki
Jump to navigation Jump to search
Cyndanera (talk | contribs)
Format Fixing
Cyndanera (talk | contribs)
 
(22 intermediate revisions by 2 users not shown)
Line 1: Line 1:
GameCube Disc Format
GameCube Disc Format aka NROM(Read-only) or NR-Disc(Recordable)
Please Note this is a work in progress doc


XOR Encryption is done using discID and a random seed by the Disc Controller Firmware, Panasonic MN103S
Please Note this is a work in progress doc.


== Random Seed List ==
DVD Sector Scrambling(XOR) is done using Disk ID(8 bytes) and a Random Number by the Disk Controller Firmware, it is stored on a 128KB on-chip ROM
0 0x0003
System Controller firmware uses a ROM 128KB chip.
8 0x0030
 
1 0x7f00
Panasonic MN103S (32bit), 54MHz is the Disk Controller(ECC, EFM\EFM+, Drive IC Control, Descrambler, XADPCM Decoding)
9 0x7001
Panasonic MN102H (16bit), 33Mhz is the System Controller(System Manager, Copy protection, Handles Commands)
2 0x0006
 
A 0x0060
The development tools used to develop for these Panasonic microcontrollers is called Debug Factory 3, it comes with a toolchain that has compiler, linker, assembler.
3 0x7e00
 
B 0x6003
In the firmware the text "Nintendo Game Disk" can be found this is the Media ID 19 byte string that is used as meta data in the lead-in area of the DVD.
4 0x000c
MN102H looks for this string to check if the disc type is a GameCube\Wii Game Disc.
C 0x00c0
It's also does the BCA copy protection check.
5 0x7c00
 
D 0x4007
== Notes ==
6 0x0018
========================================
E 0x0180
NROM BOOTABLE PRESSED DISC GUIDE
7 0x7800
GameCube / Original Wii (GC Mode)
F 0x000f
========================================
1. CONTROL DATA ZONE (CDZ) - Mandatory for boot
------------------------------------------------
Sector size: 2048 bytes
PHYSICAL FORMAT INFORMATION
---------------------------
Bytes (BP)  Name                              Value / Notes
0-5          Reserved                          Any value (zeros fine)
6            NGC Identifier                    0xFF (must)
7            Disc size & min transfer rate    0x12 (fixed)
8            Disc structure                    0x01 (fixed)
9            Recorded density                  0x00 (fixed)
10-21        Data area allocation              Start sector = 0x030000
                                                    End sector  = 0x0DE0AF
22-2047      Reserved                          Any value (zeros or filler)
Dummy area  Reserved                          6 bytes
DISC MANUFACTURING INFORMATION
------------------------------
Bytes (BP)  Name                              Value / Notes
0-5          Reserved                          Any value
6-11        Secret                            Optional, any value
12-13        Random number                      Optional
14-15        Secret                            Optional
16-21        Random number                      Optional
22-40        Media ID                          ASCII: "Nintendo Game Disk" (must match exactly)
41-47        Random number                      Optional
48          Book type / Part version          0x01 (must)
49          Disc size / min readout          0x12 (must)
50          Disc structure                    0x01 (must)
51          Recorded density                  0x00 (must)
52-63        Data area allocation              Start = 0x030000, End = 0x0DE0AF
64          BCA descriptor                    0x80 (must)
65-2047      Reserved                          Any value
Dummy area  Reserved                          6 bytes
Notes:
- Only BP6, BP7-BP9, BP48-BP51, BP52-BP63, BP64, and Media ID are critical.
- All "secret" or "random number" fields are optional filler.
2. DISCID - Mandatory
---------------------
- 8 bytes total: game_code[4] + corp_code[2] + disc_number + version
- Example:
  game_code = "ABCD"
  corp_code = "01"
  disc_number = 0x01
  version = 0x00
- DiscID is used to select XOR scrambler preset index.
3. USER AREA - Mandatory, XOR Scrambled
----------------------------------------
- Start sector: 0x030000
- End sector:  0x0DE0AF
- Sector size:  2048 bytes
XOR Scrambling (NROM style):
- Preset table (16 numbers):
  0: 3, 1: 48, 2: 32512, 3: 28673
  4: 6, 5: 69, 6: 32256, 7: 24579
  8: 12, 9: 192, 10: 31744, 11: 16391
  12: 24, 13: 384, 14: 30720, 15: 15
- Select preset index (0-15) using DiscID:
  1) sum = sum of first 8 bytes of DiscID
  2) beat_data = ((sum / 0x10) + sum) & 0x0F
  3) beat_data selects index in preset table
- Initialize XOR scrambler (LFSR) with chosen preset
- Scramble each sector:
  - Bytes D0-D5 = not scrambled
  - Bytes D6-D2047 = XOR with pseudo-random stream from LFSR
- Wrap-around ensures continuity across sectors
4. BCA (BURST-CUTTING AREA) - Optional
----------------------------------------
- 188-byte block is enough if included
- Fill with zeros or dummy values
- No real marks or signatures needed
- Drive ignores BCA for boot
5. LEAD-IN / LEAD-OUT
---------------------
- Can follow normal DVD standard
- Ignored by drive for boot
6. SUMMARY - Minimum for bootable disc
--------------------------------------
1) Control Data Zone ? correct fixed bytes + Media ID + BCA descriptor
2) DiscID ? 8 bytes
3) User area ? XOR-scrambled using DiscID/preset index
4) Optional: BCA block (zeros or filler)
 
== Data Frame ==
    u32 id; // PSN(Physical Sector Number)
    u16 ied; // ID Error Detection Code, CRC16
    u8 userdata[2048]; // Sector Data
    u8 cpr_mai[6]; // Copyright Management Information(Not used)
    u32 edc; // Error Detection Code, CRC32
    // 2064B
 
== Random Number Table ==
    0: 3
    1: 48
    2: 32512
    3: 28673
    4: 6
    5: 69
    6: 32256
    7: 24579
    8: 12
    9: 192
    10: 31744
    11: 16391
    12: 24
    13: 384
    14: 30720
    15: 15
 
== DiskId ==
    char gamecode[4];
    char makercode[2];
    u8 diskNumber;
    u8 version;
    u8 streaming;
    u8 streamingBufferSize;
    u8 pad[18];
    u32 magic;


== Burst Cutting Area ==
== Burst Cutting Area ==
     // UserData(64 Bytes)
     /* Each radial mark entry */
     u8 optionalInfo[52];
    struct_BcaMarkEntry
    u8 manufacturerCode[2];
    {
    u8 recorderDeviceCode[2];
        u32 psn; /* Physical sector number */
    u8 APMRecorderDeviceCode;
        u16 bitOffset; /* Bit offset within the sector where the mark starts */
    u8 discManufactureDate[2];
        u8 type; /* Mark type (Datel style = 0xFF) */
    u8 discManufactureTime[2];
        u8 reserved; /* Padding to make struct size 8 bytes */
    u8 discNumber[3];
    };
    // KeyData(16 Bytes)
      
    u8 bcakey[8];
    /* Complete BCA block */
    u8 bcaSerial[8];
    struct_DiscBca
    // Encrypted(48 Bytes)
    {
    u64 psn[6]; //BCA mark positions
        /* --- Manufacturing metadata (plain) --- */
// 188 Total Bytes
        u8 optInfo[52]; /* mastering options */
        u8 manufacturer[2]; /* pressing plant code */
        u8 recorderDevice[2]; /* LBR device code */
        u8 bcaSerial; /* disc batch serial */
        u8 discDate[2]; /* year / month etc. */
        u8 discTime[2]; /* hour / minute etc. */
        u8 discNumber[3]; /* disc number in batch */
       
        /* --- Authentication key and ID --- */
        u8 key[8]; /* 8-byte key used by hardware check */
        u8 id[4]; /* 4-byte disc identifier */
       
        /* --- Radial mark table --- */
        BcaMarkEntry marks[6]; /* 6 radial marks used for validation */
        /* --- Padding to fill 188 bytes --- */
        u8 reserved[64];
    };


== Disc Physical Format ==
== Disc Physical Format ==
// Leadin Area
    // Leadin Area
PhysicalFormatInfo m_pfi;
    PhysicalFormatInfo pfi;
DiscManufacturingInfo m_dmi;
    DiscManufacturingInfo dmi;


struct_PhysicalFormatInfo
PhysicalFormatInfo
{
     u8 reversed[6];
     u8 reversed[6];
     u8 discMagic; // value is -1.
     u8 discMagic; // value is -1.
Line 53: Line 194:
     u8 reversed2[2026];
     u8 reversed2[2026];
     u8 reversed3[6];
     u8 reversed3[6];
};


struct_DiscManufacturingInfo
DiscManufacturingInfo
{
     u8 reversed[6];
     u8 reversed[6];
     u8 unknown1[6];
     u8 unknown1[6];
Line 68: Line 207:
     u8 discStructure; // The value is fixed on 1.
     u8 discStructure; // The value is fixed on 1.
     u8 recordedDensity; // The value is fixed on 0.
     u8 recordedDensity; // The value is fixed on 0.
     DataAreaAllocation m_dataAreaAllocation;
     DataAreaAllocation dataAreaAllocation;
     u8 bcaDescriptor; // The value is fixed on 128.
     u8 bcaDescriptor; // The value is fixed on 128.
     u8 reversed2[1983];
     u8 reversed2[1983];
     u8 reversed3[6];
     u8 reversed3[6];
};


struct_DataAreaAllocation
DataAreaAllocation
{
     u8 reversed;
     u8 reversed;
     u16 startSector; // 196608
     u16 startSector;
     u8 reversed2;
     u8 reversed2;
     u16 endSector; // 909487
     u16 endSector;
     u8 reversed3[3];
     u8 reversed3[3];
}; // 12 Bytes
    // 12 Bytes


== Disc Image Format ==
== Disc Image Format ==
     BootHeader m_header; // boot.bin
     BootHeader m_header;
     BootHeaderInfo m_bi; // bi2.bin
     BootHeaderInfo m_bi;
     AppLoader m_apploader; // appldr.img
     AppLoader m_apploader;
     FileSystemTable m_fst; // fst.bin
     FileSystemTable m_fst;
     u8 userdata[0]; // application is stored here, including boot file
     u8 userdata[0]; // application is stored here, including boot file


struct_BootHeader
BootHeader
{
    u8 game_code[4];
u8 ConsoleID; // G = Gamecube, R = Wii.
    u8 company_code[2];
u8 Gamecode[2];
    u8 diskNumber;
u8 CountryCode;    //J=JAP . P=PAL . E=USA . D=OoT MasterQuest
    u8 gameVersion;
u8 MakerCode[2];
    u8 audioStreaming;
u8 DiscID;
    u8 streamBufSize;
u8 Version;
    u8 unused_1[18];     
u8 AudioStreaming; //01 = Enable it. 00 = Don't
    u32 magic; // 3258163005
u8 StreamBufSize; // For the AudioEnable.
    char gameName[64];
u8 unused_1[18];     
    u8 unused_2[416];
u32 DVDMagicWord; // 3258163005
    u32 nkitMagicWord;
char GameName[64];
    u32 nkitVersion;
u8 unused_2[416];
    u32 dataCRC;
u32 NKitMagicWord;
    u32 headerCRC;
u32 NKitVersion;
    u32 dataSize;
u32 ImageCRC;
    u32 junkId;
u32 ForceCRC;
    u8 unused_3[488];
u32 ImageSize;
    u32 ApploaderSize;
u32 JunkID;
    u32 ApploaderInit;
u8 unused_3[488];
    u32 ApploaderMain;
u32 ApploaderSize;
    u32 ApploaderExit;
u32 ApploaderFunc1;
    u8 unused_4[16];
u32 ApploaderFunc2;
    u32 bootOffset;
u32 ApploaderFunc3;
    u32 fstOffset;
u8 unused_4[16];
    u32 fstSize;
u32 DOLOffset;
    u32 maxFstSize;
u32 FSTOffset;
    u32 fstAddress; // debug fstOffset
u32 FSTSize;
    u32 userPos; // disc data offset
u32 MaxFSTSize;
    u32 userLength; // disc data size
u32 FSTAddress;
    u32 unused_5;
u32 UserPos;
u32 UserLength;
u32 unused_5;
};


struct_BootHeaderInfo
BootHeaderInfo
{
    u32 debugMonSize; // debug monitor size
u32 DebugMonSize;
    u32 simMemSize; // simulator memory size
u32 SimMemSize;
    u32 argOffset;
u32 ArgOffset;
    u32 debugFlag;
u32 DebugFlag;
    u32 debugOffset;
u32 DebugOffset;
    u32 debugSize;
u32 DebugSize;
    u32 country;
u32 RegionCode;
    u32 totalDisc;
u32 TotalDisc;
    u32 supportLongFileName;
u32 LongFileName;
    u32 padSpec;
u32 PADSpec;
    u32 dolLimit;
u32 DOLLimit;
    u8 unused_6[8148];
u8 unused_6[8148];
    // 8192 Bytes
}; // 8192 Bytes


struct_AppLoader
AppLoader
{
     char date[16]; // date string
     char revision[16]; // Revision compile date (example "2001/12/17")
     u32 entryAddress;
     u32 entryPoint; // Apploader's entrypoint
     u32 size;
     u32 size; // Size of apploader code
     u32 rebootSize;
     u32 rebootSize; // Size of reboot code
     u8 pad[4];
     u8 pad[4]; // zeroes
     u8* code;
     u8 code[0]; // PPC code
};


struct_FileSystemTable
FileSystemTable
{
     u32 entryCount;
     u32 entityCount;
     FileSystemEntity* m_entity;
     FileSystemEntity* m_entity;
     StringTable* m_string;
     StringTable* m_string;
};


struct_FileSystemEntity
FileSystemEntity
{
     u8 flags;
     u8 flags;
     u16 filenameOffset;
     u16 filenameOffset;
     u32 fileOffset;
     u32 fileOffset;
     u32 fileSize;
     u32 fileSize;
};


struct_StringTable
StringTable
{
     char* name;
     char name[0];
     u8 pad;
     char dummy;
};

Latest revision as of 14:47, 13 March 2026

GameCube Disc Format aka NROM(Read-only) or NR-Disc(Recordable)

Please Note this is a work in progress doc.

DVD Sector Scrambling(XOR) is done using Disk ID(8 bytes) and a Random Number by the Disk Controller Firmware, it is stored on a 128KB on-chip ROM System Controller firmware uses a ROM 128KB chip.

Panasonic MN103S (32bit), 54MHz is the Disk Controller(ECC, EFM\EFM+, Drive IC Control, Descrambler, XADPCM Decoding)
Panasonic MN102H (16bit), 33Mhz is the System Controller(System Manager, Copy protection, Handles Commands)

The development tools used to develop for these Panasonic microcontrollers is called Debug Factory 3, it comes with a toolchain that has compiler, linker, assembler.

In the firmware the text "Nintendo Game Disk" can be found this is the Media ID 19 byte string that is used as meta data in the lead-in area of the DVD.
MN102H looks for this string to check if the disc type is a GameCube\Wii Game Disc.
It's also does the BCA copy protection check.

Notes

========================================
NROM BOOTABLE PRESSED DISC GUIDE
GameCube / Original Wii (GC Mode)
========================================

1. CONTROL DATA ZONE (CDZ) - Mandatory for boot
------------------------------------------------
Sector size: 2048 bytes

PHYSICAL FORMAT INFORMATION
---------------------------
Bytes (BP)   Name                              Value / Notes
0-5          Reserved                          Any value (zeros fine)
6            NGC Identifier                    0xFF (must)
7            Disc size & min transfer rate     0x12 (fixed)
8            Disc structure                    0x01 (fixed)
9            Recorded density                  0x00 (fixed)
10-21        Data area allocation              Start sector = 0x030000
                                                    End sector   = 0x0DE0AF
22-2047      Reserved                          Any value (zeros or filler)
Dummy area   Reserved                          6 bytes

DISC MANUFACTURING INFORMATION
------------------------------
Bytes (BP)   Name                              Value / Notes
0-5          Reserved                          Any value
6-11         Secret                            Optional, any value
12-13        Random number                      Optional
14-15        Secret                             Optional
16-21        Random number                      Optional
22-40        Media ID                           ASCII: "Nintendo Game Disk" (must match exactly)
41-47        Random number                      Optional
48           Book type / Part version          0x01 (must)
49           Disc size / min readout           0x12 (must)
50           Disc structure                    0x01 (must)
51           Recorded density                  0x00 (must)
52-63        Data area allocation              Start = 0x030000, End = 0x0DE0AF
64           BCA descriptor                     0x80 (must)
65-2047      Reserved                          Any value
Dummy area   Reserved                          6 bytes

Notes:
- Only BP6, BP7-BP9, BP48-BP51, BP52-BP63, BP64, and Media ID are critical.
- All "secret" or "random number" fields are optional filler.

2. DISCID - Mandatory
---------------------
- 8 bytes total: game_code[4] + corp_code[2] + disc_number + version
- Example:
  game_code = "ABCD"
  corp_code = "01"
  disc_number = 0x01
  version = 0x00
- DiscID is used to select XOR scrambler preset index.

3. USER AREA - Mandatory, XOR Scrambled
----------------------------------------
- Start sector: 0x030000
- End sector:   0x0DE0AF
- Sector size:  2048 bytes

XOR Scrambling (NROM style):
- Preset table (16 numbers):
  0: 3, 1: 48, 2: 32512, 3: 28673
  4: 6, 5: 69, 6: 32256, 7: 24579
  8: 12, 9: 192, 10: 31744, 11: 16391
  12: 24, 13: 384, 14: 30720, 15: 15
- Select preset index (0-15) using DiscID:
  1) sum = sum of first 8 bytes of DiscID
  2) beat_data = ((sum / 0x10) + sum) & 0x0F
  3) beat_data selects index in preset table
- Initialize XOR scrambler (LFSR) with chosen preset
- Scramble each sector:
  - Bytes D0-D5 = not scrambled
  - Bytes D6-D2047 = XOR with pseudo-random stream from LFSR
- Wrap-around ensures continuity across sectors

4. BCA (BURST-CUTTING AREA) - Optional
----------------------------------------
- 188-byte block is enough if included
- Fill with zeros or dummy values
- No real marks or signatures needed
- Drive ignores BCA for boot

5. LEAD-IN / LEAD-OUT
---------------------
- Can follow normal DVD standard
- Ignored by drive for boot

6. SUMMARY - Minimum for bootable disc
--------------------------------------
1) Control Data Zone ? correct fixed bytes + Media ID + BCA descriptor
2) DiscID ? 8 bytes
3) User area ? XOR-scrambled using DiscID/preset index
4) Optional: BCA block (zeros or filler)

Data Frame

   u32 id; // PSN(Physical Sector Number)
   u16 ied; // ID Error Detection Code, CRC16
   u8 userdata[2048]; // Sector Data
   u8 cpr_mai[6]; // Copyright Management Information(Not used)
   u32 edc; // Error Detection Code, CRC32
   // 2064B

Random Number Table

   0: 3
   1: 48
   2: 32512
   3: 28673
   4: 6
   5: 69
   6: 32256
   7: 24579
   8: 12
   9: 192
   10: 31744
   11: 16391
   12: 24
   13: 384
   14: 30720
   15: 15

DiskId

   char gamecode[4];
   char makercode[2];
   u8 diskNumber;
   u8 version;
   u8 streaming;
   u8 streamingBufferSize;
   u8 pad[18];
   u32 magic;

Burst Cutting Area

   /* Each radial mark entry */
   struct_BcaMarkEntry
   {
       u32 psn; /* Physical sector number */
       u16 bitOffset; /* Bit offset within the sector where the mark starts */
       u8 type; /* Mark type (Datel style = 0xFF) */
       u8 reserved; /* Padding to make struct size 8 bytes */
   };
   
   /* Complete BCA block */
   struct_DiscBca
   {
       /* --- Manufacturing metadata (plain) --- */
       u8 optInfo[52]; /* mastering options */
       u8 manufacturer[2]; /* pressing plant code */
       u8 recorderDevice[2]; /* LBR device code */
       u8 bcaSerial; /* disc batch serial */
       u8 discDate[2]; /* year / month etc. */
       u8 discTime[2]; /* hour / minute etc. */
       u8 discNumber[3]; /* disc number in batch */
       
       /* --- Authentication key and ID --- */
       u8 key[8]; /* 8-byte key used by hardware check */
       u8 id[4]; /* 4-byte disc identifier */
       
       /* --- Radial mark table --- */
       BcaMarkEntry marks[6]; /* 6 radial marks used for validation */
       /* --- Padding to fill 188 bytes --- */
       u8 reserved[64];
   };

Disc Physical Format

   // Leadin Area
   PhysicalFormatInfo pfi;
   DiscManufacturingInfo dmi;

PhysicalFormatInfo

   u8 reversed[6];
   u8 discMagic; // value is -1.
   u8 discSizeMinTransferRate; // The value is fixed on 16.
   u8 discStructure; // The value is fixed on 1.
   u8 recordedDensity; // The value is fixed on 1.
   DataAreaAllocation m_dataAreaAllocation;
   u8 reversed2[2026];
   u8 reversed3[6];

DiscManufacturingInfo

   u8 reversed[6];
   u8 unknown1[6];
   u8 randomNumber2[6];
   u8 unknown2[6];
   u8 randomNumber3[6];
   char mediaId[19]; // "Nintendo Game Disk"
   u8 randomNumber4[6];
   u8 bookTypePartVersion; // value must be 1.
   u8 discSizeMinReadoutRate; // The value is fixed on 16.
   u8 discStructure; // The value is fixed on 1.
   u8 recordedDensity; // The value is fixed on 0.
   DataAreaAllocation dataAreaAllocation;
   u8 bcaDescriptor; // The value is fixed on 128.
   u8 reversed2[1983];
   u8 reversed3[6];

DataAreaAllocation

   u8 reversed;
   u16 startSector;
   u8 reversed2;
   u16 endSector;
   u8 reversed3[3];
   // 12 Bytes

Disc Image Format

   BootHeader m_header;
   BootHeaderInfo m_bi;
   AppLoader m_apploader;
   FileSystemTable m_fst;
   u8 userdata[0]; // application is stored here, including boot file

BootHeader

   u8 game_code[4];
   u8 company_code[2];
   u8 diskNumber;
   u8 gameVersion;
   u8 audioStreaming;
   u8 streamBufSize;
   u8 unused_1[18];    
   u32 magic; // 3258163005
   char gameName[64];
   u8 unused_2[416];
   u32 nkitMagicWord;
   u32 nkitVersion;
   u32 dataCRC;
   u32 headerCRC;
   u32 dataSize;
   u32 junkId;
   u8 unused_3[488];
   u32 ApploaderSize;
   u32 ApploaderInit;
   u32 ApploaderMain;
   u32 ApploaderExit;
   u8 unused_4[16];
   u32 bootOffset;
   u32 fstOffset;
   u32 fstSize;
   u32 maxFstSize;
   u32 fstAddress; // debug fstOffset
   u32 userPos; // disc data offset
   u32 userLength; // disc data size
   u32 unused_5;

BootHeaderInfo

   u32 debugMonSize; // debug monitor size
   u32 simMemSize; // simulator memory size
   u32 argOffset;
   u32 debugFlag;
   u32 debugOffset;
   u32 debugSize;
   u32 country;
   u32 totalDisc;
   u32 supportLongFileName;
   u32 padSpec;
   u32 dolLimit;
   u8 unused_6[8148];
   // 8192 Bytes

AppLoader

   char date[16]; // date string
   u32 entryAddress;
   u32 size;
   u32 rebootSize;
   u8 pad[4];
   u8* code;

FileSystemTable

   u32 entryCount;
   FileSystemEntity* m_entity;
   StringTable* m_string;

FileSystemEntity

   u8 flags;
   u16 filenameOffset;
   u32 fileOffset;
   u32 fileSize;

StringTable

   char* name;
   u8 pad;