public static async Task <ExeFs> Load(IBinaryDataAccessor exeFsData) { var exefs = new ExeFs(exeFsData); await exefs.Initialize(); return(exefs); }
public static async Task <TmdMetadata> Load(IBinaryDataAccessor data) { var tmd = new TmdMetadata(data); await tmd.Initalize(); return(tmd); }
public static async Task <CiaFile> Load(IBinaryDataAccessor data) { var file = new CiaFile(data); await file.Initalize(); return(file); }
public static async Task <DirectoryMetadata> Load(IBinaryDataAccessor data, IvfcLevelHeader header, int offsetOffDirTable) { var offset = header.DirectoryMetadataTableOffset + offsetOffDirTable; var metadata = new DirectoryMetadata(data, header); metadata.ParentDirectoryOffset = await data.ReadInt32Async(offset + 0); metadata.SiblingDirectoryOffset = await data.ReadInt32Async(offset + 4); metadata.FirstChildDirectoryOffset = await data.ReadInt32Async(offset + 8); metadata.FirstFileOffset = await data.ReadInt32Async(offset + 0xC); metadata.NextDirectoryOffset = await data.ReadInt32Async(offset + 0x10); metadata.NameLength = await data.ReadInt32Async(offset + 0x14); if (metadata.NameLength > 0) { metadata.Name = Encoding.Unicode.GetString(await data.ReadArrayAsync(offset + 0x18, Math.Min(metadata.NameLength, MaxFilenameLength))); } await Task.WhenAll( metadata.LoadChildDirectories(), metadata.LoadChildFiles() ); return(metadata); }
public static async Task <RomFs> Load(IBinaryDataAccessor data) { var header = new RomFsHeader(await data.ReadArrayAsync(0, 0x6B)); var romfs = new RomFs(data, header); await romfs.Initialize(); return(romfs); }
public static async Task <IvfcLevel> Load(IBinaryDataAccessor romfsData, IvfcLevelLocation location) { var header = new IvfcLevelHeader(await romfsData.ReadArrayAsync(location.DataOffset, 0x28)); var level = new IvfcLevel(romfsData.GetDataReference(location.DataOffset, location.DataSize), header); await level.Initialize(); return(level); }
public static async Task <NcchPartition> Load(IBinaryDataAccessor data) { NcchHeader header = null; if (data.Length > 0) { header = new NcchHeader(await data.ReadArrayAsync(0, 0x200)); } var partition = new NcchPartition(header); await partition.Initialize(data); return(partition); }
public BinaryDataAccessorReference(IBinaryDataAccessor data, long offset, long length) { if (offset < 0) { throw new ArgumentOutOfRangeException(nameof(offset)); } if (length < 0) { throw new ArgumentOutOfRangeException(nameof(length)); } Data = data ?? throw new ArgumentNullException(nameof(data)); Offset = offset; Length = length; }
public void Write(IBinaryDataAccessor data) { data.WriteInt32(0x00, (int)Features); data.WriteInt32(0x04, Index); data.WriteInt16(0x08, Short08); data.WriteInt16(0x0A, Short0A); data.WriteInt32(0x0C, SortKey); data.Write(0x12, DungeonBalanceIndex); data.Write(0x13, Byte13); data.Write(0x14, MaxItems); data.Write(0x15, MaxTeammates); data.Write(0x17, Byte17); data.Write(0x18, Byte18); data.Write(0x19, Byte19); }
public static async Task <bool> IsNcsd(IBinaryDataAccessor file) { try { if (file.Length < 0x104) { return(false); } return(await file.ReadStringAsync(0x100, 4, Encoding.ASCII) == "NCSD"); } catch (Exception) { return(false); } }
public static async Task <bool> IsRomFs(IBinaryDataAccessor file) { try { if (file.Length < 4) { return(false); } return(await file.ReadStringAsync(0, 4, Encoding.ASCII) == "IVFC"); } catch (Exception) { return(false); } }
public async Task Initialize(IBinaryDataAccessor data) { if (Header != null && Header.RomFsSize > 0) { if (Header.ExeFsOffset > 0 && Header.ExeFsSize > 0) { ExeFs = await ExeFs.Load(data.GetDataReference((long)Header.ExeFsOffset *MediaUnitSize, (long)Header.ExeFsSize *MediaUnitSize)); } if (Header.RomFsOffset > 0 && Header.RomFsOffset > 0) { RomFs = await RomFs.Load(data.GetDataReference((long)Header.RomFsOffset *MediaUnitSize, (long)Header.RomFsSize *MediaUnitSize)); } if (Header.ExHeaderSize > 0) { ExHeader = data.GetDataReference(0x200, Header.ExHeaderSize); } } }
public static async Task <bool> IsExeFs(IBinaryDataAccessor file) { try { if (file.Length < 0x200) { return(false); } var exefsHeaders = (await ExeFs.Load(file)).Headers.Where(h => !string.IsNullOrEmpty(h.Filename)); if (!exefsHeaders.Any()) { return(false); } return(exefsHeaders.All(h => h.Offset >= 0x200 && (h.Offset + h.FileSize) < file.Length)); } catch (Exception) { return(false); } }
public RomFs(IBinaryDataAccessor data, RomFsHeader header) { Data = data ?? throw new ArgumentNullException(nameof(data)); Header = header ?? throw new ArgumentNullException(nameof(header)); LevelLocations = new IvfcLevelLocation[] { new IvfcLevelLocation { HashBlockSize = 1 << header.Level1BlockSize, HashOffset = 0x60 }, new IvfcLevelLocation { HashBlockSize = 1 << header.Level2BlockSize }, new IvfcLevelLocation { HashBlockSize = 1 << header.Level3BlockSize } }; BodyOffset = Util.Align64(LevelLocations[0].HashOffset + header.MasterHashSize, LevelLocations[2].HashBlockSize); BodySize = header.Level3HashDataSize; LevelLocations[2].DataOffset = BodyOffset; LevelLocations[2].DataSize = Util.Align64(BodySize, LevelLocations[2].HashBlockSize); LevelLocations[1].HashOffset = Util.Align64(BodyOffset + BodySize, LevelLocations[2].HashBlockSize); LevelLocations[2].HashOffset = LevelLocations[1].HashOffset + header.Level2LogicalOffset - header.Level1LogicalOffset; LevelLocations[1].DataOffset = LevelLocations[2].HashOffset; LevelLocations[1].DataSize = Util.Align64(header.Level2HashDataSize, LevelLocations[1].HashBlockSize); LevelLocations[0].DataOffset = LevelLocations[2].HashOffset; LevelLocations[0].DataSize = Util.Align64(header.Level1HashDataSize, LevelLocations[0].HashBlockSize); // To-do: verify hashes }
public static async Task <FileMetadata> Load(IBinaryDataAccessor data, IvfcLevelHeader header, long offsetFromMetadataTable) { var offset = header.FileMetadataTableOffset + offsetFromMetadataTable; var metadata = new FileMetadata(data, header); metadata.ContainingDirectoryOffset = await data.ReadInt32Async(offset + 0); metadata.NextSiblingFileOffset = await data.ReadInt32Async(offset + 4); metadata.FileDataOffset = await data.ReadInt64Async(offset + 8); metadata.FileDataLength = await data.ReadInt64Async(offset + 0x10); metadata.NextFileOffset = await data.ReadInt32Async(offset + 0x18); metadata.NameLength = await data.ReadInt32Async(offset + 0x1C); if (metadata.NameLength > 0) { metadata.Name = Encoding.Unicode.GetString(await data.ReadArrayAsync(offset + 0x20, Math.Min(metadata.NameLength, MaxFilenameLength))); } return(metadata); }
/// <summary> /// Writes the current state of the NCSD partition to the given binary data accessor /// </summary> /// <param name="data">Data accessor to receive the binary data</param> public async Task WriteBinary(IBinaryDataAccessor data) { long offset = 0x4000; var partitionHeaders = new List <NcsdPartitionInfo>(); for (int i = 0; i < Partitions.Length; i++) { if (Partitions[i] != null) { var bytesWritten = await Partitions[i].WriteBinary(data.Slice(offset, data.Length)); partitionHeaders.Add(new NcsdPartitionInfo { CryptType = 0, Length = (int)((bytesWritten + 0x200 - 1) / 0x200), Offset = (int)((offset + 0x200 - 1) / 0x200) }); offset += bytesWritten + (0x200 - (bytesWritten % 0x200)); } else { partitionHeaders.Add(new NcsdPartitionInfo { CryptType = 0, Length = 0, Offset = 0 }); } } Header.Partitions = partitionHeaders.ToArray(); var headerData = Header.ToByteArray(); await data.WriteAsync(0, headerData); await data.WriteAsync(headerData.Length, Enumerable.Repeat <byte>(0xFF, 0x4000 - headerData.Length).ToArray()); }
private IBinaryDataAccessor GetDataReference(string[] parts, bool throwIfNotFound = true) { IBinaryDataAccessor getExeFsDataReference(string[] pathParts, int partitionId) { if (pathParts.Length == 2) { return(GetPartitionOrDefault(partitionId)?.ExeFs?.GetDataReference(pathParts.Last())); } return(null); } IBinaryDataAccessor getRomFsDataReference(string[] pathParts, int partitionId) { var currentDirectory = Partitions[partitionId]?.RomFs?.Level3.RootDirectoryMetadataTable; for (int i = 1; i < pathParts.Length - 1; i += 1) { currentDirectory = currentDirectory?.ChildDirectories.Where(x => string.Compare(x.Name, pathParts[i], true) == 0).FirstOrDefault(); } if (currentDirectory != null) { if (ReferenceEquals(currentDirectory, Partitions[partitionId].RomFs.Level3.RootDirectoryMetadataTable)) { // The root RomFS directory doesn't contain files; those are located in the level 3 return(GetPartitionOrDefault(partitionId).RomFs.Level3.RootFiles.FirstOrDefault(f => string.Compare(f.Name, pathParts.Last(), true) == 0)?.GetDataReference()); } else { return(currentDirectory.ChildFiles.FirstOrDefault(f => string.Compare(f.Name, pathParts.Last(), true) == 0)?.GetDataReference()); } } return(null); } IBinaryDataAccessor dataReference = null; var firstDirectory = parts[0].ToLower(); switch (firstDirectory) { case "exefs-partition-0": case "exefs": dataReference = getExeFsDataReference(parts, 0); break; case "romfs-partition-0": case "romfs": dataReference = getRomFsDataReference(parts, 0); break; case "romfs-partition-1": case "manual": dataReference = getRomFsDataReference(parts, 1); break; case "romfs-partition-2": case "downloadplay": dataReference = getRomFsDataReference(parts, 2); break; case "romfs-partition-6": case "n3dsupdate": dataReference = getRomFsDataReference(parts, 6); break; case "romfs-partition-7": case "o3dsupdate": dataReference = getRomFsDataReference(parts, 7); break; case "exheader.bin": dataReference = GetPartitionOrDefault(0)?.ExHeader; break; default: if (firstDirectory.StartsWith("romfs-partition-")) { var partitionNumRaw = firstDirectory.Split("-".ToCharArray(), 3)[2]; if (int.TryParse(partitionNumRaw, out var partitionNum)) { dataReference = getRomFsDataReference(parts, partitionNum); } } else if (firstDirectory.StartsWith("exefs-partition-")) { var partitionNumRaw = firstDirectory.Split("-".ToCharArray(), 3)[2]; if (int.TryParse(partitionNumRaw, out var partitionNum)) { dataReference = getExeFsDataReference(parts, partitionNum); } } if (firstDirectory.StartsWith("romfs-")) { var partitionNumRaw = firstDirectory.Split("-".ToCharArray(), 2)[1].Split(".".ToCharArray(), 2)[0]; if (int.TryParse(partitionNumRaw, out var partitionNum)) { throw new NotImplementedException(); } } else if (firstDirectory.StartsWith("exefs-")) { var partitionNumRaw = firstDirectory.Split("-".ToCharArray(), 2)[1].Split(".".ToCharArray(), 2)[0]; if (int.TryParse(partitionNumRaw, out var partitionNum)) { throw new NotImplementedException(); } } else if (firstDirectory.StartsWith("exheader-")) { var partitionNumRaw = firstDirectory.Split("-".ToCharArray(), 2)[1].Split(".".ToCharArray(), 2)[0]; if (int.TryParse(partitionNumRaw, out var partitionNum)) { dataReference = GetPartitionOrDefault(partitionNum)?.ExHeader; } } break; } if (dataReference != null) { return(dataReference); } if (throwIfNotFound) { var path = "/" + string.Join("/", parts); throw new FileNotFoundException(string.Format(Properties.Resources.ThreeDsRom_ErrorRomFileNotFound, path), path); } else { return(null); } }
public TmdMetadata(IBinaryDataAccessor tmdData) { TmdData = tmdData ?? throw new ArgumentNullException(nameof(tmdData)); }
public CiaFile(IBinaryDataAccessor data) { CiaData = data ?? throw new ArgumentNullException(nameof(data)); }
public IvfcLevel(IBinaryDataAccessor data, IvfcLevelHeader header) { LevelData = data ?? throw new ArgumentNullException(nameof(data)); Header = header ?? throw new ArgumentNullException(nameof(header)); }
public NcchPartition(RomFs romfs = null, ExeFs exefs = null, IBinaryDataAccessor exheader = null) { RomFs = romfs; ExeFs = exefs; ExHeader = exheader; }
/// <summary> /// Gets a view on top of the current data /// </summary> /// <param name="data">Data to reference</param> /// <param name="offset">Offset of the view</param> /// <param name="length">Maximum length of the view</param> /// <returns>A view on top of the data</returns> public static BinaryDataAccessorReference GetDataReference(this IBinaryDataAccessor data, long offset, long length) { return(new BinaryDataAccessorReference(data, offset, length)); }
public ExeFs(IBinaryDataAccessor exeFsData) { ExeFsData = exeFsData ?? throw new ArgumentNullException(nameof(exeFsData)); }
public DirectoryMetadata(IBinaryDataAccessor data, IvfcLevelHeader header) { LevelData = data ?? throw new ArgumentNullException(nameof(data)); IvfcLevelHeader = header ?? throw new ArgumentNullException(nameof(data)); }