Example #1
0
        private void BuildRomFsFile(FileStream isoStream, long ivfcOffset, long fileEntryOffset, long fileBlockOffset, long romFsDataOffset)
        {
            RomFsFileEntry file = new RomFsFileEntry();

            // Nintendo3dsCtrFile tempFile;
            byte[] nameBytes;

            // load dir
            file.ParentDirOffset = ParseFile.ReadUintLE(isoStream, ivfcOffset + fileBlockOffset + fileEntryOffset);
            file.SiblingOffset   = ParseFile.ReadInt32LE(isoStream, ivfcOffset + fileBlockOffset + fileEntryOffset + 4);
            file.DataOffset      = ParseFile.ReadUlongLE(isoStream, ivfcOffset + fileBlockOffset + fileEntryOffset + 8);
            file.DataSize        = ParseFile.ReadUlongLE(isoStream, ivfcOffset + fileBlockOffset + fileEntryOffset + 0x10);
            file.WeirdOffset     = ParseFile.ReadUintLE(isoStream, ivfcOffset + fileBlockOffset + fileEntryOffset + 0x18);
            file.NameSize        = ParseFile.ReadUintLE(isoStream, ivfcOffset + fileBlockOffset + fileEntryOffset + 0x1C);

            // build directory name
            if (file.NameSize > 0)
            {
                nameBytes = ParseFile.ParseSimpleOffset(isoStream, ivfcOffset + fileBlockOffset + fileEntryOffset + 0x20, (int)file.NameSize);
                file.Name = ByteConversion.GetUtf16LeText(nameBytes);
            }
            else // this is root
            {
                file.Name = "NO_NAME_FOUND"; // @TODO Make this a constant
            }

            this.FileName = file.Name;
            this.Offset   = ivfcOffset + romFsDataOffset + (long)file.DataOffset;
            this.Size     = (long)file.DataSize;

            // get sibling
            this.SiblingOffset = file.SiblingOffset;
        }
Example #2
0
        private void ParseIvfcHeader(FileStream fs, long offset)
        {
            this.MagicBytes = ParseFile.ReadUintBE(fs, offset);

            // verify magic bytes
            if (this.MagicBytes != 0x49564643)
            {
                throw new FormatException(String.Format("IVFC bytes not found."));
            }

            this.VersionNumber  = ParseFile.ReadUintLE(fs, offset + 0x04);
            this.MasterHashSize = ParseFile.ReadUintLE(fs, offset + 0x08);

            this.Level1Offset       = ParseFile.ReadUlongLE(fs, offset + 0x0C);
            this.Level1HashDataSize = ParseFile.ReadUlongLE(fs, offset + 0x14);
            this.Level1BlockSize    = ParseFile.ReadUintLE(fs, offset + 0x1C);
            this.Reserved01         = ParseFile.ReadUintLE(fs, offset + 0x20);

            this.Level2Offset       = ParseFile.ReadUlongLE(fs, offset + 0x24);
            this.Level2HashDataSize = ParseFile.ReadUlongLE(fs, offset + 0x2C);
            this.Level2BlockSize    = ParseFile.ReadUintLE(fs, offset + 0x34);
            this.Reserved02         = ParseFile.ReadUintLE(fs, offset + 0x38);

            this.Level3Offset       = ParseFile.ReadUlongLE(fs, offset + 0x3C);
            this.Level3HashDataSize = ParseFile.ReadUlongLE(fs, offset + 0x44);
            this.Level3BlockSize    = ParseFile.ReadUintLE(fs, offset + 0x4C);
            this.Reserved03         = ParseFile.ReadUintLE(fs, offset + 0x50);

            this.Reserved04       = ParseFile.ReadUintLE(fs, offset + 0x54);
            this.OptionalInfoSize = ParseFile.ReadUintLE(fs, offset + 0x58);
        }
Example #3
0
        public MicrosoftExFatRootDirFileDirectoryEntry(byte[] directoryEntry)
        {
            this.EntryType = directoryEntry[0];

            this.SecondaryCount = directoryEntry[1];
            this.SetChecksum    = ParseFile.ReadUshortLE(directoryEntry, 2);
            this.FileAttributes = ParseFile.ReadUshortLE(directoryEntry, 4);
            this.Reserved1      = ParseFile.ReadUshortLE(directoryEntry, 6);

            this.Create       = ParseFile.ReadUintLE(directoryEntry, 8);
            this.LastModified = ParseFile.ReadUintLE(directoryEntry, 0x0C);
            this.LastAccessed = ParseFile.ReadUintLE(directoryEntry, 0x10);

            this.Create10ms       = directoryEntry[0x14];
            this.LastModified10ms = directoryEntry[0x15];

            this.CreateTZOffset       = directoryEntry[0x16];
            this.LastModifiedTZOffset = directoryEntry[0x17];
            this.LastAccessTZOffset   = directoryEntry[0x18];

            this.Reserved2 = ParseFile.SimpleArrayCopy(directoryEntry, 0x19, 7);

            this.IsInUse     = ((this.EntryType & 0x80) == 0x80);
            this.IsDirectory = ((this.FileAttributes & 0x10) == 0x10);
        }
