示例#1
0
        // Create a new filesystem.
        public Filesystem(BinaryReader r, uint fntOff, uint fntSize, uint fatOff, uint fatSize, bool convertFiles, ConversionInfo conversionInfo)
        {
            // Read a folder.
            Folder ReadFolder(ushort id, Folder parent = null, string folderName = "")
            {
                // Get folder info.
                r.BaseStream.Position = fntOff + 8 * id;
                Folder ret = new Folder();

                ret.Parent = parent;
                ret.Id     = id;
                ret.Name   = folderName;
                uint off = r.ReadUInt32();

                ret.FirstFileId = r.ReadUInt16();
                r.ReadUInt16(); // Parent ID. Root folder is total number of folders.
                r.BaseStream.Position = fntOff + off;

                // Data.
                byte   control = r.ReadByte();
                ushort currId  = ret.FirstFileId;

                while (control != 0)
                {
                    bool folder = (control & 0x80) != 0;
                    control &= 0x7F;
                    string name = new string(r.ReadChars(control));
                    if (folder)
                    {
                        ushort subId     = (ushort)(r.ReadUInt16() & 0xFFF);
                        long   bakPos    = r.BaseStream.Position;
                        Folder newFolder = ReadFolder(subId, ret, name);
                        r.BaseStream.Position = bakPos;
                        ret.Folders.Add(newFolder);
                    }
                    else
                    {
                        long bakPos = r.BaseStream.Position;
                        r.BaseStream.Position = fatOff + currId * 8;
                        uint startOff = r.ReadUInt32();
                        uint endOff   = r.ReadUInt32();
                        r.BaseStream.Position = startOff;
                        byte[]  fileData = r.ReadBytes((int)(endOff - startOff));
                        IFormat newData  = null;
                        if (convertFiles)
                        {
                            string filePath   = name;
                            Folder currFolder = ret;
                            while (currFolder != null)
                            {
                                filePath   = currFolder.Name + "/" + filePath;
                                currFolder = currFolder.Parent;
                            }
                            if (filePath.StartsWith("/"))
                            {
                                filePath = filePath.Substring(1);
                            }
                            newData = FormatUtil.DoExtractionConversion(conversionInfo, r, startOff, filePath, fileData);
                        }
                        else
                        {
                            newData = new GenericFile()
                            {
                                Data = fileData
                            };
                        }
                        r.BaseStream.Position = bakPos;
                        ret.Files.Add(new File()
                        {
                            Name = name, Id = currId++, Data = newData
                        });
                    }
                    control = r.ReadByte();
                }

                // Finish.
                return(ret);
            }

            // Read root.
            var root = ReadFolder(0);

            Folders     = root.Folders;
            Files       = root.Files;
            FirstFileId = root.FirstFileId;
        }
示例#2
0
        // Create a new ROM.
        public ROM(string filePath, string conversionPath)
        {
            // Build system.
            if (!conversionPath.Equals(""))
            {
                Directory.CreateDirectory(conversionPath);
                ConversionInfo = new ConversionInfo(conversionPath);
            }

            // Read the file.
            using (Stream s = new FileStream(filePath, FileMode.Open)) {
                // Read general data.
                BinaryReader r = new BinaryReader(s);
                GameTitle            = r.ReadFixedLen(0xC);
                GameCode             = r.ReadFixedLen(0x4);
                MakerCode            = r.ReadFixedLen(0x2);
                UnitCode             = (UnitCode)r.ReadByte();
                EncryptionSeedSelect = r.ReadByte();
                DeviceCapacity       = r.ReadByte();
                r.ReadBytes(7);
                Revision = r.ReadUInt16();
                Version  = r.ReadByte();
                Flags    = r.ReadByte();
                uint arm9Offset = r.ReadUInt32();
                Arm9EntryAddress = r.ReadUInt32();
                Arm9LoadAddress  = r.ReadUInt32();
                uint arm9Size   = r.ReadUInt32();
                uint arm7Offset = r.ReadUInt32();
                Arm7EntryAddress = r.ReadUInt32();
                Arm7LoadAddress  = r.ReadUInt32();
                uint arm7Size          = r.ReadUInt32();
                uint fntOffset         = r.ReadUInt32();
                uint fntSize           = r.ReadUInt32();
                uint fatOffset         = r.ReadUInt32();
                uint fatSize           = r.ReadUInt32();
                uint arm9OverlayOffset = r.ReadUInt32();
                uint arm9OverlayLength = r.ReadUInt32();
                uint arm7OverlayOffset = r.ReadUInt32();
                uint arm7OverlayLength = r.ReadUInt32();
                NormalCardControlRegisterSettings = r.ReadUInt32();
                SecureCardControlRegisterSettings = r.ReadUInt32();
                uint iconBannerOffset = r.ReadUInt32();
                SecureAreaCRC         = r.ReadUInt16();
                SecureTransferTimeout = r.ReadUInt16();
                Arm9Autoload          = r.ReadUInt32();
                Arm7Autoload          = r.ReadUInt32();
                SecureDisable         = r.ReadUInt64();
                uint romSize = r.ReadUInt32() + 0x88;
                HeaderSize = r.ReadUInt32();

                // Read logo.
                r.BaseStream.Position = 0xC0;
                NintendoLogo          = r.ReadBytes(0x9C);
                r.ReadUInt16(); // Nintendo logo CRC. It is literally just the CRC of the logo.
                r.ReadUInt16(); // Header CRC. It is the CRC of everything up to this point (0 to 0x15E).

                // Get banner.
                r.BaseStream.Position = iconBannerOffset;
                ushort bannerVersion = r.ReadUInt16();
                r.BaseStream.Position -= 2;
                Banner = r.ReadBytes((int)BANNER_LENGTHS[bannerVersion]);

                // Code binaries.
                r.BaseStream.Position = arm9Offset;
                Arm9 = r.ReadBytes((int)arm9Size);
                r.BaseStream.Position = arm7Offset;
                Arm7 = r.ReadBytes((int)arm7Size);

                // Get overlays.
                Arm9Overlays = Overlay.LoadOverlays(r, arm9OverlayOffset, arm9OverlayLength);
                Arm7Overlays = Overlay.LoadOverlays(r, arm7OverlayOffset, arm7OverlayLength);
                for (int i = 0; i < Arm9Overlays.Count; i++)
                {
                    r.BaseStream.Position = fatOffset + Arm9Overlays[i].FileId * 8;
                    uint fileStart = r.ReadUInt32();
                    uint fileEnd   = r.ReadUInt32();
                    r.BaseStream.Position = fileStart;
                    Arm9Overlays[i].Data  = r.ReadBytes((int)(fileEnd - fileStart));
                }
                for (int i = 0; i < Arm7Overlays.Count; i++)
                {
                    r.BaseStream.Position = fatOffset + Arm7Overlays[i].FileId * 8;
                    uint fileStart = r.ReadUInt32();
                    uint fileEnd   = r.ReadUInt32();
                    r.BaseStream.Position = fileStart;
                    Arm7Overlays[i].Data  = r.ReadBytes((int)(fileEnd - fileStart));
                }

                // Read filesystem.
                Filesystem = new Filesystem(r, fntOffset, fntSize, fatOffset, fatSize, !conversionPath.Equals(""), ConversionInfo);

                // Dispose.
                r.Dispose();
            }
        }