public string ReadAsciiString(FileStream fs, long BaseOffset, long UtfOffset) { byte encryptedByte; byte decryptedByte; var asciiVal = new StringBuilder(); // byte xorByte; var fileSize = fs.Length; if (IsEncrypted) { fs.Position = BaseOffset + UtfOffset; if (UtfOffset < CurrentUtfStringOffset) { // reset, maybe add some sort of index later? CurrentUtfStringOffset = 0; } if (CurrentUtfStringOffset == 0) { // reset or initialize CurrentStringXor = Seed; } for (var j = CurrentUtfStringOffset; j < UtfOffset; j++) { if (j > 0) { CurrentStringXor *= Increment; } CurrentUtfStringOffset++; } for (var i = UtfOffset; i < fileSize - (BaseOffset + UtfOffset); i++) { CurrentStringXor *= Increment; CurrentUtfStringOffset++; encryptedByte = (byte)fs.ReadByte(); decryptedByte = (byte)(encryptedByte ^ CurrentStringXor); if (decryptedByte == 0) { break; } else { asciiVal.Append(Convert.ToChar(decryptedByte)); } } } else { asciiVal.Append(ParseFile.ReadAsciiString(fs, BaseOffset + UtfOffset)); } return(asciiVal.ToString()); }
public string ReadAsciiString(FileStream fs, long BaseOffset, long UtfOffset) { byte encryptedByte; byte decryptedByte; StringBuilder asciiVal = new StringBuilder(); byte xorByte; long fileSize = fs.Length; if (this.IsEncrypted) { fs.Position = (BaseOffset + UtfOffset); if (UtfOffset < this.CurrentUtfStringOffset) { // reset, maybe add some sort of index later? this.CurrentUtfStringOffset = 0; } if (this.CurrentUtfStringOffset == 0) { // reset or initialize this.CurrentStringXor = this.Seed; } for (long j = this.CurrentUtfStringOffset; j < UtfOffset; j++) { if (j > 0) { this.CurrentStringXor *= this.Increment; } this.CurrentUtfStringOffset++; } for (long i = UtfOffset; i < (fileSize - (BaseOffset + UtfOffset)); i++) { this.CurrentStringXor *= this.Increment; this.CurrentUtfStringOffset++; encryptedByte = (byte)fs.ReadByte(); decryptedByte = (byte)(encryptedByte ^ this.CurrentStringXor); if (decryptedByte == 0) { break; } else { asciiVal.Append(Convert.ToChar(decryptedByte)); } } } else { asciiVal.Append(ParseFile.ReadAsciiString(fs, BaseOffset + UtfOffset)); } return(asciiVal.ToString()); }
private NintendoU8File getFileNode(FileStream fs, int nodeIndex, string parentDirectory) { // get node u8Node node = this.NodeList[nodeIndex]; // get directory name string fileName = ParseFile.ReadAsciiString(fs, this.NameTableOffset + node.NameOffset); // create file item NintendoU8File newFile = new NintendoU8File(parentDirectory, this.SourceFileName, fileName, node.DataOffset, this.VolumeBaseOffset, node.DataOffset, node.DataSize); return(newFile); }
private void initializeUtfHeader(FileStream UtfTableFs) { this.TableSize = ParseFile.ReadUintBE(UtfTableFs, 4); this.Unknown1 = ParseFile.ReadUshortBE(UtfTableFs, 8); this.RowOffset = (uint)ParseFile.ReadUshortBE(UtfTableFs, 0xA) + 8; this.StringTableOffset = ParseFile.ReadUintBE(UtfTableFs, 0xC) + 8; this.DataOffset = ParseFile.ReadUintBE(UtfTableFs, 0x10) + 8; this.TableNameOffset = ParseFile.ReadUintBE(UtfTableFs, 0x14); this.TableName = ParseFile.ReadAsciiString(UtfTableFs, this.StringTableOffset + this.TableNameOffset); this.NumberOfFields = ParseFile.ReadUshortBE(UtfTableFs, 0x18); this.RowSize = ParseFile.ReadUshortBE(UtfTableFs, 0x1A); this.NumberOfRows = ParseFile.ReadUintBE(UtfTableFs, 0x1C); }
public void ParseFileTable(FileStream isoStream) { FileTableEntry tableEntry = new FileTableEntry(); long fileTableMinOffset; long fileTableMaxOffset; long fileSize = isoStream.Length; // get offset for blocks fileTableMinOffset = ComputeBlockNumberAndGetOffset(this.FileTableBlockNumber, this.HeaderSize, this.BlockSeparation); fileTableMaxOffset = ComputeBlockNumberAndGetOffset(this.FileTableBlockNumber + this.FileTableBlockCount, this.HeaderSize, this.BlockSeparation); // check offsets if ((fileTableMinOffset >= MicrosoftSTFS.FIRST_BLOCK_OFFSET) && (fileTableMinOffset < fileTableMaxOffset) && (fileTableMaxOffset < fileSize)) { for (long i = fileTableMinOffset; i < fileTableMaxOffset; i += 0x40) { tableEntry.FileName = ParseFile.ReadAsciiString(isoStream, i); if (!String.IsNullOrEmpty(tableEntry.FileName)) { tableEntry.Flags = ParseFile.ReadByte(isoStream, i + 0x28); tableEntry.BlocksForFileLE1 = ParseFile.ReadInt24LE(isoStream, i + 0x29); tableEntry.BlocksForFileLE2 = ParseFile.ReadInt24LE(isoStream, i + 0x2C); tableEntry.StartingBlockForFileLE = ParseFile.ReadInt24LE(isoStream, i + 0x2F); tableEntry.PathIndicator = ParseFile.ReadInt16BE(isoStream, i + 0x32); tableEntry.FileSize = ParseFile.ReadUintBE(isoStream, i + 0x34); tableEntry.UpdateDateTime = ParseFile.ReadInt32BE(isoStream, i + 0x38); tableEntry.AccessDateTime = ParseFile.ReadInt32BE(isoStream, i + 0x3C); FileTableEntryArray.Add(tableEntry); } } } else { throw new IndexOutOfRangeException("File Table block IDs do not make sense."); } }
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); } } }
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++) }
private NintendoU8Directory getDirectoryNode(FileStream fs, int nodeIndex, string parentDirectory, out int lastIndexProcessed) { string newParentDirectoryName; uint maxNodeIndex; NintendoU8Directory newSubDirectory; lastIndexProcessed = nodeIndex; // get node u8Node node = this.NodeList[nodeIndex]; // get directory name string directoryName = ParseFile.ReadAsciiString(fs, this.NameTableOffset + node.NameOffset); // create directory item NintendoU8Directory newDirectory = new NintendoU8Directory(this.SourceFileName, directoryName, parentDirectory); // parse other items maxNodeIndex = node.DataSize; for (int i = (nodeIndex + 1); i < maxNodeIndex; i = (lastIndexProcessed + 1)) { node = this.NodeList[i]; newParentDirectoryName = Path.Combine(parentDirectory, directoryName); if (node.IsDirectory()) { newSubDirectory = this.getDirectoryNode(fs, i, newParentDirectoryName, out lastIndexProcessed); if (!newSubDirectory.DirectoryName.Equals(".")) { newDirectory.SubDirectoryArray.Add(newSubDirectory); } else // in current folder "." { // move folders to this folder foreach (NintendoU8Directory d in newSubDirectory.SubDirectories) { newDirectory.SubDirectoryArray.Add(d); } // move files to this folder foreach (NintendoU8File f in newSubDirectory.Files) { newDirectory.FileArray.Add(f); } } } else { newDirectory.FileArray.Add(this.getFileNode(fs, i, newParentDirectoryName)); lastIndexProcessed = i; } } return(newDirectory); }