Example #4
0
        public void Initialize(FileStream isoStream, long offset, bool isRawDump)
        {
            this.VolumeBaseOffset        = offset;
            this.IsRawDump               = isRawDump;
            this.VolumeType              = VolumeDataType.Data;
            this.DirectoryStructureArray = new ArrayList();
            this.FormatDescription       = MicrosoftExFatFileSystem.FORMAT_DESCRIPTION_STRING;

            this.JumpBoot   = ParseFile.ReadUint24LE(isoStream, this.VolumeBaseOffset + 0);
            this.MagicBytes = ParseFile.ParseSimpleOffset(isoStream, this.VolumeBaseOffset + 3, 8);
            this.ZeroChunk  = ParseFile.ParseSimpleOffset(isoStream, this.VolumeBaseOffset + 11, 53);

            this.PartitionOffset           = ParseFile.ReadUlongLE(isoStream, this.VolumeBaseOffset + 64);
            this.VolumeLength              = ParseFile.ReadUlongLE(isoStream, this.VolumeBaseOffset + 72);
            this.FatOffset                 = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 80);
            this.FatLength                 = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 84);
            this.ClusterHeapOffset         = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 88);
            this.ClusterCount              = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 92);
            this.RootDirectoryFirstCluster = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 96);

            this.VolumeSerialNumber = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 100);
            this.VolumeIdentifier   = this.VolumeSerialNumber.ToString("X2");

            this.FileSystemRevision = ParseFile.ReadUshortLE(isoStream, this.VolumeBaseOffset + 104);
            this.VolumeFlags        = ParseFile.ReadUshortLE(isoStream, this.VolumeBaseOffset + 106);

            this.BytesPerSector    = ParseFile.ReadByte(isoStream, this.VolumeBaseOffset + 108);
            this.SectorsPerCluster = ParseFile.ReadByte(isoStream, this.VolumeBaseOffset + 109);

            this.NumberOfFats = ParseFile.ReadByte(isoStream, this.VolumeBaseOffset + 110);

            // caclulate helper values
            this.SectorSizeInBytes  = (uint)(1 << this.BytesPerSector);
            this.ClusterSizeInBytes = (uint)(1 << (this.SectorsPerCluster + this.BytesPerSector));

            this.VolumeLengthInBytes         = this.VolumeLength * this.SectorSizeInBytes;
            this.FatAbsoluteOffset           = (ulong)this.VolumeBaseOffset + (this.FatOffset * this.SectorSizeInBytes);
            this.FatLengthInBytes            = this.FatLength * this.SectorSizeInBytes;
            this.ClusterHeapAbsoluteOffset   = (ulong)this.VolumeBaseOffset + (this.ClusterHeapOffset * this.SectorSizeInBytes);
            this.RootDirectoryAbsoluteOffset =
                MicrosoftExFatFileSystem.GetOffsetForClusterId(this.ClusterHeapAbsoluteOffset, this.ClusterSizeInBytes, this.RootDirectoryFirstCluster); // this.ClusterHeapAbsoluteOffset + ((this.RootDirectoryFirstCluster - MicrosoftExFatFileSystem.CLUSTER_CORRECTION_OFFSET) * this.ClusterSizeInBytes);

            if (this.FileSystemRevision == MicrosoftExFatFileSystem.EXFAT_VERSION_0100)
            {
                // initialize FAT
                this.InitializeAndValidateFat(isoStream);

                // process root directory entry
                this.GetVolumeLabel(isoStream);

                // load directories
                this.LoadDirectories(isoStream);
            }
            else
            {
                MessageBox.Show(String.Format("Unsupported exFAT version: {0}", this.FileSystemRevision.ToString("X8")));
            }
        }
