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; }
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); }
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); }
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"))); } }
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; } }
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); }
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); }
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; }
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); }
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); }
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++ ) }
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); }
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); } } }
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); }
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"))); } }
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); }
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; } } }