Esempio n. 1
0
        public static async Task <ExeFs> Load(IBinaryDataAccessor exeFsData)
        {
            var exefs = new ExeFs(exeFsData);
            await exefs.Initialize();

            return(exefs);
        }
Esempio n. 2
0
        public static async Task <TmdMetadata> Load(IBinaryDataAccessor data)
        {
            var tmd = new TmdMetadata(data);
            await tmd.Initalize();

            return(tmd);
        }
Esempio n. 3
0
        public static async Task <CiaFile> Load(IBinaryDataAccessor data)
        {
            var file = new CiaFile(data);
            await file.Initalize();

            return(file);
        }
Esempio n. 4
0
            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);
            }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
            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;
        }
Esempio n. 9
0
 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);
 }
Esempio n. 10
0
        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);
            }
        }
Esempio n. 11
0
        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);
            }
        }
Esempio n. 12
0
 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);
         }
     }
 }
Esempio n. 13
0
        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);
            }
        }
Esempio n. 14
0
        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
        }
Esempio n. 15
0
            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);
            }
Esempio n. 16
0
        /// <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());
        }
Esempio n. 17
0
        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);
            }
        }
Esempio n. 18
0
 public TmdMetadata(IBinaryDataAccessor tmdData)
 {
     TmdData = tmdData ?? throw new ArgumentNullException(nameof(tmdData));
 }
Esempio n. 19
0
 public CiaFile(IBinaryDataAccessor data)
 {
     CiaData = data ?? throw new ArgumentNullException(nameof(data));
 }
Esempio n. 20
0
 public IvfcLevel(IBinaryDataAccessor data, IvfcLevelHeader header)
 {
     LevelData = data ?? throw new ArgumentNullException(nameof(data));
     Header    = header ?? throw new ArgumentNullException(nameof(header));
 }
Esempio n. 21
0
 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));
 }
Esempio n. 23
0
 public ExeFs(IBinaryDataAccessor exeFsData)
 {
     ExeFsData = exeFsData ?? throw new ArgumentNullException(nameof(exeFsData));
 }
Esempio n. 24
0
 public DirectoryMetadata(IBinaryDataAccessor data, IvfcLevelHeader header)
 {
     LevelData       = data ?? throw new ArgumentNullException(nameof(data));
     IvfcLevelHeader = header ?? throw new ArgumentNullException(nameof(data));
 }