Example #5
0
        protected override void ReadHeader(FileStream inStream, long offset)
        {
            long currentOffset = offset;

            ushort chunkTypeId;
            ushort subChunkCount;

            // read header size
            this.HeaderSize = ParseFile.ReadUintLE(inStream, currentOffset + 4) + 8;
            currentOffset  += 8;

            while (currentOffset < this.HeaderSize)
            {
                // read chunk type id
                chunkTypeId = ParseFile.ReadUshortBE(inStream, currentOffset);

                // read subchunk count
                subChunkCount = ParseFile.ReadUshortLE(inStream, currentOffset + 2);

                switch (chunkTypeId)
                {
                // get audio details
                case MobiclipWiiStream.AudioChunkSignature:
                    this.AudioStreamCount    = ParseFile.ReadUintLE(inStream, currentOffset + 4);
                    this.AudioStreamFeatures = new MobiclipAudioStreamFeatures[this.AudioStreamCount];

                    for (uint i = 0; i < this.AudioStreamCount; i++)
                    {
                        this.AudioStreamFeatures[i]            = new MobiclipAudioStreamFeatures();
                        this.AudioStreamFeatures[i].StreamType = ParseFile.ReadUshortBE(inStream, currentOffset + 8 + (i * 0xA));
                        this.AudioStreamFeatures[i].Frequency  = ParseFile.ReadUintLE(inStream, currentOffset + 8 + (i * 0xA) + 2);
                        this.AudioStreamFeatures[i].Channels   = ParseFile.ReadUintLE(inStream, currentOffset + 8 + (i * 0xA) + 6);
                    }

                    break;

                case MobiclipWiiStream.AudioChunkSignaturePcm:
                case MobiclipWiiStream.AudioChunkSignatureA3:
                    this.AudioStreamCount                  = 1;
                    this.AudioStreamFeatures               = new MobiclipAudioStreamFeatures[this.AudioStreamCount];
                    this.AudioStreamFeatures[0]            = new MobiclipAudioStreamFeatures();
                    this.AudioStreamFeatures[0].StreamType = ParseFile.ReadUshortBE(inStream, currentOffset);
                    this.AudioStreamFeatures[0].Frequency  = ParseFile.ReadUintLE(inStream, currentOffset + 4);
                    this.AudioStreamFeatures[0].Channels   = ParseFile.ReadUintLE(inStream, currentOffset + 8);
                    break;

                default:
                    break;
                }

                currentOffset += (subChunkCount * 4) + 4;
            }
        }
Example #6
0
        protected override ChunkStruct GetVideoChunk(FileStream inStream, long currentOffset)
        {
            ChunkStruct videoChunkStruct = new ChunkStruct();

            long chunkSize = (long)ParseFile.ReadUintLE(inStream, currentOffset + 4);

            byte[] videoChunk = ParseFile.ParseSimpleOffset(inStream, currentOffset + 8, (int)chunkSize);

            videoChunkStruct.Chunk   = videoChunk;
            videoChunkStruct.ChunkId = MobiclipWiiStream.VideoChunkId;

            return(videoChunkStruct);
        }
Example #7
0
        protected override ChunkStruct[] GetAudioChunk(FileStream inStream, long currentOffset, long blockSize, long videoChunkSize)
        {
            ChunkStruct[] audioChunkStructs = new ChunkStruct[this.AudioStreamCount];

            long absoluteOffset = currentOffset + 8 + videoChunkSize + 4;
            uint baseChunkId;// = ParseFile.ReadUintLE(inStream, absoluteOffset - 4);

            baseChunkId = 0;
            uint chunkSize = 0;

            for (uint i = 0; i < this.AudioStreamCount; i++)
            {
                audioChunkStructs[i] = new ChunkStruct();

                // Untested for file with more than 2 streams
                if (this.AudioStreamCount > 1)
                {
                    if (i == 0)
                    {
                        // read chunk size before first audio stream, should be the same for each.
                        chunkSize       = ParseFile.ReadUintLE(inStream, absoluteOffset);
                        absoluteOffset += 4;
                    }
                }
                else
                {
                    chunkSize = (uint)((currentOffset + blockSize) - absoluteOffset);
                }

                if (chunkSize > 0)
                {
                    audioChunkStructs[i].ChunkId = baseChunkId + i;
                    audioChunkStructs[i].Chunk   = ParseFile.ParseSimpleOffset(inStream, absoluteOffset, (int)chunkSize);
                }

                absoluteOffset += chunkSize;
            }

            //int chunkSize = (int)(blockSize - videoChunkSize - 8 - 4);

            //if (chunkSize > 0)
            //{
            //    audioChunk = ParseFile.ParseSimpleOffset(inStream, absoluteOffset, chunkSize);

            //    audioChunkStruct.Chunk = audioChunk;
            //    audioChunkStructs[0].ChunkId = ParseFile.ReadUintLE(inStream, absoluteOffset - 4);
            //    audioChunkStruct.ChunkId = 0;
            //}

            return(audioChunkStructs);
        }
Example #8
0
        private void ParseRomFsHeader(FileStream fs, long offset)
        {
            this.RomFsHeaderSize = ParseFile.ReadUintLE(fs, offset + 0x1000);

            this.RomFsSections = new SimpleOffset[4];
            for (int i = 0; i < 4; i++)
            {
                this.RomFsSections[i] = new SimpleOffset((ParseFile.ReadUintLE(fs, offset + 0x1004 + (8 * i))),
                                                         ParseFile.ReadUintLE(fs, offset + 0x1004 + ((8 * i) + 4)));
            }

            this.DirectoryBlockOffset = (long)(this.RomFsSections[1].Offset + 0x1000);
            this.FileBlockOffset      = (long)(this.RomFsSections[3].Offset + 0x1000);
            this.RomFsDataOffset      = ParseFile.ReadUintLE(fs, offset + 0x1024) + 0x1000;
        }
