Exemplo n.º 1
0
        public NintendoWad(string sourceFile)
        {
            // check magic bytes
            if (NintendoWad.IsWadFile(sourceFile))
            {
                // read header
                using (FileStream fs = File.OpenRead(sourceFile))
                {
                    // set source file
                    this.SourceFileName = sourceFile;

                    // parse header
                    this.HeaderSize           = ParseFile.ReadUintBE(fs, 0);
                    this.WadType              = ParseFile.ReadUintBE(fs, 4);
                    this.CertificateChainSize = ParseFile.ReadUintBE(fs, 8);
                    this.Reserved             = ParseFile.ReadUintBE(fs, 0xC);
                    this.TicketSize           = ParseFile.ReadUintBE(fs, 0x10);
                    this.TitleMetaDataSize    = ParseFile.ReadUintBE(fs, 0x14);
                    this.DataSize             = ParseFile.ReadUintBE(fs, 0x18);
                    this.FooterSize           = ParseFile.ReadUintBE(fs, 0x1C);

                    // offsets
                    this.CertificateChainOffset = (uint)this.PadValue(this.HeaderSize, "Certificate Chain Offset");
                    this.TicketOffset           = (uint)this.PadValue(this.CertificateChainOffset + this.CertificateChainSize, "Ticket Offset");
                    this.TitleMetaDataOffset    = (uint)this.PadValue(this.TicketOffset + this.TicketSize, "Title Meta Data Offset");
                    this.DataOffset             = (uint)this.PadValue(this.TitleMetaDataOffset + this.TitleMetaDataSize, "Data Offset");
                    this.FooterOffset           = (uint)this.PadValue(this.DataOffset + this.DataSize, "Footer Offset");

                    // get important values
                    this.TicketId          = ParseFile.ReadUlongBE(fs, this.TicketOffset + 0x1D0);
                    this.TitleId           = ParseFile.ReadUlongBE(fs, this.TicketOffset + 0x1DC);
                    this.TitleIdBytes      = ParseFile.ParseSimpleOffset(fs, this.TicketOffset + 0x1DC, 8);
                    this.EncryptedTitleKey = ParseFile.ParseSimpleOffset(fs, this.TicketOffset + 0x1BF, 0x10);
                    this.CommonKeyIndex    = ParseFile.ReadByte(fs, this.TicketOffset + 0x1F1);

                    // decrypt title key
                    this.DecryptTitleKey();

                    // get TMD content entries
                    this.NumberOfContents = ParseFile.ReadUshortBE(fs, this.TitleMetaDataOffset + 0x1DE);
                    this.ParseTmdContentEntries(fs);
                } // using (FileStream fs = File.OpenRead(sourceFile))
            }
            else
            {
                throw new FormatException("Nintendo WAD magic bytes not found at offset 0x03.");
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Parse the Content Entries in the Title Meta Data section.
        /// </summary>
        /// <param name="fs">File Stream of WAD.</param>
        private void ParseTmdContentEntries(FileStream fs)
        {
            ulong            nextOffset = this.DataOffset;
            TmdContentStruct contentEntry;
            ArrayList        contentEntryList = new ArrayList();

            for (ushort i = 0; i < this.NumberOfContents; i++)
            {
                contentEntry               = new TmdContentStruct();
                contentEntry.ContentId     = ParseFile.ReadUintBE(fs, this.TitleMetaDataOffset + 0x1E4 + (i * 0x24) + 0);
                contentEntry.ContentIndex  = ParseFile.ReadUshortBE(fs, this.TitleMetaDataOffset + 0x1E4 + (i * 0x24) + 4);
                contentEntry.ContentType   = ParseFile.ReadUshortBE(fs, this.TitleMetaDataOffset + 0x1E4 + (i * 0x24) + 6);
                contentEntry.ContentSize   = ParseFile.ReadUlongBE(fs, this.TitleMetaDataOffset + 0x1E4 + (i * 0x24) + 8);
                contentEntry.Sha1Hash      = ParseFile.ParseSimpleOffset(fs, (this.TitleMetaDataOffset + 0x1E4 + (i * 0x24) + 0x10), 20);
                contentEntry.ContentOffset = nextOffset;
                contentEntryList.Add(contentEntry);

                nextOffset = this.PadValue((contentEntry.ContentOffset + contentEntry.ContentSize),
                                           String.Format("Next Offset for ContentId: 0x{0}", contentEntry.ContentId.ToString("X8")));
            }

            this.TmdContentEntries = (TmdContentStruct[])contentEntryList.ToArray(typeof(TmdContentStruct));
        }
Exemplo n.º 3
0
        private void initializeUtfSchema(FileStream SourceFs, FileStream UtfTableFs, long schemaOffset)
        {
            long nameOffset;

            long constantOffset;

            long dataOffset;
            long dataSize;

            long rowDataOffset;
            long rowDataSize;

            long currentOffset = schemaOffset;
            long currentRowBase;
            long currentRowOffset = 0;

            CriField field;

            for (uint i = 0; i < this.NumberOfRows; i++)
            {
                //if (i == 0x1a2a)
                //{
                //    int yuuuu = 1;
                //}
                //try
                //{
                currentOffset    = schemaOffset;
                currentRowBase   = this.RowOffset + (this.RowSize * i);
                currentRowOffset = 0;
                this.Rows[i]     = new Dictionary <string, CriField>();

                // parse fields
                for (ushort j = 0; j < this.NumberOfFields; j++)
                {
                    field = new CriField();

                    field.Type = ParseFile.ReadByte(UtfTableFs, currentOffset);
                    nameOffset = ParseFile.ReadUintBE(UtfTableFs, currentOffset + 1);
                    field.Name = ParseFile.ReadAsciiString(UtfTableFs, this.StringTableOffset + nameOffset);

                    // each row will have a constant
                    if (((field.Type & COLUMN_STORAGE_MASK) == COLUMN_STORAGE_CONSTANT) ||
                        ((field.Type & COLUMN_STORAGE_MASK) == COLUMN_STORAGE_CONSTANT2))
                    {
                        // capture offset of constant
                        constantOffset = currentOffset + 5;

                        // read the constant depending on the type
                        switch (field.Type & COLUMN_TYPE_MASK)
                        {
                        case COLUMN_TYPE_STRING:
                            dataOffset     = ParseFile.ReadUintBE(UtfTableFs, constantOffset);
                            field.Value    = ParseFile.ReadAsciiString(UtfTableFs, this.StringTableOffset + dataOffset);
                            currentOffset += 4;
                            break;

                        case COLUMN_TYPE_8BYTE:
                            field.Value    = ParseFile.ReadUlongBE(UtfTableFs, constantOffset);
                            currentOffset += 8;
                            break;

                        case COLUMN_TYPE_DATA:
                            dataOffset   = ParseFile.ReadUintBE(UtfTableFs, constantOffset);
                            dataSize     = ParseFile.ReadUintBE(UtfTableFs, constantOffset + 4);
                            field.Offset = (ulong)(this.BaseOffset + this.DataOffset + dataOffset);
                            field.Size   = (ulong)dataSize;

                            // don't think this is encrypted, need to check
                            field.Value    = ParseFile.ParseSimpleOffset(SourceFs, (long)field.Offset, (int)dataSize);
                            currentOffset += 8;
                            break;

                        case COLUMN_TYPE_FLOAT:
                            field.Value    = ParseFile.ReadFloatBE(UtfTableFs, constantOffset);
                            currentOffset += 4;
                            break;

                        case COLUMN_TYPE_4BYTE2:
                            field.Value    = ParseFile.ReadInt32BE(UtfTableFs, constantOffset);
                            currentOffset += 4;
                            break;

                        case COLUMN_TYPE_4BYTE:
                            field.Value    = ParseFile.ReadUintBE(UtfTableFs, constantOffset);
                            currentOffset += 4;
                            break;

                        case COLUMN_TYPE_2BYTE2:
                            field.Value    = ParseFile.ReadInt16BE(UtfTableFs, constantOffset);
                            currentOffset += 2;
                            break;

                        case COLUMN_TYPE_2BYTE:
                            field.Value    = ParseFile.ReadUshortBE(UtfTableFs, constantOffset);
                            currentOffset += 2;
                            break;

                        case COLUMN_TYPE_1BYTE2:
                            field.Value    = ParseFile.ReadSByte(UtfTableFs, constantOffset);
                            currentOffset += 1;
                            break;

                        case COLUMN_TYPE_1BYTE:
                            field.Value    = ParseFile.ReadByte(UtfTableFs, constantOffset);
                            currentOffset += 1;
                            break;

                        default:
                            throw new FormatException(String.Format("Unknown COLUMN TYPE at offset: 0x{0}", currentOffset.ToString("X8")));
                        }     // switch (field.Type & COLUMN_TYPE_MASK)
                    }
                    else if ((field.Type & COLUMN_STORAGE_MASK) == COLUMN_STORAGE_PERROW)
                    {
                        // read the constant depending on the type
                        switch (field.Type & COLUMN_TYPE_MASK)
                        {
                        case COLUMN_TYPE_STRING:
                            rowDataOffset     = ParseFile.ReadUintBE(UtfTableFs, currentRowBase + currentRowOffset);
                            field.Value       = ParseFile.ReadAsciiString(UtfTableFs, this.StringTableOffset + rowDataOffset);
                            currentRowOffset += 4;
                            break;

                        case COLUMN_TYPE_8BYTE:
                            field.Value       = ParseFile.ReadUlongBE(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 8;
                            break;

                        case COLUMN_TYPE_DATA:
                            rowDataOffset = ParseFile.ReadUintBE(UtfTableFs, currentRowBase + currentRowOffset);
                            rowDataSize   = ParseFile.ReadUintBE(UtfTableFs, currentRowBase + currentRowOffset + 4);
                            field.Offset  = (ulong)(this.BaseOffset + this.DataOffset + rowDataOffset);
                            field.Size    = (ulong)rowDataSize;

                            // don't think this is encrypted
                            field.Value       = ParseFile.ParseSimpleOffset(SourceFs, (long)field.Offset, (int)rowDataSize);
                            currentRowOffset += 8;
                            break;

                        case COLUMN_TYPE_FLOAT:
                            field.Value       = ParseFile.ReadFloatBE(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 4;
                            break;

                        case COLUMN_TYPE_4BYTE2:
                            field.Value       = ParseFile.ReadInt32BE(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 4;
                            break;

                        case COLUMN_TYPE_4BYTE:
                            field.Value       = ParseFile.ReadUintBE(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 4;
                            break;

                        case COLUMN_TYPE_2BYTE2:
                            field.Value       = ParseFile.ReadInt16BE(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 2;
                            break;

                        case COLUMN_TYPE_2BYTE:
                            field.Value       = ParseFile.ReadUshortBE(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 2;
                            break;

                        case COLUMN_TYPE_1BYTE2:
                            field.Value       = ParseFile.ReadSByte(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 1;
                            break;

                        case COLUMN_TYPE_1BYTE:
                            field.Value       = ParseFile.ReadByte(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 1;
                            break;

                        default:
                            throw new FormatException(String.Format("Unknown COLUMN TYPE at offset: 0x{0}", currentOffset.ToString("X8")));
                        } // switch (field.Type & COLUMN_TYPE_MASK)
                    }     // if ((fields[i].Type & COLUMN_STORAGE_MASK) == COLUMN_STORAGE_CONSTANT)

                    // add field to dictionary
                    this.Rows[i].Add(field.Name, field);

                    // move to next field
                    currentOffset += 5; //  sizeof(CriField.Type + CriField.NameOffset)
                }                       // for (ushort j = 0; j < this.NumberOfFields; j++)
                //}
                //catch (Exception ex)
                //{
                //    int xxxx = 1;
                //}
            } // for (uint i = 0; i < this.NumberOfRows; i++)
        }