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 }); }
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; }
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; }
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); }
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}\""); } } } }
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 }); }
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); }