Example #9
0
        public MicrosoftExFatRootDirStreamExtensionEntry(byte[] streamExtensionEntry)
        {
            this.EntryType             = streamExtensionEntry[0];
            this.GeneralSecondaryFlags = streamExtensionEntry[1];
            this.Reserved1             = streamExtensionEntry[2];

            this.NameLength = streamExtensionEntry[3];
            this.NameHash   = ParseFile.ReadUshortLE(streamExtensionEntry, 4);
            this.Reserved2  = ParseFile.ReadUshortLE(streamExtensionEntry, 6);

            this.ValidDataLength = ParseFile.ReadUlongLE(streamExtensionEntry, 8);
            this.Reserved3       = ParseFile.ReadUintLE(streamExtensionEntry, 0x10);

            this.FirstCluster = ParseFile.ReadUintLE(streamExtensionEntry, 0x14);
            this.DataLength   = ParseFile.ReadUlongLE(streamExtensionEntry, 0x18);
        }
Example #10
0
        private void ParseNcsdHeader(FileStream fs, long offset)
        {
            // parse NCSD header
            this.NcsdHash                 = ParseFile.ParseSimpleOffset(fs, offset, 0x100);
            this.MagicBytes               = ParseFile.ReadUintBE(fs, offset + 0x100);
            this.ImageSize                = ParseFile.ReadUintLE(fs, offset + 0x104);
            this.MediaId                  = ParseFile.ReadUlongLE(fs, offset + 0x108);
            this.PartitionsFsType         = ParseFile.ReadUlongLE(fs, offset + 0x110);
            this.PartitionsEncryptionType = ParseFile.ReadUlongLE(fs, offset + 0x118);

            this.NcchOffsetInfo = new SimpleOffset[8];
            for (int i = 0; i < 8; i++)
            {
                this.NcchOffsetInfo[i] = new SimpleOffset(
                    ParseFile.ReadUintLE(fs, offset + 0x120 + (8 * i)),
                    ParseFile.ReadUintLE(fs, offset + 0x120 + ((8 * i) + 4)));
            }

            // parse Exheader
            this.ExHeaderHash         = ParseFile.ParseSimpleOffset(fs, offset + 0x160, 0x20);
            this.AdditionalHeaderSize = ParseFile.ReadUintLE(fs, offset + 0x180);
            this.SectorZeroOffset     = ParseFile.ReadUintLE(fs, offset + 0x184);
            this.PartitionFlags       = ParseFile.ReadUlongLE(fs, offset + 0x188);

            this.PartitionIds = new ulong[8];
            for (int i = 0; i < 8; i++)
            {
                this.PartitionIds[i] = ParseFile.ReadUlongLE(fs, offset + 0x190 + (8 * i));
            }


            this.Reserved01 = ParseFile.ParseSimpleOffset(fs, offset + 0x1D0, 0x20);
            this.Reserved02 = ParseFile.ParseSimpleOffset(fs, offset + 0x1F0, 0xE);
            this.Unknown01  = ParseFile.ReadByte(fs, 0x1FE);
            this.Unknown02  = ParseFile.ReadByte(fs, 0x1FF);

            // parse Card Info
            this.CardInfoWritableAddress = ParseFile.ReadInt32LE(fs, offset + 0x200);
            this.CardInfoBitmask         = ParseFile.ReadUintLE(fs, offset + 0x204);
            this.CardInfoReserved01      = ParseFile.ParseSimpleOffset(fs, offset + 0x208, 0xDF8);
            this.CardInfoMediaId         = ParseFile.ReadUlongLE(fs, offset + 0x1000);
            this.CardInfoReserved02      = ParseFile.ReadUlongLE(fs, offset + 0x1008);
            this.CardInfoInitialData     = ParseFile.ParseSimpleOffset(fs, offset + 0x1010, 0x30);
            this.CardInfoReserved03      = ParseFile.ParseSimpleOffset(fs, offset + 0x1040, 0xC0);
            this.CardInfoNcchHeaderCopy  = ParseFile.ParseSimpleOffset(fs, offset + 0x1011, 0x100);
        }
