If I'm missing anything or it needs corrections feel free to reply below.

Please Note this reverse engineering the format is WIP.
GameCube Disc Format aka NROM(Read-only) or NR-Disc(Rewritable)
XOR Encryption is done using discId and a randomKey by the Disc Controller Firmware, Panasonic MN103S and is controlled by the System Controller MN102H that does BCA
Copy Protection
Code: Select all
Custom Data Sector Format(Data Frames)
Custom Filesystem
Sectors are encrypted by DiskID(Key1) and RandomKey(Key2)
DiskID = GameID + MakerID
RandomKeys:
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
Check for the Security Code of 6 BCA marks on the disc, from the 6 positions stored on the BCA encrypted area
The 6 BCA mark positions corrupt the sector data stored on the disc, the BCA data tells the locations.
Disc sectors get decrypted with a DiscID and RandomKey from RandomKey list. using the MN102H & MN103S system controller in the DVD drive
Encryption doesn't have a random key for NR disc instead it's a fixed key after the discID, the fixed key value is 9
Encryption with the gamecode and random key xor encryption is similar to the nintendo ds
Encryption(XOR): DiscID(KEY1) -> RandomKey(KEY2)
Security Check: Get DiscID -> Check BCA Marks -> Run Apploader code -> BOOT
Code: Select all
// Burst-Cutting Area(BCA)
struct_DiscBca
{
// UserData(unencrypted), 64B
u8 optInfo[52]; // optional info this can be any data access with the new command on the wii, this is used in NSMB Wii
u8 manufacturer[2];
u8 recorderDevice[2];
u8 bcaSerial;
u8 discDate[2];
u8 discTime[2];
u8 discNumber[3];
// SecureData(unencrypted), 12B
u8 key[8];
u8 id[4];
// AuthenticationData(encrypted with key), 48B
PsnRegion psn[6];
u8 pad[64];
}; // 188B
struct_PsnRegion
{
u32 start;
u32 end;
};
struct_DataFrame
{
u32 id; // PSN(Physical Sector Number)
u16 ied; // ID Error Detection Code, CRC16
u8 userdata[2048]; // Data
u8 cpr_mai[6]; // Copyright Management Information(Unused)
u32 edc; // Error Detection Code, CRC32
}; // 2064B
struct_ControlDataZone
{
DiscManufacturingInfo m_dmi;
PhysicalFormatInfo m_pfi;
};
struct_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[2000];
u8 reversed3[6];
}; // 2048B
struct_DiscManufacturingInfo
{
u8 reversed[6];
u8 secret1[6];
u8 randomNumber2[6];
u8 secret2[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 m_dataAreaAllocation;
u8 bcaDescriptor; // The value is fixed on 128.
u8 reversed2[1967];
u8 reversed3[6];
}; // 2048B
struct_DataAreaAllocation
{
u8 reversed;
u16 startSector; // 196608
u8 reversed2;
u16 endSector; // 909487
u8 reversed3[3];
}; // 12 Bytes
Code: Select all
struct_root
{
BootHeader m_header; // boot.bin
BootHeaderInfo m_bi; // bi2.bin
AppLoader m_apploader; // appldr.img
FileSystemTable m_fst; // fst.bin
u8* userdata; // application is stored here, including boot file
};
struct_BootHeader
{
u8 ConsoleID; // G = Gamecube, R = Wii.
u8 Gamecode[2];
u8 CountryCode; // J=JAP . P=PAL . E=USA
u8 MakerCode[2];
u8 DiscID;
u8 Version;
u8 AudioStreaming; //01 = Enable it. 00 = Don't
u8 StreamBufSize; // For the AudioEnable.
u8 unused_1[18];
u32 DVDMagicWord; // 3258163005
char GameName[64];
u8 unused_2[416];
u32 NKitMagicWord;
u32 NKitVersion;
u32 ImageCRC;
u32 ForceCRC;
u32 ImageSize;
u32 JunkID;
u8 unused_3[488];
u32 ApploaderSize;
u32 ApploaderFunc1;
u32 ApploaderFunc2;
u32 ApploaderFunc3;
u8 unused_4[16];
u32 DOLOffset;
u32 FSTOffset;
u32 FSTSize;
u32 MaxFSTSize;
u32 FSTAddress;
u32 UserPos;
u32 UserLength;
u32 unused_5;
};
struct_BootHeaderInfo
{
u32 DebugMonSize;
u32 SimMemSize;
u32 ArgOffset;
u32 DebugFlag;
u32 DebugOffset;
u32 DebugSize;
u32 RegionCode;
u32 TotalDisc;
u32 LongFileName;
u32 padSpec;
u32 dolLimit;
u8 pad[8148];
}; // 8192 Bytes
struct_AppLoader
{
char revision[16]; // Revision compile date (example "2001/12/17")
u32 entryPoint; // Apploader's entrypoint
u32 size; // Size of apploader code
u32 rebootSize; // Size of reboot code
u8 pad[4]; // zeroes
u8* code; // PPC code
};
struct_FileSystemTable
{
u32 entityCount;
FileSystemEntity* m_entity;
StringTable* m_string;
};
struct_FileSystemEntity
{
u8 flags;
u16 filenameOffset;
u32 fileOffset;
u32 fileSize;
};
struct_StringTable
{
char* name;
u8 dummy;
};