示例#1
0
        public void LoadProgram(string filePath)
        {
            Npdm metaData = GetDefaultNpdm();

            bool isNro = Path.GetExtension(filePath).ToLower() == ".nro";

            FileStream input = new FileStream(filePath, FileMode.Open);

            IExecutable staticObject;

            if (isNro)
            {
                NxRelocatableObject obj = new NxRelocatableObject(input);
                staticObject = obj;

                // homebrew NRO can actually have some data after the actual NRO
                if (input.Length > obj.FileSize)
                {
                    input.Position = obj.FileSize;

                    BinaryReader reader = new BinaryReader(input);

                    uint asetMagic = reader.ReadUInt32();

                    if (asetMagic == 0x54455341)
                    {
                        uint asetVersion = reader.ReadUInt32();
                        if (asetVersion == 0)
                        {
                            ulong iconOffset = reader.ReadUInt64();
                            ulong iconSize   = reader.ReadUInt64();

                            ulong nacpOffset = reader.ReadUInt64();
                            ulong nacpSize   = reader.ReadUInt64();

                            ulong romfsOffset = reader.ReadUInt64();
                            ulong romfsSize   = reader.ReadUInt64();

                            if (romfsSize != 0)
                            {
                                Device.FileSystem.SetRomFs(new HomebrewRomFsStream(input, obj.FileSize + (long)romfsOffset));
                            }
                        }
                        else
                        {
                            Logger.PrintWarning(LogClass.Loader, $"Unsupported ASET header version found \"{asetVersion}\"");
                        }
                    }
                }
            }
            else
            {
                staticObject = new NxStaticObject(input);
            }

            ContentManager.LoadEntries();

            ProgramLoader.LoadStaticObjects(this, metaData, new IExecutable[] { staticObject });
        }
示例#2
0
 public NroInfo(
     NxRelocatableObject executable,
     byte[]              hash,
     ulong nroAddress,
     ulong nroSize,
     ulong bssAddress,
     ulong bssSize,
     ulong totalSize)
 {
     Executable = executable;
     Hash       = hash;
     NroAddress = nroAddress;
     NroSize    = nroSize;
     BssAddress = bssAddress;
     BssSize    = bssSize;
     TotalSize  = totalSize;
 }
示例#3
0
 public NroInfo(
     NxRelocatableObject Executable,
     byte[]              Hash,
     ulong NroAddress,
     ulong NroSize,
     ulong BssAddress,
     ulong BssSize,
     ulong TotalSize)
 {
     this.Executable = Executable;
     this.Hash       = Hash;
     this.NroAddress = NroAddress;
     this.NroSize    = NroSize;
     this.BssAddress = BssAddress;
     this.BssSize    = BssSize;
     this.TotalSize  = TotalSize;
 }
示例#4
0
        public long ParseNro(out NroInfo res, ServiceCtx context, ulong nroAddress, ulong nroSize, ulong bssAddress, ulong bssSize)
        {
            res = null;

            if (_nroInfos.Count >= MaxNro)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.MaxNro));
            }
            else if (nroSize == 0 || nroAddress + nroSize <= nroAddress || (nroSize & 0xFFF) != 0)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.BadSize));
            }
            else if (bssSize != 0 && bssAddress + bssSize <= bssAddress)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.BadSize));
            }
            else if ((nroAddress & 0xFFF) != 0)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.UnalignedAddress));
            }

            uint magic       = context.Memory.ReadUInt32((long)nroAddress + 0x10);
            uint nroFileSize = context.Memory.ReadUInt32((long)nroAddress + 0x18);

            if (magic != NroMagic || nroSize != nroFileSize)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.InvalidNro));
            }

            byte[] nroData = context.Memory.ReadBytes((long)nroAddress, (long)nroSize);
            byte[] nroHash = null;

            MemoryStream stream = new MemoryStream(nroData);

            using (SHA256 hasher = SHA256.Create())
            {
                nroHash = hasher.ComputeHash(stream);
            }

            if (!IsNroHashPresent(nroHash))
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.NroHashNotPresent));
            }

            if (IsNroLoaded(nroHash))
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.NroAlreadyLoaded));
            }

            stream.Position = 0;

            NxRelocatableObject executable = new NxRelocatableObject(stream, nroAddress, bssAddress);

            // check if everything is page align.
            if ((executable.Text.Length & 0xFFF) != 0 || (executable.Ro.Length & 0xFFF) != 0 ||
                (executable.Data.Length & 0xFFF) != 0 || (executable.BssSize & 0xFFF) != 0)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.InvalidNro));
            }

            // check if everything is contiguous.
            if (executable.RoOffset != executable.TextOffset + executable.Text.Length ||
                executable.DataOffset != executable.RoOffset + executable.Ro.Length ||
                nroFileSize != executable.DataOffset + executable.Data.Length)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.InvalidNro));
            }

            // finally check the bss size match.
            if ((ulong)executable.BssSize != bssSize)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.InvalidNro));
            }

            int totalSize = executable.Text.Length + executable.Ro.Length + executable.Data.Length + executable.BssSize;

            res = new NroInfo(
                executable,
                nroHash,
                nroAddress,
                nroSize,
                bssAddress,
                bssSize,
                (ulong)totalSize);

            return(0);
        }