Example #11
0
        private void InitializeAndValidateFat(FileStream isoStream)
        {
            this.FileAllocationTable = new uint[this.ClusterCount + 2]; // first 2 entries of FAT contain info

            for (ulong i = 0; i < (this.ClusterCount + 2); i++)
            {
                this.FileAllocationTable[i] = ParseFile.ReadUintLE(isoStream, (long)(this.FatAbsoluteOffset + (i * 4)));

                if (i == 1) // first two cells are populated
                {
                    if (!((this.FileAllocationTable[0] == MicrosoftExFatFileSystem.FAT_MEDIA_TYPE) &&
                          (this.FileAllocationTable[1] == MicrosoftExFatFileSystem.FAT_CELL1_PLACEHOLDER)))
                    {
                        MessageBox.Show("WARNING: File Allocation Table (FAT) cell check failed.");
                    }
                }
            } // for (ulong i = 0; i < (this.ClusterCount + 2); i++ )
        }
Example #12
0
        private void ParseNcchHeader(FileStream fs, long offset)
        {
            this.NcsdHash    = ParseFile.ParseSimpleOffset(fs, offset, 0x100);
            this.MagicBytes  = ParseFile.ReadUintBE(fs, offset + 0x100);
            this.ContentSize = ParseFile.ReadUintLE(fs, offset + 0x104);
            this.PartitionId = ParseFile.ReadUlongLE(fs, offset + 0x108);

            this.MakerCode      = ParseFile.ReadUshortLE(fs, offset + 0x110);
            this.Version        = ParseFile.ReadUshortLE(fs, offset + 0x112);
            this.Reserved01     = ParseFile.ReadUintLE(fs, offset + 0x114);
            this.ProgramId      = ParseFile.ReadUlongLE(fs, offset + 0x118);
            this.Reserved02     = ParseFile.ParseSimpleOffset(fs, offset + 0x120, 0x10);
            this.LogoRegionHash = ParseFile.ParseSimpleOffset(fs, offset + 0x130, 0x20);
            this.ProductCode    = ParseFile.ReadAsciiString(fs, offset + 0x150);

            this.ExtendedHeaderHash = ParseFile.ParseSimpleOffset(fs, offset + 0x160, 0x10);
            this.ExtendedHeaderSize = ParseFile.ReadUintLE(fs, offset + 0x180);

            this.Reserved03 = ParseFile.ReadUintLE(fs, offset + 0x184);
            this.Flags      = ParseFile.ReadUlongLE(fs, offset + 0x188);

            this.PlainRegionOffset = ParseFile.ReadUintLE(fs, offset + 0x190);
            this.PlainRegionSize   = ParseFile.ReadUintLE(fs, offset + 0x194);

            this.LogoRegionOffset = ParseFile.ReadUintLE(fs, offset + 0x198);
            this.LogoRegionSize   = ParseFile.ReadUintLE(fs, offset + 0x19C);

            this.ExeFsOffset   = ParseFile.ReadUintLE(fs, offset + 0x1A0);
            this.ExeFsSize     = ParseFile.ReadUintLE(fs, offset + 0x1A4);
            this.ExeFsHashSize = ParseFile.ReadUintLE(fs, offset + 0x1A8);
            this.Reserved04    = ParseFile.ReadUintLE(fs, offset + 0x1AC);

            this.RomFsOffset   = ParseFile.ReadUintLE(fs, offset + 0x1B0);
            this.RomFsSize     = ParseFile.ReadUintLE(fs, offset + 0x1B4);
            this.RomFsHashSize = ParseFile.ReadUintLE(fs, offset + 0x1B8);
            this.Reserved05    = ParseFile.ReadUintLE(fs, offset + 0x1BC);

            this.ExeSuperblockHash   = ParseFile.ParseSimpleOffset(fs, offset + 0x1C0, 0x20);
            this.RomFsSuperblockHash = ParseFile.ParseSimpleOffset(fs, offset + 0x1E0, 0x20);
        }
Example #13
0
        public void InitializeExeFileSystem(FileStream isoStream, long offset, string nextDirectoryName)
        {
            string fileName;
            long   fileOffset;
            uint   fileLength;

            byte[] hash;
            long   hashOffset;

            Nintendo3dsCtrFile file;

            // parse file entries
            for (int i = 0; i < 10; i++)
            {
                // check if row has data
                if (ParseFile.ReadByte(isoStream, offset + (0x10 * i)) != 0)
                {
                    // read VFS items
                    fileName = ParseFile.ReadAsciiString(isoStream, offset + (0x10 * i));

                    fileOffset  = ParseFile.ReadUintLE(isoStream, offset + (0x10 * i) + 8);
                    fileOffset += offset + 0x200;

                    fileLength = ParseFile.ReadUintLE(isoStream, offset + (0x10 * i) + 0xC);

                    // read SHA256 hash
                    hashOffset = offset + 0x200 - (0x20 * (i + 1));
                    hash       = ParseFile.ParseSimpleOffset(isoStream, hashOffset, 0x20);

                    // build file object
                    file = new Nintendo3dsCtrFile(isoStream, nextDirectoryName, this.SourceFilePath,
                                                  fileName, fileOffset, fileLength, this.FileSystem, null);
                    file.Sha256Hash = hash;
                    this.FileArray.Add(file);
                }
            }
        }
Example #14
0
        public void ParseHeader(FileStream inStream, long offsetToHeader)
        {
            long frameOffsetOffset;
            long audioIdOffet;
            int  fullHeaderSize;
            byte versionId;

            this.MagicBytes = ParseFile.ParseSimpleOffset(inStream, offsetToHeader, 3);
            if (ParseFile.CompareSegment(this.MagicBytes, 0, BINK01_HEADER))
            {
                this.BinkVersion = BinkType.Version01;
            }
            else if (ParseFile.CompareSegment(this.MagicBytes, 0, BINK02_HEADER))
            {
                versionId = ParseFile.ReadByte(inStream, offsetToHeader + 3);

                if (versionId < 0x69) // version "i"
                {
                    this.BinkVersion = BinkType.Version01;
                }
                else // version "a" through "h"
                {
                    this.BinkVersion = BinkType.Version02;
                }
            }
            else
            {
                throw new FormatException("Unrecognized Magic Bytes for Bink.");
            }

            this.FrameCount      = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(inStream, offsetToHeader + 8, 4), 0);
            this.AudioTrackCount = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(inStream, offsetToHeader + 0x28, 4), 0);

            // get Audio Track Ids
            this.AudioTrackIds = new uint[this.AudioTrackCount];

            for (uint i = 0; i < this.AudioTrackCount; i++)
            {
                audioIdOffet = offsetToHeader + 0x2C + (this.AudioTrackCount * 8) + (i * 4);

                if (this.BinkVersion == BinkType.Version02)
                {
                    audioIdOffet += 4;
                }

                this.AudioTrackIds[i] = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(inStream, audioIdOffet, 4), 0);
            }

            // get frame offsets
            this.FrameOffsetList = new FrameOffsetStruct[this.FrameCount];

            for (uint i = 0; i < this.FrameCount; i++)
            {
                frameOffsetOffset = offsetToHeader + 0x2C + (this.AudioTrackCount * 0xC) + (i * 4);

                if (this.BinkVersion == BinkType.Version02)
                {
                    frameOffsetOffset += 4;
                }

                this.FrameOffsetList[i].FrameOffset = ParseFile.ReadUintLE(inStream, frameOffsetOffset);

                if ((this.FrameOffsetList[i].FrameOffset & 1) == 1)
                {
                    this.FrameOffsetList[i].IsKeyFrame   = true;
                    this.FrameOffsetList[i].FrameOffset &= 0xFFFFFFFE; // mask off bit 0
                }
            }

            // get full header
            fullHeaderSize = (int)(offsetToHeader + 0x2C + (this.AudioTrackCount * 0xC) + (this.FrameCount * 4) + 4);

            if (this.BinkVersion == BinkType.Version02)
            {
                fullHeaderSize += 4;
            }

            this.FullHeader = ParseFile.ParseSimpleOffset(inStream, offsetToHeader, fullHeaderSize);
        }