示例#5
0
        public void LoadProgram(string filePath)
        {
            Npdm metaData = GetDefaultNpdm();

            bool isNro = Path.GetExtension(filePath).ToLower() == ".nro";

            FileStream input = new FileStream(filePath, FileMode.Open);

            IExecutable staticObject;

            if (isNro)
            {
                NxRelocatableObject obj = new NxRelocatableObject(input);
                staticObject = obj;

                // homebrew NRO can actually have some data after the actual NRO
                if (input.Length > obj.FileSize)
                {
                    input.Position = obj.FileSize;

                    BinaryReader reader = new BinaryReader(input);

                    uint asetMagic = reader.ReadUInt32();

                    if (asetMagic == 0x54455341)
                    {
                        uint asetVersion = reader.ReadUInt32();
                        if (asetVersion == 0)
                        {
                            ulong iconOffset = reader.ReadUInt64();
                            ulong iconSize   = reader.ReadUInt64();

                            ulong nacpOffset = reader.ReadUInt64();
                            ulong nacpSize   = reader.ReadUInt64();

                            ulong romfsOffset = reader.ReadUInt64();
                            ulong romfsSize   = reader.ReadUInt64();

                            if (romfsSize != 0)
                            {
                                Device.FileSystem.SetRomFs(new HomebrewRomFsStream(input, obj.FileSize + (long)romfsOffset));
                            }

                            if (nacpSize != 0)
                            {
                                input.Seek(obj.FileSize + (long)nacpOffset, SeekOrigin.Begin);

                                reader.Read(ControlData.ByteSpan);

                                ref ApplicationControlProperty nacp = ref ControlData.Value;

                                metaData.TitleName = nacp.Titles[(int)State.DesiredTitleLanguage].Name.ToString();

                                if (string.IsNullOrWhiteSpace(metaData.TitleName))
                                {
                                    metaData.TitleName = nacp.Titles.ToArray().FirstOrDefault(x => x.Name[0] != 0).Name.ToString();
                                }

                                if (nacp.PresenceGroupId != 0)
                                {
                                    metaData.Aci0.TitleId = nacp.PresenceGroupId;
                                }
                                else if (nacp.SaveDataOwnerId.Value != 0)
                                {
                                    metaData.Aci0.TitleId = nacp.SaveDataOwnerId.Value;
                                }
                                else if (nacp.AddOnContentBaseId != 0)
                                {
                                    metaData.Aci0.TitleId = nacp.AddOnContentBaseId - 0x1000;
                                }
                                else
                                {
                                    metaData.Aci0.TitleId = 0000000000000000;
                                }
                            }
                        }
                        else
                        {
                            Logger.PrintWarning(LogClass.Loader, $"Unsupported ASET header version found \"{asetVersion}\"");
                        }
                    }
                }
            }
示例#6
0
        public void LoadProgram(string filePath)
        {
            Npdm metaData = GetDefaultNpdm();

            bool isNro = Path.GetExtension(filePath).ToLower() == ".nro";

            FileStream input = new FileStream(filePath, FileMode.Open);

            IExecutable staticObject;

            if (isNro)
            {
                NxRelocatableObject obj = new NxRelocatableObject(input);
                staticObject = obj;

                // homebrew NRO can actually have some data after the actual NRO
                if (input.Length > obj.FileSize)
                {
                    input.Position = obj.FileSize;

                    BinaryReader reader = new BinaryReader(input);

                    uint asetMagic = reader.ReadUInt32();

                    if (asetMagic == 0x54455341)
                    {
                        uint asetVersion = reader.ReadUInt32();
                        if (asetVersion == 0)
                        {
                            ulong iconOffset = reader.ReadUInt64();
                            ulong iconSize   = reader.ReadUInt64();

                            ulong nacpOffset = reader.ReadUInt64();
                            ulong nacpSize   = reader.ReadUInt64();

                            ulong romfsOffset = reader.ReadUInt64();
                            ulong romfsSize   = reader.ReadUInt64();

                            if (romfsSize != 0)
                            {
                                Device.FileSystem.SetRomFs(new HomebrewRomFsStream(input, obj.FileSize + (long)romfsOffset));
                            }

                            if (nacpSize != 0)
                            {
                                input.Seek(obj.FileSize + (long)nacpOffset, SeekOrigin.Begin);
                                using (MemoryStream stream = new MemoryStream(reader.ReadBytes((int)nacpSize)))
                                {
                                    ControlData = new Nacp(stream);
                                }

                                metaData.TitleName = ControlData.Descriptions[(int)State.DesiredTitleLanguage].Title;

                                if (string.IsNullOrWhiteSpace(metaData.TitleName))
                                {
                                    metaData.TitleName = ControlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title;
                                }

                                metaData.Aci0.TitleId = ControlData.PresenceGroupId;

                                if (metaData.Aci0.TitleId == 0)
                                {
                                    metaData.Aci0.TitleId = ControlData.SaveDataOwnerId;
                                }

                                if (metaData.Aci0.TitleId == 0)
                                {
                                    metaData.Aci0.TitleId = ControlData.AddOnContentBaseId - 0x1000;
                                }

                                if (metaData.Aci0.TitleId.ToString("x16") == "fffffffffffff000")
                                {
                                    metaData.Aci0.TitleId = 0000000000000000;
                                }
                            }
                        }
                        else
                        {
                            Logger.PrintWarning(LogClass.Loader, $"Unsupported ASET header version found \"{asetVersion}\"");
                        }
                    }
                }
            }
            else
            {
                staticObject = new NxStaticObject(input);
            }

            ContentManager.LoadEntries();

            TitleName = CurrentTitle = metaData.TitleName;
            TitleID   = metaData.Aci0.TitleId.ToString("x16");

            ProgramLoader.LoadStaticObjects(this, metaData, new IExecutable[] { staticObject });
        }
示例#7
0
        public long ParseNro(out NroInfo Res, ServiceCtx Context, ulong NroAddress, ulong NroSize, ulong BssAddress, ulong BssSize)
        {
            Res = null;

            if (NroInfos.Count >= MaxNro)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.MaxNro));
            }
            else if (NroSize == 0 || NroAddress + NroSize <= NroAddress || (NroSize & 0xFFF) != 0)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.BadSize));
            }
            else if (BssSize != 0 && BssAddress + BssSize <= BssAddress)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.BadSize));
            }
            else if ((NroAddress & 0xFFF) != 0)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.UnalignedAddress));
            }

            uint Magic       = Context.Memory.ReadUInt32((long)NroAddress + 0x10);
            uint NroFileSize = Context.Memory.ReadUInt32((long)NroAddress + 0x18);

            if (Magic != NroMagic || NroSize != NroFileSize)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.InvalidNro));
            }

            byte[] NroData = Context.Memory.ReadBytes((long)NroAddress, (long)NroSize);
            byte[] NroHash = null;

            MemoryStream Stream = new MemoryStream(NroData);

            using (SHA256 Hasher = SHA256.Create())
            {
                NroHash = Hasher.ComputeHash(Stream);
            }

            if (!IsNroHashPresent(NroHash))
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.NroHashNotPresent));
            }

            if (IsNroLoaded(NroHash))
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.NroAlreadyLoaded));
            }

            Stream.Position = 0;

            NxRelocatableObject Executable = new NxRelocatableObject(Stream, NroAddress, BssAddress);

            // check if everything is page align.
            if ((Executable.Text.Length & 0xFFF) != 0 || (Executable.RO.Length & 0xFFF) != 0 ||
                (Executable.Data.Length & 0xFFF) != 0 || (Executable.BssSize & 0xFFF) != 0)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.InvalidNro));
            }

            // check if everything is contiguous.
            if (Executable.ROOffset != Executable.TextOffset + Executable.Text.Length ||
                Executable.DataOffset != Executable.ROOffset + Executable.RO.Length ||
                NroFileSize != Executable.DataOffset + Executable.Data.Length)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.InvalidNro));
            }

            // finally check the bss size match.
            if ((ulong)Executable.BssSize != BssSize)
            {
                return(MakeError(ErrorModule.Loader, LoaderErr.InvalidNro));
            }

            int TotalSize = Executable.Text.Length + Executable.RO.Length + Executable.Data.Length + Executable.BssSize;

            Res = new NroInfo(
                Executable,
                NroHash,
                NroAddress,
                NroSize,
                BssAddress,
                BssSize,
                (ulong)TotalSize);

            return(0);
        }