Example #15
0
        public CriAfs2Archive(FileStream fs, long offset)
        {
            ushort previousCueId = ushort.MaxValue;

            if (IsCriAfs2Archive(fs, offset))
            {
                this.SourceFile = fs.Name;
                long afs2FileSize = fs.Length;

                this.MagicBytes = ParseFile.ParseSimpleOffset(fs, offset, SIGNATURE.Length);
                this.Version    = ParseFile.ParseSimpleOffset(fs, offset + 4, 4);
                this.FileCount  = ParseFile.ReadUintLE(fs, offset + 8);

                // setup offset field size
                int  offsetFieldSize = this.Version[1]; // known values: 2 and 4.  4 is most common.  I've only seen 2 in 'se_enemy_gurdon_galaga_bee.acb' from Sonic Lost World.
                uint offsetMask      = 0;

                for (int j = 0; j < offsetFieldSize; j++)
                {
                    offsetMask |= (uint)((byte)0xFF << (j * 8));
                }

                if (this.FileCount > ushort.MaxValue)
                {
                    throw new FormatException(String.Format("ERROR, file count exceeds max value for ushort.  Please report this at official feedback forums (see 'Other' menu item).", fs.Name));
                }

                this.ByteAlignment = ParseFile.ReadUintLE(fs, offset + 0xC);
                this.Files         = new Dictionary <ushort, CriAfs2File>((int)this.FileCount);

                CriAfs2File dummy;

                for (ushort i = 0; i < this.FileCount; i++)
                {
                    dummy = new CriAfs2File();

                    dummy.CueId         = ParseFile.ReadUshortLE(fs, offset + (0x10 + (2 * i)));
                    dummy.FileOffsetRaw = ParseFile.ReadUintLE(fs, offset + (0x10 + (this.FileCount * 2) + (offsetFieldSize * i)));

                    // mask off unneeded info
                    dummy.FileOffsetRaw &= offsetMask;

                    // add offset
                    dummy.FileOffsetRaw += offset;  // for AFS2 files inside of other files (ACB, etc.)

                    // set file offset to byte alignment
                    if ((dummy.FileOffsetRaw % this.ByteAlignment) != 0)
                    {
                        dummy.FileOffsetByteAligned = MathUtil.RoundUpToByteAlignment(dummy.FileOffsetRaw, this.ByteAlignment);
                    }
                    else
                    {
                        dummy.FileOffsetByteAligned = dummy.FileOffsetRaw;
                    }

                    //---------------
                    // set file size
                    //---------------
                    // last file will use final offset entry
                    if (i == this.FileCount - 1)
                    {
                        dummy.FileLength = (ParseFile.ReadUintLE(fs, offset + (0x10 + (this.FileCount * 2) + ((offsetFieldSize) * i)) + offsetFieldSize) + offset) - dummy.FileOffsetByteAligned;
                    }

                    // else set length for previous cue id
                    if (previousCueId != ushort.MaxValue)
                    {
                        this.Files[previousCueId].FileLength = dummy.FileOffsetRaw - this.Files[previousCueId].FileOffsetByteAligned;
                    }

                    this.Files.Add(dummy.CueId, dummy);
                    previousCueId = dummy.CueId;
                } // for (uint i = 0; i < this.FileCount; i++)
            }
            else
            {
                throw new FormatException(String.Format("AFS2 magic bytes not found at offset: 0x{0}.", offset.ToString("X8")));
            }
        }
Example #16
0
        public static long Uncompress(Stream inFile, long offset, long input_size, string outFile)
        {
            byte[] output_buffer;
            long   bytes_output = 0;

            byte[] magicBytes = ParseFile.ParseSimpleOffset(inFile, offset, CRILAYLA_SIGNATURE.GetLength(0));

            if (!ParseFile.CompareSegment(magicBytes, 0, CRILAYLA_SIGNATURE))
            {
                throw new FormatException(String.Format("CRILAYLA Signature not found at offset: 0x{0}", offset.ToString("X8")));
            }

            if (!Directory.Exists(Path.GetDirectoryName(outFile)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(outFile));
            }

            long uncompressed_size          = (long)ParseFile.ReadUintLE(inFile, offset + 8);
            long uncompressed_header_offset = (long)(offset + ParseFile.ReadUintLE(inFile, offset + 0x0C) + 0x10);

            if ((uncompressed_header_offset + 0x100) != (offset + input_size))
            {
                throw new FormatException(String.Format("CRILAYLA: Uncompressed header size does not match expected size at offset: 0x{0}", offset.ToString("X8")));
            }

            output_buffer = new byte[uncompressed_size + 0x100];

            // write uncompressed header
            inFile.Position = uncompressed_header_offset;
            inFile.Read(output_buffer, 0, 0x100);

            // do the hocus pocus?
            long input_end    = offset + input_size - 0x100 - 1;
            long input_offset = input_end;
            long output_end   = 0x100 + uncompressed_size - 1;

            byte bit_pool  = 0;
            int  bits_left = 0;

            int[] vle_lens = new int[4] {
                2, 3, 5, 8
            };

            long backreference_offset;
            long backreference_length;

            int vle_level;
            int this_level;

            ushort temp;

            while (bytes_output < uncompressed_size)
            {
                if (get_next_bits(inFile, ref input_offset, ref bit_pool, ref bits_left, 1) > 0)
                {
                    backreference_offset = output_end - bytes_output +
                                           get_next_bits(inFile, ref input_offset, ref bit_pool, ref bits_left, 13) + 3;
                    backreference_length = 3;

                    // decode variable length coding for length
                    for (vle_level = 0; vle_level < vle_lens.Length; vle_level++)
                    {
                        this_level            = get_next_bits(inFile, ref input_offset, ref bit_pool, ref bits_left, vle_lens[vle_level]);
                        backreference_length += this_level;

                        if (this_level != ((1 << vle_lens[vle_level]) - 1))
                        {
                            break;
                        }
                    }

                    if (vle_level == vle_lens.Length)
                    {
                        do
                        {
                            this_level            = get_next_bits(inFile, ref input_offset, ref bit_pool, ref bits_left, 8);
                            backreference_length += this_level;
                        } while (this_level == 255);
                    }

                    //printf("0x%08lx backreference to 0x%lx, length 0x%lx\n", output_end-bytes_output, backreference_offset, backreference_length);
                    for (int i = 0; i < backreference_length; i++)
                    {
                        output_buffer[output_end - bytes_output] = output_buffer[backreference_offset--];
                        bytes_output++;
                    }
                }
                else
                {
                    // verbatim byte
                    temp = get_next_bits(inFile, ref input_offset, ref bit_pool, ref bits_left, 8);
                    output_buffer[output_end - bytes_output] = (byte)temp;

                    //printf("0x%08lx verbatim byte\n", output_end-bytes_output);
                    bytes_output++;
                }
            }

            using (FileStream outStream = File.Open(outFile, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                outStream.Write(output_buffer, 0, output_buffer.Length);
            }

            return(0x100 + bytes_output);
        }
Example #17
0
        private void BuildDirectory(FileStream isoStream, long ivfcOffset, long directoryEntryOffset, long directoryBlockOffset,
                                    long fileBlockOffset)
        {
            RomFsDirEntry           dir  = new RomFsDirEntry();
            RomFsFileEntry          file = new RomFsFileEntry();
            Nintendo3dsCtrDirectory tempDir;
            Nintendo3dsCtrFile      tempFile;

            byte[] nameBytes;
            string nextDirectory;

            // load dir
            dir.ParentOffset  = ParseFile.ReadUintLE(isoStream, ivfcOffset + directoryBlockOffset + directoryEntryOffset);
            dir.SiblingOffset = ParseFile.ReadInt32LE(isoStream, ivfcOffset + directoryBlockOffset + directoryEntryOffset + 4);
            dir.ChildOffset   = ParseFile.ReadInt32LE(isoStream, ivfcOffset + directoryBlockOffset + directoryEntryOffset + 8);
            dir.FileOffset    = ParseFile.ReadInt32LE(isoStream, ivfcOffset + directoryBlockOffset + directoryEntryOffset + 0xC);
            dir.WeirdOffset   = ParseFile.ReadInt32LE(isoStream, ivfcOffset + directoryBlockOffset + directoryEntryOffset + 0x10);
            dir.NameSize      = ParseFile.ReadUintLE(isoStream, ivfcOffset + directoryBlockOffset + directoryEntryOffset + 0x14);

            // build directory name
            if (dir.NameSize > 0)
            {
                nameBytes = ParseFile.ParseSimpleOffset(isoStream, ivfcOffset + directoryBlockOffset + directoryEntryOffset + 0x18, (int)dir.NameSize);
                dir.Name  = ByteConversion.GetUtf16LeText(nameBytes);
            }
            else // this is root
            {
                dir.Name = "RomFS"; // @TODO Make this a constant
            }

            this.DirectoryName = dir.Name;
            nextDirectory      = this.ParentDirectoryName + Path.DirectorySeparatorChar + this.DirectoryName;

            // add files
            if (dir.FileOffset != -1)
            {
                tempFile = new Nintendo3dsCtrFile(isoStream, nextDirectory, isoStream.Name,
                                                  null, ivfcOffset, -1, Nintendo3dsCtr.FileSystemType.RomFS, this.IvfcLevels[2],
                                                  dir.FileOffset, fileBlockOffset, this.RomFsDataOffset);
                this.FileArray.Add(tempFile);

                while (tempFile.SiblingOffset != -1)
                {
                    tempFile = new Nintendo3dsCtrFile(isoStream, nextDirectory, isoStream.Name,
                                                      null, ivfcOffset, -1, Nintendo3dsCtr.FileSystemType.RomFS, this.IvfcLevels[2],
                                                      tempFile.SiblingOffset, fileBlockOffset, this.RomFsDataOffset);

                    this.FileArray.Add(tempFile);
                }
            }

            // get sibling dir
            if (dir.SiblingOffset != -1)
            {
                tempDir = new Nintendo3dsCtrDirectory(isoStream, isoStream.Name, this.ParentDirectoryName,
                                                      ivfcOffset, Nintendo3dsCtr.FileSystemType.RomFS, this.IvfcLevels, dir.SiblingOffset, directoryBlockOffset,
                                                      fileBlockOffset, this.RomFsDataOffset);
                this.SiblingDirectory = tempDir;
            }

            // add subdirs
            if (dir.ChildOffset != -1)
            {
                tempDir = new Nintendo3dsCtrDirectory(isoStream, isoStream.Name, nextDirectory,
                                                      ivfcOffset, Nintendo3dsCtr.FileSystemType.RomFS, this.IvfcLevels, dir.ChildOffset, directoryBlockOffset,
                                                      fileBlockOffset, this.RomFsDataOffset);
                this.SubDirectoryArray.Add(tempDir);

                while (tempDir.SiblingDirectory != null)
                {
                    this.SubDirectoryArray.Add(tempDir.SiblingDirectory);
                    tempDir = tempDir.SiblingDirectory;
                }
            }
        }