private static void processControlNacp(Stream controlNacp, ref Title title) { log?.WriteLine("Processing Control NACP"); Nacp nacp = new Nacp(controlNacp); bool first = true; foreach (NacpDescription description in nacp.Descriptions) { if (!String.IsNullOrEmpty(description.Title)) { if (first) { title.titleName = description.Title; title.publisher = description.Developer; first = false; } title.languages.Add(Title.LanguageCode.ElementAtOrDefault((int)description.Language)); } } title.displayVersion = nacp.DisplayVersion; }
private void jSONToolStripMenuItem_Click(object sender, EventArgs e) { if (Control != null) { using (var Rom = Control.OpenSection(0, false, IntegrityCheckLevel.None)) { var Romfs = new Romfs(Rom); var Dialog = folderBrowserDialog1.ShowDialog(); if (Dialog != DialogResult.Cancel) { using (var InFile = Romfs.OpenFile(Romfs.Files.FirstOrDefault(f => f.Name == "control.nacp"))) using (var Read = new BinaryReader(InFile)) { var Nacp = new Nacp(Read); var Settings = new JsonSerializerSettings { Formatting = Formatting.Indented }; File.WriteAllText($"{folderBrowserDialog1.SelectedPath}/{Nca.Header.TitleId:x16}_control.json", JsonConvert.SerializeObject(Nacp, Settings)); } } } } else { MessageBox.Show("Error: No control is present!"); } }
public void ReadControlData(Nca controlNca) { Romfs controlRomfs = new Romfs(controlNca.OpenSection(0, false, FsIntegrityCheckLevel, true)); IStorage controlFile = controlRomfs.OpenFile("/control.nacp"); ControlData = new Nacp(controlFile.AsStream()); }
public void ReadControlData(Nca controlNca) { IFileSystem controlFs = controlNca.OpenFileSystem(NcaSectionType.Data, FsIntegrityCheckLevel); IFile controlFile = controlFs.OpenFile("/control.nacp", OpenMode.Read); ControlData = new Nacp(controlFile.AsStream()); TitleName = CurrentTitle = ControlData.Descriptions[(int)State.DesiredTitleLanguage].Title; }
public void ReadControlData(Nca controlNca) { Romfs controlRomfs = new Romfs(controlNca.OpenSection(0, false, FsIntegrityCheckLevel)); byte[] controlFile = controlRomfs.GetFile("/control.nacp"); BinaryReader reader = new BinaryReader(new MemoryStream(controlFile)); ControlData = new Nacp(reader); }
public void ReadControlData(Nca ControlNca) { Romfs ControlRomfs = new Romfs(ControlNca.OpenSection(0, false, EnableFsIntegrityChecks)); byte[] ControlFile = ControlRomfs.GetFile("/control.nacp"); BinaryReader Reader = new BinaryReader(new MemoryStream(ControlFile)); ControlData = new Nacp(Reader); }
public void ReadControlData(Nca controlNca) { IFileSystem controlFs = controlNca.OpenFileSystem(NcaSectionType.Data, FsIntegrityCheckLevel); Result result = controlFs.OpenFile(out IFile controlFile, "/control.nacp", OpenMode.Read); if (result.IsSuccess()) { ControlData = new Nacp(controlFile.AsStream()); TitleName = ControlData.Descriptions[(int)State.DesiredTitleLanguage].Title; } }
private string[] GetTitleMeta(string TitleID = null) { var Info = new string[] { "No title info loaded.", "" }; if (Control != null) { var Rom = new Romfs(Control.OpenSection(0, false, IntegrityCheckLevel.None, true)); var OpenControl = Rom.OpenFile(Rom.Files.FirstOrDefault(f => f.Name == "control.nacp")); var OpenIcon = Rom.OpenFile(Rom.Files.FirstOrDefault(f => f.Name.Contains("icon"))); var ControlNacp = new Nacp(OpenControl.AsStream()); var Lang = ControlNacp.Descriptions.FirstOrDefault(l => l.Title.Length > 1); Info[0] = Lang.Title; Info[1] = Lang.Developer; pictureBox1.Image = Image.FromStream(OpenIcon.AsStream()); } return(Info); }
private static void processControlNacp(Stream controlNacp, ref Title title) { log?.WriteLine("Processing Control NACP"); Nacp nacp = new Nacp(controlNacp); foreach (NacpDescription description in nacp.Descriptions) { if (!String.IsNullOrEmpty(description.Title)) { title.titleName = description.Title; break; } } title.displayVersion = nacp.DisplayVersion; }
private string[] GetTitleMeta(string TitleID = null) { var Info = new string[] { "Title missing from database", "" }; if (Control != null) { var Rom = new Romfs(Control.OpenSection(0, false, IntegrityCheckLevel.None)); var OpenControl = Rom.OpenFile(Rom.Files.FirstOrDefault(f => f.Name == "control.nacp")); var OpenIcon = Rom.OpenFile(Rom.Files.FirstOrDefault(f => f.Name.Contains("icon"))); var ControlNacp = new Nacp(new BinaryReader(OpenControl)); var Lang = ControlNacp.Languages.FirstOrDefault(l => l.Title.Length > 1); Info[0] = Lang.Title; Info[1] = Lang.Developer; pictureBox1.Image = Image.FromStream(OpenIcon); } else { try { using (var WC = new WebClient()) { var Cli = WC.DownloadData($"https://gamechat.network/nucleus?title_id={TitleID}"); pictureBox1.Image = Image.FromStream(new MemoryStream(Cli)); Info[0] = Encoding.UTF8.GetString ( WC.ResponseHeaders.Get("X-GCN-Game-Name") .Select(b => (byte)b).ToArray() ); Info[1] = Encoding.UTF8.GetString ( WC.ResponseHeaders.Get("X-GCN-Game-Dev") .Select(b => (byte)b).ToArray() ); } } catch { } } return(Info); }
private static void GetNameIdDeveloper(Nacp controlData, out string titleName, out string titleId, out string developer) { Enum.TryParse(_desiredTitleLanguage.ToString(), out TitleLanguage desiredTitleLanguage); NacpDescription nacpDescription = controlData.Descriptions.ToList().Find(x => x.Language == desiredTitleLanguage); if (nacpDescription != null) { titleName = nacpDescription.Title; developer = nacpDescription.Developer; } else { titleName = null; developer = null; } if (string.IsNullOrWhiteSpace(titleName)) { titleName = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title; } if (string.IsNullOrWhiteSpace(developer)) { developer = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Developer)).Developer; } if (controlData.PresenceGroupId != 0) { titleId = controlData.PresenceGroupId.ToString("x16"); } else if (controlData.SaveDataOwnerId != 0) { titleId = controlData.SaveDataOwnerId.ToString("x16"); } else if (controlData.AddOnContentBaseId != 0) { titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16"); } else { titleId = "0000000000000000"; } }
public Horizon(Switch device) { ControlData = new Nacp(); Device = device; State = new SystemStateMgr(); ResourceLimit = new KResourceLimit(this); KernelInit.InitializeResourceLimit(ResourceLimit); MemoryRegions = KernelInit.GetMemoryRegions(); LargeMemoryBlockAllocator = new KMemoryBlockAllocator(MemoryBlockAllocatorSize * 2); SmallMemoryBlockAllocator = new KMemoryBlockAllocator(MemoryBlockAllocatorSize); UserSlabHeapPages = new KSlabHeap( UserSlabHeapBase, UserSlabHeapItemSize, UserSlabHeapSize); CriticalSection = new KCriticalSection(this); Scheduler = new KScheduler(this); TimeManager = new KTimeManager(); Synchronization = new KSynchronization(this); ContextIdManager = new KContextIdManager(); _kipId = InitialKipId; _processId = InitialProcessId; Scheduler.StartAutoPreemptionThread(); KernelInitialized = true; ThreadCounter = new CountdownEvent(1); Processes = new SortedDictionary <long, KProcess>(); AutoObjectNames = new ConcurrentDictionary <string, KAutoObject>(); //Note: This is not really correct, but with HLE of services, the only memory //region used that is used is Application, so we can use the other ones for anything. KMemoryRegionManager region = MemoryRegions[(int)MemoryRegion.NvServices]; ulong hidPa = region.Address; ulong fontPa = region.Address + HidSize; ulong iirsPa = region.Address + HidSize + FontSize; ulong timePa = region.Address + HidSize + FontSize + IirsSize; HidBaseAddress = (long)(hidPa - DramMemoryMap.DramBase); KPageList hidPageList = new KPageList(); KPageList fontPageList = new KPageList(); KPageList iirsPageList = new KPageList(); KPageList timePageList = new KPageList(); hidPageList.AddRange(hidPa, HidSize / KMemoryManager.PageSize); fontPageList.AddRange(fontPa, FontSize / KMemoryManager.PageSize); iirsPageList.AddRange(iirsPa, IirsSize / KMemoryManager.PageSize); timePageList.AddRange(timePa, TimeSize / KMemoryManager.PageSize); HidSharedMem = new KSharedMemory(this, hidPageList, 0, 0, MemoryPermission.Read); FontSharedMem = new KSharedMemory(this, fontPageList, 0, 0, MemoryPermission.Read); IirsSharedMem = new KSharedMemory(this, iirsPageList, 0, 0, MemoryPermission.Read); TimeSharedMem = new KSharedMemory(this, timePageList, 0, 0, MemoryPermission.Read); AppletState = new AppletStateMgr(this); AppletState.SetFocus(true); Font = new SharedFontManager(device, (long)(fontPa - DramMemoryMap.DramBase)); IUserInterface.InitializePort(this); VsyncEvent = new KEvent(this); LoadKeySet(); ContentManager = new ContentManager(device); }
public void LoadNca(Nca mainNca, Nca controlNca) { if (mainNca.Header.ContentType != ContentType.Program) { Logger.PrintError(LogClass.Loader, "Selected NCA is not a \"Program\" NCA"); return; } Stream romfsStream = mainNca.OpenSection(ProgramPartitionType.Data, false, FsIntegrityCheckLevel); Stream exefsStream = mainNca.OpenSection(ProgramPartitionType.Code, false, FsIntegrityCheckLevel); if (exefsStream == null) { Logger.PrintError(LogClass.Loader, "No ExeFS found in NCA"); return; } if (romfsStream == null) { Logger.PrintWarning(LogClass.Loader, "No RomFS found in NCA"); } else { Device.FileSystem.SetRomFs(romfsStream); } Pfs exefs = new Pfs(exefsStream); Npdm metaData = null; if (exefs.FileExists("main.npdm")) { Logger.PrintInfo(LogClass.Loader, "Loading main.npdm..."); metaData = new Npdm(exefs.OpenFile("main.npdm")); } else { Logger.PrintWarning(LogClass.Loader, $"NPDM file not found, using default values!"); metaData = GetDefaultNpdm(); } List <IExecutable> staticObjects = new List <IExecutable>(); void LoadNso(string filename) { foreach (PfsFileEntry file in exefs.Files.Where(x => x.Name.StartsWith(filename))) { if (Path.GetExtension(file.Name) != string.Empty) { continue; } Logger.PrintInfo(LogClass.Loader, $"Loading {filename}..."); NxStaticObject staticObject = new NxStaticObject(exefs.OpenFile(file)); staticObjects.Add(staticObject); } } Nacp ReadControlData() { Romfs controlRomfs = new Romfs(controlNca.OpenSection(0, false, FsIntegrityCheckLevel)); byte[] controlFile = controlRomfs.GetFile("/control.nacp"); BinaryReader reader = new BinaryReader(new MemoryStream(controlFile)); Nacp controlData = new Nacp(reader); CurrentTitle = controlData.Languages[(int)State.DesiredTitleLanguage].Title; if (string.IsNullOrWhiteSpace(CurrentTitle)) { CurrentTitle = controlData.Languages.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title; } return(controlData); } if (controlNca != null) { ReadControlData(); } else { CurrentTitle = metaData.Aci0.TitleId.ToString("x16"); } if (!metaData.Is64Bits) { throw new NotImplementedException("32-bit titles are not supported!"); } LoadNso("rtld"); LoadNso("main"); LoadNso("subsdk"); LoadNso("sdk"); ContentManager.LoadEntries(); ProgramLoader.LoadStaticObjects(this, metaData, staticObjects.ToArray()); }
public Horizon(Switch device) { ControlData = new Nacp(); Device = device; State = new SystemStateMgr(); ResourceLimit = new KResourceLimit(this); KernelInit.InitializeResourceLimit(ResourceLimit); MemoryRegions = KernelInit.GetMemoryRegions(); LargeMemoryBlockAllocator = new KMemoryBlockAllocator(MemoryBlockAllocatorSize * 2); SmallMemoryBlockAllocator = new KMemoryBlockAllocator(MemoryBlockAllocatorSize); UserSlabHeapPages = new KSlabHeap( UserSlabHeapBase, UserSlabHeapItemSize, UserSlabHeapSize); CriticalSection = new KCriticalSection(this); Scheduler = new KScheduler(this); TimeManager = new KTimeManager(); Synchronization = new KSynchronization(this); ContextIdManager = new KContextIdManager(); _kipId = InitialKipId; _processId = InitialProcessId; Scheduler.StartAutoPreemptionThread(); KernelInitialized = true; ThreadCounter = new CountdownEvent(1); Processes = new SortedDictionary <long, KProcess>(); AutoObjectNames = new ConcurrentDictionary <string, KAutoObject>(); // Note: This is not really correct, but with HLE of services, the only memory // region used that is used is Application, so we can use the other ones for anything. KMemoryRegionManager region = MemoryRegions[(int)MemoryRegion.NvServices]; ulong hidPa = region.Address; ulong fontPa = region.Address + HidSize; ulong iirsPa = region.Address + HidSize + FontSize; ulong timePa = region.Address + HidSize + FontSize + IirsSize; HidBaseAddress = (long)(hidPa - DramMemoryMap.DramBase); KPageList hidPageList = new KPageList(); KPageList fontPageList = new KPageList(); KPageList iirsPageList = new KPageList(); KPageList timePageList = new KPageList(); hidPageList.AddRange(hidPa, HidSize / KMemoryManager.PageSize); fontPageList.AddRange(fontPa, FontSize / KMemoryManager.PageSize); iirsPageList.AddRange(iirsPa, IirsSize / KMemoryManager.PageSize); timePageList.AddRange(timePa, TimeSize / KMemoryManager.PageSize); HidSharedMem = new KSharedMemory(this, hidPageList, 0, 0, MemoryPermission.Read); FontSharedMem = new KSharedMemory(this, fontPageList, 0, 0, MemoryPermission.Read); IirsSharedMem = new KSharedMemory(this, iirsPageList, 0, 0, MemoryPermission.Read); KSharedMemory timeSharedMemory = new KSharedMemory(this, timePageList, 0, 0, MemoryPermission.Read); TimeServiceManager.Instance.Initialize(device, this, timeSharedMemory, (long)(timePa - DramMemoryMap.DramBase), TimeSize); AppletState = new AppletStateMgr(this); AppletState.SetFocus(true); Font = new SharedFontManager(device, (long)(fontPa - DramMemoryMap.DramBase)); IUserInterface.InitializePort(this); VsyncEvent = new KEvent(this); LoadKeySet(); ContentManager = new ContentManager(device); // TODO: use set:sys (and get external clock source id from settings) // TODO: use "time!standard_steady_clock_rtc_update_interval_minutes" and implement a worker thread to be accurate. UInt128 clockSourceId = new UInt128(Guid.NewGuid().ToByteArray()); IRtcManager.GetExternalRtcValue(out ulong rtcValue); // We assume the rtc is system time. TimeSpanType systemTime = TimeSpanType.FromSeconds((long)rtcValue); // First init the standard steady clock TimeServiceManager.Instance.SetupStandardSteadyClock(null, clockSourceId, systemTime, TimeSpanType.Zero, TimeSpanType.Zero, false); TimeServiceManager.Instance.SetupStandardLocalSystemClock(null, new SystemClockContext(), systemTime.ToSeconds()); if (NxSettings.Settings.TryGetValue("time!standard_network_clock_sufficient_accuracy_minutes", out object standardNetworkClockSufficientAccuracyMinutes)) { TimeSpanType standardNetworkClockSufficientAccuracy = new TimeSpanType((int)standardNetworkClockSufficientAccuracyMinutes * 60000000000); TimeServiceManager.Instance.SetupStandardNetworkSystemClock(new SystemClockContext(), standardNetworkClockSufficientAccuracy); } TimeServiceManager.Instance.SetupStandardUserSystemClock(null, false, SteadyClockTimePoint.GetRandom()); // FIXME: TimeZone shoud be init here but it's actually done in ContentManager TimeServiceManager.Instance.SetupEphemeralNetworkSystemClock(); LocalFileSystem serverBaseFs = new LocalFileSystem(device.FileSystem.GetBasePath()); DefaultFsServerObjects fsServerObjects = DefaultFsServerObjects.GetDefaultEmulatedCreators(serverBaseFs, KeySet); GameCard = fsServerObjects.GameCard; FileSystemServerConfig fsServerConfig = new FileSystemServerConfig { FsCreators = fsServerObjects.FsCreators, DeviceOperator = fsServerObjects.DeviceOperator, ExternalKeySet = KeySet.ExternalKeySet }; FsServer = new FileSystemServer(fsServerConfig); }
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 static void LoadApplications(List <string> appDirs, VirtualFileSystem virtualFileSystem, Language desiredTitleLanguage) { int numApplicationsFound = 0; int numApplicationsLoaded = 0; _loadingError = false; _virtualFileSystem = virtualFileSystem; _desiredTitleLanguage = desiredTitleLanguage; // Builds the applications list with paths to found applications List <string> applications = new List <string>(); foreach (string appDir in appDirs) { if (!Directory.Exists(appDir)) { Logger.PrintWarning(LogClass.Application, $"The \"game_dirs\" section in \"Config.json\" contains an invalid directory: \"{appDir}\""); continue; } foreach (string app in Directory.GetFiles(appDir, "*.*", SearchOption.AllDirectories)) { if ((Path.GetExtension(app).ToLower() == ".nsp") || (Path.GetExtension(app).ToLower() == ".pfs0") || (Path.GetExtension(app).ToLower() == ".xci") || (Path.GetExtension(app).ToLower() == ".nca") || (Path.GetExtension(app).ToLower() == ".nro") || (Path.GetExtension(app).ToLower() == ".nso")) { applications.Add(app); numApplicationsFound++; } } } // Loops through applications list, creating a struct and then firing an event containing the struct for each application foreach (string applicationPath in applications) { double fileSize = new FileInfo(applicationPath).Length * 0.000000000931; string titleName = "Unknown"; string titleId = "0000000000000000"; string developer = "Unknown"; string version = "0"; string saveDataPath = null; byte[] applicationIcon = null; try { using (FileStream file = new FileStream(applicationPath, FileMode.Open, FileAccess.Read)) { if ((Path.GetExtension(applicationPath).ToLower() == ".nsp") || (Path.GetExtension(applicationPath).ToLower() == ".pfs0") || (Path.GetExtension(applicationPath).ToLower() == ".xci")) { try { PartitionFileSystem pfs; bool isExeFs = false; if (Path.GetExtension(applicationPath).ToLower() == ".xci") { Xci xci = new Xci(_virtualFileSystem.KeySet, file.AsStorage()); pfs = xci.OpenPartition(XciPartitionType.Secure); } else { pfs = new PartitionFileSystem(file.AsStorage()); // If the NSP doesn't have a main NCA, decrement the number of applications found and then continue to the next application. bool hasMainNca = false; foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*")) { if (Path.GetExtension(fileEntry.FullPath).ToLower() == ".nca") { pfs.OpenFile(out IFile ncaFile, fileEntry.FullPath, OpenMode.Read).ThrowIfFailure(); Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage()); int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); if (nca.Header.ContentType == NcaContentType.Program && !nca.Header.GetFsHeader(dataIndex).IsPatchSection()) { hasMainNca = true; break; } } else if (Path.GetFileNameWithoutExtension(fileEntry.FullPath) == "main") { isExeFs = true; } } if (!hasMainNca && !isExeFs) { numApplicationsFound--; continue; } } if (isExeFs) { applicationIcon = _nspIcon; Result result = pfs.OpenFile(out IFile npdmFile, "/main.npdm", OpenMode.Read); if (ResultFs.PathNotFound.Includes(result)) { Npdm npdm = new Npdm(npdmFile.AsStream()); titleName = npdm.TitleName; titleId = npdm.Aci0.TitleId.ToString("x16"); } } else { // Store the ControlFS in variable called controlFs GetControlFsAndTitleId(pfs, out IFileSystem controlFs, out titleId); // Creates NACP class from the NACP file controlFs.OpenFile(out IFile controlNacpFile, "/control.nacp", OpenMode.Read).ThrowIfFailure(); Nacp controlData = new Nacp(controlNacpFile.AsStream()); // Get the title name, title ID, developer name and version number from the NACP version = controlData.DisplayVersion; GetNameIdDeveloper(controlData, out titleName, out _, out developer); // Read the icon from the ControlFS and store it as a byte array try { controlFs.OpenFile(out IFile icon, $"/icon_{_desiredTitleLanguage}.dat", OpenMode.Read).ThrowIfFailure(); using (MemoryStream stream = new MemoryStream()) { icon.AsStream().CopyTo(stream); applicationIcon = stream.ToArray(); } } catch (HorizonResultException) { foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*")) { if (entry.Name == "control.nacp") { continue; } controlFs.OpenFile(out IFile icon, entry.FullPath, OpenMode.Read).ThrowIfFailure(); using (MemoryStream stream = new MemoryStream()) { icon.AsStream().CopyTo(stream); applicationIcon = stream.ToArray(); } if (applicationIcon != null) { break; } } if (applicationIcon == null) { applicationIcon = Path.GetExtension(applicationPath).ToLower() == ".xci" ? _xciIcon : _nspIcon; } } } } catch (MissingKeyException exception) { applicationIcon = Path.GetExtension(applicationPath).ToLower() == ".xci" ? _xciIcon : _nspIcon; Logger.PrintWarning(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}"); } catch (InvalidDataException) { applicationIcon = Path.GetExtension(applicationPath).ToLower() == ".xci" ? _xciIcon : _nspIcon; Logger.PrintWarning(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {applicationPath}"); } catch (Exception exception) { Logger.PrintWarning(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}"); Logger.PrintDebug(LogClass.Application, exception.ToString()); numApplicationsFound--; _loadingError = true; continue; } } else if (Path.GetExtension(applicationPath).ToLower() == ".nro") { BinaryReader reader = new BinaryReader(file); byte[] Read(long position, int size) { file.Seek(position, SeekOrigin.Begin); return(reader.ReadBytes(size)); } try { file.Seek(24, SeekOrigin.Begin); int assetOffset = reader.ReadInt32(); if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET") { byte[] iconSectionInfo = Read(assetOffset + 8, 0x10); long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0); long iconSize = BitConverter.ToInt64(iconSectionInfo, 8); ulong nacpOffset = reader.ReadUInt64(); ulong nacpSize = reader.ReadUInt64(); // Reads and stores game icon as byte array applicationIcon = Read(assetOffset + iconOffset, (int)iconSize); // Creates memory stream out of byte array which is the NACP using (MemoryStream stream = new MemoryStream(Read(assetOffset + (int)nacpOffset, (int)nacpSize))) { // Creates NACP class from the memory stream Nacp controlData = new Nacp(stream); // Get the title name, title ID, developer name and version number from the NACP version = controlData.DisplayVersion; GetNameIdDeveloper(controlData, out titleName, out titleId, out developer); } } else { applicationIcon = _nroIcon; titleName = Path.GetFileNameWithoutExtension(applicationPath); } } catch { Logger.PrintWarning(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}"); numApplicationsFound--; continue; } } else if (Path.GetExtension(applicationPath).ToLower() == ".nca") { try { Nca nca = new Nca(_virtualFileSystem.KeySet, new FileStream(applicationPath, FileMode.Open, FileAccess.Read).AsStorage()); int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); if (nca.Header.ContentType != NcaContentType.Program || nca.Header.GetFsHeader(dataIndex).IsPatchSection()) { numApplicationsFound--; continue; } } catch (InvalidDataException) { Logger.PrintWarning(LogClass.Application, $"The NCA header content type check has failed. This is usually because the header key is incorrect or missing. Errored File: {applicationPath}"); } catch { Logger.PrintWarning(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}"); numApplicationsFound--; _loadingError = true; continue; } applicationIcon = _ncaIcon; titleName = Path.GetFileNameWithoutExtension(applicationPath); } // If its an NSO we just set defaults else if (Path.GetExtension(applicationPath).ToLower() == ".nso") { applicationIcon = _nsoIcon; titleName = Path.GetFileNameWithoutExtension(applicationPath); } } } catch (IOException exception) { Logger.PrintWarning(LogClass.Application, exception.Message); numApplicationsFound--; _loadingError = true; continue; } ApplicationMetadata appMetadata = LoadAndSaveMetaData(titleId); if (ulong.TryParse(titleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdNum)) { SaveDataFilter filter = new SaveDataFilter(); filter.SetUserId(new UserId(1, 0)); filter.SetProgramId(new TitleId(titleIdNum)); Result result = virtualFileSystem.FsClient.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, ref filter); if (result.IsSuccess()) { saveDataPath = Path.Combine(virtualFileSystem.GetNandPath(), $"user/save/{saveDataInfo.SaveDataId:x16}"); } } ApplicationData data = new ApplicationData() { Favorite = appMetadata.Favorite, Icon = applicationIcon, TitleName = titleName, TitleId = titleId, Developer = developer, Version = version, TimePlayed = ConvertSecondsToReadableString(appMetadata.TimePlayed), LastPlayed = appMetadata.LastPlayed, FileExtension = Path.GetExtension(applicationPath).ToUpper().Remove(0, 1), FileSize = (fileSize < 1) ? (fileSize * 1024).ToString("0.##") + "MB" : fileSize.ToString("0.##") + "GB", Path = applicationPath, SaveDataPath = saveDataPath }; numApplicationsLoaded++; OnApplicationAdded(new ApplicationAddedEventArgs() { AppData = data }); OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs() { NumAppsFound = numApplicationsFound, NumAppsLoaded = numApplicationsLoaded }); } OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs() { NumAppsFound = numApplicationsFound, NumAppsLoaded = numApplicationsLoaded }); if (_loadingError) { Gtk.Application.Invoke(delegate { GtkDialog.CreateErrorDialog("One or more files encountered could not be loaded, check logs for more info."); }); } }
public static void Init(List <string> AppDirs, Keyset keySet, SystemState.TitleLanguage desiredTitleLanguage) { KeySet = keySet; DesiredTitleLanguage = desiredTitleLanguage; // Loads the default application Icons RyujinxNspIcon = GetResourceBytes("Ryujinx.Ui.assets.ryujinxNSPIcon.png"); RyujinxXciIcon = GetResourceBytes("Ryujinx.Ui.assets.ryujinxXCIIcon.png"); RyujinxNcaIcon = GetResourceBytes("Ryujinx.Ui.assets.ryujinxNCAIcon.png"); RyujinxNroIcon = GetResourceBytes("Ryujinx.Ui.assets.ryujinxNROIcon.png"); RyujinxNsoIcon = GetResourceBytes("Ryujinx.Ui.assets.ryujinxNSOIcon.png"); // Builds the applications list with paths to found applications List <string> applications = new List <string>(); foreach (string appDir in AppDirs) { if (Directory.Exists(appDir) == false) { Logger.PrintWarning(LogClass.Application, $"The \"game_dirs\" section in \"Config.json\" contains an invalid directory: \"{appDir}\""); continue; } DirectoryInfo AppDirInfo = new DirectoryInfo(appDir); foreach (FileInfo App in AppDirInfo.GetFiles()) { if ((Path.GetExtension(App.ToString()) == ".xci") || (Path.GetExtension(App.ToString()) == ".nca") || (Path.GetExtension(App.ToString()) == ".nsp") || (Path.GetExtension(App.ToString()) == ".pfs0") || (Path.GetExtension(App.ToString()) == ".nro") || (Path.GetExtension(App.ToString()) == ".nso")) { applications.Add(App.ToString()); } } } // Loops through applications list, creating a struct for each application and then adding the struct to a list of structs ApplicationLibraryData = new List <ApplicationData>(); foreach (string applicationPath in applications) { double filesize = new FileInfo(applicationPath).Length * 0.000000000931; string titleName = null; string titleId = null; string developer = null; string version = null; byte[] applicationIcon = null; using (FileStream file = new FileStream(applicationPath, FileMode.Open, FileAccess.Read)) { if ((Path.GetExtension(applicationPath) == ".nsp") || (Path.GetExtension(applicationPath) == ".pfs0") || (Path.GetExtension(applicationPath) == ".xci")) { try { IFileSystem controlFs = null; // Store the ControlFS in variable called controlFs if (Path.GetExtension(applicationPath) == ".xci") { Xci xci = new Xci(KeySet, file.AsStorage()); controlFs = GetControlFs(xci.OpenPartition(XciPartitionType.Secure)); } else { controlFs = GetControlFs(new PartitionFileSystem(file.AsStorage())); } // Creates NACP class from the NACP file controlFs.OpenFile(out IFile controlNacpFile, "/control.nacp", OpenMode.Read).ThrowIfFailure(); Nacp controlData = new Nacp(controlNacpFile.AsStream()); // Get the title name, title ID, developer name and version number from the NACP version = controlData.DisplayVersion; titleName = controlData.Descriptions[(int)DesiredTitleLanguage].Title; if (string.IsNullOrWhiteSpace(titleName)) { titleName = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title; } titleId = controlData.PresenceGroupId.ToString("x16"); if (string.IsNullOrWhiteSpace(titleId)) { titleId = controlData.SaveDataOwnerId.ToString("x16"); } if (string.IsNullOrWhiteSpace(titleId)) { titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16"); } developer = controlData.Descriptions[(int)DesiredTitleLanguage].Developer; if (string.IsNullOrWhiteSpace(developer)) { developer = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Developer)).Developer; } // Read the icon from the ControlFS and store it as a byte array try { controlFs.OpenFile(out IFile icon, $"/icon_{DesiredTitleLanguage}.dat", OpenMode.Read).ThrowIfFailure(); using (MemoryStream stream = new MemoryStream()) { icon.AsStream().CopyTo(stream); applicationIcon = stream.ToArray(); } } catch (HorizonResultException) { foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*")) { if (entry.Name == "control.nacp") { continue; } controlFs.OpenFile(out IFile icon, entry.FullPath, OpenMode.Read).ThrowIfFailure(); using (MemoryStream stream = new MemoryStream()) { icon.AsStream().CopyTo(stream); applicationIcon = stream.ToArray(); } if (applicationIcon != null) { break; } } if (applicationIcon == null) { applicationIcon = NspOrXciIcon(applicationPath); } } } catch (MissingKeyException exception) { titleName = "Unknown"; titleId = "Unknown"; developer = "Unknown"; version = "?"; applicationIcon = NspOrXciIcon(applicationPath); Logger.PrintWarning(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}"); } catch (InvalidDataException) { titleName = "Unknown"; titleId = "Unknown"; developer = "Unknown"; version = "?"; applicationIcon = NspOrXciIcon(applicationPath); Logger.PrintWarning(LogClass.Application, $"The file is not an NCA file or the header key is incorrect. Errored File: {applicationPath}"); } catch (Exception exception) { Logger.PrintWarning(LogClass.Application, $"This warning usualy means that you have a DLC in one of you game directories\n{exception}"); continue; } } else if (Path.GetExtension(applicationPath) == ".nro") { BinaryReader reader = new BinaryReader(file); byte[] Read(long Position, int Size) { file.Seek(Position, SeekOrigin.Begin); return(reader.ReadBytes(Size)); } file.Seek(24, SeekOrigin.Begin); int AssetOffset = reader.ReadInt32(); if (Encoding.ASCII.GetString(Read(AssetOffset, 4)) == "ASET") { byte[] IconSectionInfo = Read(AssetOffset + 8, 0x10); long iconOffset = BitConverter.ToInt64(IconSectionInfo, 0); long iconSize = BitConverter.ToInt64(IconSectionInfo, 8); ulong nacpOffset = reader.ReadUInt64(); ulong nacpSize = reader.ReadUInt64(); // Reads and stores game icon as byte array applicationIcon = Read(AssetOffset + iconOffset, (int)iconSize); // Creates memory stream out of byte array which is the NACP using (MemoryStream stream = new MemoryStream(Read(AssetOffset + (int)nacpOffset, (int)nacpSize))) { // Creates NACP class from the memory stream Nacp controlData = new Nacp(stream); // Get the title name, title ID, developer name and version number from the NACP version = controlData.DisplayVersion; titleName = controlData.Descriptions[(int)DesiredTitleLanguage].Title; if (string.IsNullOrWhiteSpace(titleName)) { titleName = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title; } titleId = controlData.PresenceGroupId.ToString("x16"); if (string.IsNullOrWhiteSpace(titleId)) { titleId = controlData.SaveDataOwnerId.ToString("x16"); } if (string.IsNullOrWhiteSpace(titleId)) { titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16"); } developer = controlData.Descriptions[(int)DesiredTitleLanguage].Developer; if (string.IsNullOrWhiteSpace(developer)) { developer = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Developer)).Developer; } } } else { applicationIcon = RyujinxNroIcon; titleName = "Application"; titleId = "0000000000000000"; developer = "Unknown"; version = "?"; } } // If its an NCA or NSO we just set defaults else if ((Path.GetExtension(applicationPath) == ".nca") || (Path.GetExtension(applicationPath) == ".nso")) { if (Path.GetExtension(applicationPath) == ".nca") { applicationIcon = RyujinxNcaIcon; } else if (Path.GetExtension(applicationPath) == ".nso") { applicationIcon = RyujinxNsoIcon; } string fileName = Path.GetFileName(applicationPath); string fileExt = Path.GetExtension(applicationPath); StringBuilder titlename = new StringBuilder(); titlename.Append(fileName); titlename.Remove(fileName.Length - fileExt.Length, fileExt.Length); titleName = titlename.ToString(); titleId = "0000000000000000"; version = "?"; developer = "Unknown"; } } string[] playedData = GetPlayedData(titleId, "00000000000000000000000000000001"); ApplicationData data = new ApplicationData() { Icon = applicationIcon, TitleName = titleName, TitleId = titleId, Developer = developer, Version = version, TimePlayed = playedData[0], LastPlayed = playedData[1], FileExt = Path.GetExtension(applicationPath).ToUpper().Remove(0, 1), FileSize = (filesize < 1) ? (filesize * 1024).ToString("0.##") + "MB" : filesize.ToString("0.##") + "GB", Path = applicationPath, }; ApplicationLibraryData.Add(data); } }
public void LoadNca(Nca mainNca, Nca patchNca, Nca controlNca) { if (mainNca.Header.ContentType != ContentType.Program) { Logger.PrintError(LogClass.Loader, "Selected NCA is not a \"Program\" NCA"); return; } IStorage dataStorage = null; IFileSystem codeFs = null; if (patchNca == null) { if (mainNca.CanOpenSection(NcaSectionType.Data)) { dataStorage = mainNca.OpenStorage(NcaSectionType.Data, FsIntegrityCheckLevel); } if (mainNca.CanOpenSection(NcaSectionType.Code)) { codeFs = mainNca.OpenFileSystem(NcaSectionType.Code, FsIntegrityCheckLevel); } } else { if (patchNca.CanOpenSection(NcaSectionType.Data)) { dataStorage = mainNca.OpenStorageWithPatch(patchNca, NcaSectionType.Data, FsIntegrityCheckLevel); } if (patchNca.CanOpenSection(NcaSectionType.Code)) { codeFs = mainNca.OpenFileSystemWithPatch(patchNca, NcaSectionType.Code, FsIntegrityCheckLevel); } } if (codeFs == null) { Logger.PrintError(LogClass.Loader, "No ExeFS found in NCA"); return; } if (dataStorage == null) { Logger.PrintWarning(LogClass.Loader, "No RomFS found in NCA"); } else { Device.FileSystem.SetRomFs(dataStorage.AsStream(FileAccess.Read)); } LoadExeFs(codeFs, out Npdm metaData); Nacp ReadControlData() { IFileSystem controlRomfs = controlNca.OpenFileSystem(NcaSectionType.Data, FsIntegrityCheckLevel); IFile controlFile = controlRomfs.OpenFile("/control.nacp", OpenMode.Read); Nacp controlData = new Nacp(controlFile.AsStream()); TitleName = CurrentTitle = controlData.Descriptions[(int)State.DesiredTitleLanguage].Title; TitleID = metaData.Aci0.TitleId.ToString("x16"); CurrentTitle = controlData.Descriptions[(int)State.DesiredTitleLanguage].Title; if (string.IsNullOrWhiteSpace(CurrentTitle)) { TitleName = CurrentTitle = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title; } return(controlData); } if (controlNca != null) { ReadControlData(); } else { TitleID = CurrentTitle = metaData.Aci0.TitleId.ToString("x16"); } }
public Horizon(Switch device) { ControlData = new Nacp(); Device = device; State = new SystemStateMgr(); ResourceLimit = new KResourceLimit(this); KernelInit.InitializeResourceLimit(ResourceLimit); MemoryRegions = KernelInit.GetMemoryRegions(); LargeMemoryBlockAllocator = new KMemoryBlockAllocator(MemoryBlockAllocatorSize * 2); SmallMemoryBlockAllocator = new KMemoryBlockAllocator(MemoryBlockAllocatorSize); UserSlabHeapPages = new KSlabHeap( UserSlabHeapBase, UserSlabHeapItemSize, UserSlabHeapSize); CriticalSection = new KCriticalSection(this); Scheduler = new KScheduler(this); TimeManager = new KTimeManager(); Synchronization = new KSynchronization(this); ContextIdManager = new KContextIdManager(); _kipId = InitialKipId; _processId = InitialProcessId; Scheduler.StartAutoPreemptionThread(); KernelInitialized = true; ThreadCounter = new CountdownEvent(1); Processes = new SortedDictionary <long, KProcess>(); AutoObjectNames = new ConcurrentDictionary <string, KAutoObject>(); // Note: This is not really correct, but with HLE of services, the only memory // region used that is used is Application, so we can use the other ones for anything. KMemoryRegionManager region = MemoryRegions[(int)MemoryRegion.NvServices]; ulong hidPa = region.Address; ulong fontPa = region.Address + HidSize; ulong iirsPa = region.Address + HidSize + FontSize; ulong timePa = region.Address + HidSize + FontSize + IirsSize; HidBaseAddress = (long)(hidPa - DramMemoryMap.DramBase); KPageList hidPageList = new KPageList(); KPageList fontPageList = new KPageList(); KPageList iirsPageList = new KPageList(); KPageList timePageList = new KPageList(); hidPageList.AddRange(hidPa, HidSize / KMemoryManager.PageSize); fontPageList.AddRange(fontPa, FontSize / KMemoryManager.PageSize); iirsPageList.AddRange(iirsPa, IirsSize / KMemoryManager.PageSize); timePageList.AddRange(timePa, TimeSize / KMemoryManager.PageSize); HidSharedMem = new KSharedMemory(this, hidPageList, 0, 0, MemoryPermission.Read); FontSharedMem = new KSharedMemory(this, fontPageList, 0, 0, MemoryPermission.Read); IirsSharedMem = new KSharedMemory(this, iirsPageList, 0, 0, MemoryPermission.Read); TimeSharedMem = new KSharedMemory(this, timePageList, 0, 0, MemoryPermission.Read); AppletState = new AppletStateMgr(this); AppletState.SetFocus(true); Font = new SharedFontManager(device, (long)(fontPa - DramMemoryMap.DramBase)); IUserInterface.InitializePort(this); VsyncEvent = new KEvent(this); LoadKeySet(); ContentManager = new ContentManager(device); // TODO: use set:sys (and set external clock source id from settings) // TODO: use "time!standard_steady_clock_rtc_update_interval_minutes" and implement a worker thread to be accurate. SteadyClockCore.Instance.ConfigureSetupValue(); if (Services.Set.NxSettings.Settings.TryGetValue("time!standard_network_clock_sufficient_accuracy_minutes", out object standardNetworkClockSufficientAccuracyMinutes)) { TimeSpanType standardNetworkClockSufficientAccuracy = new TimeSpanType((int)standardNetworkClockSufficientAccuracyMinutes * 60000000000); StandardNetworkSystemClockCore.Instance.SetStandardNetworkClockSufficientAccuracy(standardNetworkClockSufficientAccuracy); } }
// Lets start building evrything private void Compile_button_Click(object sender, EventArgs e) { Control.DircControl.BuildTemp(); Tools Checks = new Tools { IdBox = id_box.Text, NameBox = name_box.Text, AuthorBox = author_box.Text, VersionBox = version_box.Text, Line = line }; if (Checks.Compile_Checks() == true) { Nacp nacp = new Nacp { TitleId = id_box.Text, AppName = name_box.Text, Author = author_box.Text, Version = version_box.Text }; nacp.Build(); Source make = new Source { TitleId = id_box.Text, AppName = name_box.Text, Author = author_box.Text, Version = version_box.Text, Path_Sd = sdmc_path.Text, Path_Romfs = romfs_path.Text, Line = line, NroName = nroname, NroPath = nropath }; make.Meta(); make.Build(); Control.Tools.LsLog(); new Thread(() => new PleaseWait().ShowDialog()).Start(); try { switch (Tools.RunningPlatform()) { case Tools.Platform.Linux: Tools.UnixCommand(id_box.Text); break; case Tools.Platform.Mac: Tools.UnixCommand(id_box.Text); break; case Tools.Platform.Windows: Tools.WinCommand(@"CMD.EXE", "/c make -C " + DircControl.buildpath, false, true); if (File.Exists(DircControl.buildpath + "build/exefs/main") && File.Exists(DircControl.buildpath + "build/exefs/main.npdm")) { Tools.WinCommand(@"CMD.EXE", "/c " + Tools.HacPackBrew(), false, true); } else { MessageBox.Show("First build step failed, Please Check Devkitpro install and verify Enviroment Varibles are set correctly"); } break; default: MessageBox.Show("Couldnt Detect Operating System, This is probably a bug, please report it"); break; } } catch (Exception f) { MessageBox.Show(f.Message); } Control.Tools.LsLog(); PleaseWait w = new PleaseWait(); w = (PleaseWait)Application.OpenForms["PleaseWait"]; w.Invoke(new ThreadStart(delegate { w.Close(); })); } DircControl copy = new DircControl { TitleId = id_box.Text, AppName = name_box.Text }; if (File.Exists(DircControl.buildpath + id_box.Text + ".nsp")) { copy.OutputCopy(); } else { MessageBox.Show("Builing of Nsp Failed, Please refer to logs"); } Icon_Button.BackgroundImage = Properties.Resources._default; if (Convert.ToBoolean(Settings.Default["RollingIdEnable"]) == true) { Control.Tools.IncreaseRollingId(); } if (Directory.Exists(MtX.Control.DircControl.root)) { MtX.Control.DircControl.CleanTemp(); } Reload("Post Build:"); }
public void LoadNca(Nca MainNca, Nca ControlNca) { NcaSection RomfsSection = MainNca.Sections.FirstOrDefault(x => x?.Type == SectionType.Romfs || x?.Type == SectionType.Bktr); NcaSection ExefsSection = MainNca.Sections.FirstOrDefault(x => x?.IsExefs == true); if (ExefsSection == null) { Logger.PrintError(LogClass.Loader, "No ExeFS found in NCA"); return; } if (RomfsSection == null) { Logger.PrintWarning(LogClass.Loader, "No RomFS found in NCA"); } else { Stream RomfsStream = MainNca.OpenSection(RomfsSection.SectionNum, false, EnableFsIntegrityChecks); Device.FileSystem.SetRomFs(RomfsStream); } Stream ExefsStream = MainNca.OpenSection(ExefsSection.SectionNum, false, EnableFsIntegrityChecks); Pfs Exefs = new Pfs(ExefsStream); Npdm MetaData = null; if (Exefs.FileExists("main.npdm")) { Logger.PrintInfo(LogClass.Loader, "Loading main.npdm..."); MetaData = new Npdm(Exefs.OpenFile("main.npdm")); } else { Logger.PrintWarning(LogClass.Loader, $"NPDM file not found, using default values!"); } Process MainProcess = MakeProcess(MetaData); void LoadNso(string Filename) { foreach (PfsFileEntry File in Exefs.Files.Where(x => x.Name.StartsWith(Filename))) { if (Path.GetExtension(File.Name) != string.Empty) { continue; } Logger.PrintInfo(LogClass.Loader, $"Loading {Filename}..."); string Name = Path.GetFileNameWithoutExtension(File.Name); Nso Program = new Nso(Exefs.OpenFile(File), Name); MainProcess.LoadProgram(Program); } } Nacp ReadControlData() { Romfs ControlRomfs = new Romfs(ControlNca.OpenSection(0, false, EnableFsIntegrityChecks)); byte[] ControlFile = ControlRomfs.GetFile("/control.nacp"); BinaryReader Reader = new BinaryReader(new MemoryStream(ControlFile)); Nacp ControlData = new Nacp(Reader); CurrentTitle = ControlData.Languages[(int)State.DesiredTitleLanguage].Title; if (string.IsNullOrWhiteSpace(CurrentTitle)) { CurrentTitle = ControlData.Languages.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title; } return(ControlData); } if (ControlNca != null) { MainProcess.ControlData = ReadControlData(); } else { CurrentTitle = MainProcess.MetaData.ACI0.TitleId.ToString("x16"); } if (!MainProcess.MetaData.Is64Bits) { throw new NotImplementedException("32-bit titles are unsupported!"); } LoadNso("rtld"); MainProcess.SetEmptyArgs(); LoadNso("main"); LoadNso("subsdk"); LoadNso("sdk"); MainProcess.Run(); }
public long GetApplicationControlData(ServiceCtx context) { long position = context.Request.ReceiveBuff[0].Position; Nacp nacp = context.Device.System.ControlData; for (int i = 0; i < 0x10; i++) { NacpDescription description = nacp.Descriptions[i]; byte[] titleData = new byte[0x200]; byte[] developerData = new byte[0x100]; if (description != null && description.Title != null) { byte[] titleDescriptionData = Encoding.ASCII.GetBytes(description.Title); Buffer.BlockCopy(titleDescriptionData, 0, titleData, 0, titleDescriptionData.Length); } if (description != null && description.Developer != null) { byte[] developerDescriptionData = Encoding.ASCII.GetBytes(description.Developer); Buffer.BlockCopy(developerDescriptionData, 0, developerData, 0, developerDescriptionData.Length); } context.Memory.WriteBytes(position, titleData); context.Memory.WriteBytes(position + 0x200, developerData); position += i * 0x300; } byte[] isbn = new byte[0x25]; if (nacp.Isbn != null) { byte[] isbnData = Encoding.ASCII.GetBytes(nacp.Isbn); Buffer.BlockCopy(isbnData, 0, isbn, 0, isbnData.Length); } context.Memory.WriteBytes(position, isbn); position += isbn.Length; context.Memory.WriteByte(position++, nacp.StartupUserAccount); context.Memory.WriteByte(position++, nacp.TouchScreenUsageMode); context.Memory.WriteByte(position++, nacp.AocRegistrationType); context.Memory.WriteInt32(position, nacp.AttributeFlag); position += 4; context.Memory.WriteUInt32(position, nacp.SupportedLanguageFlag); position += 4; context.Memory.WriteUInt32(position, nacp.ParentalControlFlag); position += 4; context.Memory.WriteByte(position++, nacp.Screenshot); context.Memory.WriteByte(position++, nacp.VideoCapture); context.Memory.WriteByte(position++, nacp.DataLossConfirmation); context.Memory.WriteByte(position++, nacp.PlayLogPolicy); context.Memory.WriteUInt64(position, nacp.PresenceGroupId); position += 8; for (int i = 0; i < nacp.RatingAge.Length; i++) { context.Memory.WriteSByte(position++, nacp.RatingAge[i]); } byte[] displayVersion = new byte[0x10]; if (nacp.DisplayVersion != null) { byte[] displayVersionData = Encoding.ASCII.GetBytes(nacp.DisplayVersion); Buffer.BlockCopy(displayVersionData, 0, displayVersion, 0, displayVersionData.Length); } context.Memory.WriteBytes(position, displayVersion); position += displayVersion.Length; context.Memory.WriteUInt64(position, nacp.AddOnContentBaseId); position += 8; context.Memory.WriteUInt64(position, nacp.SaveDataOwnerId); position += 8; context.Memory.WriteInt64(position, nacp.UserAccountSaveDataSize); position += 8; context.Memory.WriteInt64(position, nacp.UserAccountSaveDataJournalSize); position += 8; context.Memory.WriteInt64(position, nacp.DeviceSaveDataSize); position += 8; context.Memory.WriteInt64(position, nacp.DeviceSaveDataJournalSize); position += 8; context.Memory.WriteInt64(position, nacp.BcatDeliveryCacheStorageSize); position += 8; byte[] applicationErrorCodeCategory = new byte[0x8]; if (nacp.ApplicationErrorCodeCategory != null) { byte[] applicationErrorCodeCategoryData = Encoding.ASCII.GetBytes(nacp.ApplicationErrorCodeCategory); Buffer.BlockCopy(applicationErrorCodeCategoryData, 0, applicationErrorCodeCategoryData, 0, applicationErrorCodeCategoryData.Length); } context.Memory.WriteBytes(position, applicationErrorCodeCategory); position += applicationErrorCodeCategory.Length; for (int i = 0; i < nacp.LocalCommunicationId.Length; i++) { context.Memory.WriteUInt64(position, nacp.LocalCommunicationId[i]); position += 8; } context.Memory.WriteByte(position++, nacp.LogoType); context.Memory.WriteByte(position++, nacp.LogoHandling); context.Memory.WriteByte(position++, nacp.RuntimeAddOnContentInstall); byte[] reserved000 = new byte[0x3]; context.Memory.WriteBytes(position, reserved000); position += reserved000.Length; context.Memory.WriteByte(position++, nacp.CrashReport); context.Memory.WriteByte(position++, nacp.Hdcp); context.Memory.WriteUInt64(position, nacp.SeedForPseudoDeviceId); position += 8; byte[] bcatPassphrase = new byte[65]; if (nacp.BcatPassphrase != null) { byte[] bcatPassphraseData = Encoding.ASCII.GetBytes(nacp.BcatPassphrase); Buffer.BlockCopy(bcatPassphraseData, 0, bcatPassphrase, 0, bcatPassphraseData.Length); } context.Memory.WriteBytes(position, bcatPassphrase); position += bcatPassphrase.Length; context.Memory.WriteByte(position++, nacp.Reserved01); byte[] reserved02 = new byte[0x6]; context.Memory.WriteBytes(position, reserved02); position += reserved02.Length; context.Memory.WriteInt64(position, nacp.UserAccountSaveDataSizeMax); position += 8; context.Memory.WriteInt64(position, nacp.UserAccountSaveDataJournalSizeMax); position += 8; context.Memory.WriteInt64(position, nacp.DeviceSaveDataSizeMax); position += 8; context.Memory.WriteInt64(position, nacp.DeviceSaveDataJournalSizeMax); position += 8; context.Memory.WriteInt64(position, nacp.TemporaryStorageSize); position += 8; context.Memory.WriteInt64(position, nacp.CacheStorageSize); position += 8; context.Memory.WriteInt64(position, nacp.CacheStorageJournalSize); position += 8; context.Memory.WriteInt64(position, nacp.CacheStorageDataAndJournalSizeMax); position += 8; context.Memory.WriteInt16(position, nacp.CacheStorageIndex); position += 2; byte[] reserved03 = new byte[0x6]; context.Memory.WriteBytes(position, reserved03); position += reserved03.Length; for (int i = 0; i < 16; i++) { ulong value = 0; if (nacp.PlayLogQueryableApplicationId.Count > i) { value = nacp.PlayLogQueryableApplicationId[i]; } context.Memory.WriteUInt64(position, value); position += 8; } context.Memory.WriteByte(position++, nacp.PlayLogQueryCapability); context.Memory.WriteByte(position++, nacp.RepairFlag); context.Memory.WriteByte(position++, nacp.ProgramIndex); return(0); }
public static void LoadApplications(List <string> appDirs, Keyset keySet, TitleLanguage desiredTitleLanguage, FileSystemClient fsClient = null, VirtualFileSystem vfs = null) { int numApplicationsFound = 0; int numApplicationsLoaded = 0; _keySet = keySet; _desiredTitleLanguage = desiredTitleLanguage; // Builds the applications list with paths to found applications List <string> applications = new List <string>(); foreach (string appDir in appDirs) { if (Directory.Exists(appDir) == false) { Logger.PrintWarning(LogClass.Application, $"The \"game_dirs\" section in \"Config.json\" contains an invalid directory: \"{appDir}\""); continue; } foreach (string app in Directory.GetFiles(appDir, "*.*", SearchOption.AllDirectories)) { if ((Path.GetExtension(app) == ".xci") || (Path.GetExtension(app) == ".nro") || (Path.GetExtension(app) == ".nso") || (Path.GetFileName(app) == "hbl.nsp")) { applications.Add(app); numApplicationsFound++; } else if ((Path.GetExtension(app) == ".nsp") || (Path.GetExtension(app) == ".pfs0")) { try { bool hasMainNca = false; PartitionFileSystem nsp = new PartitionFileSystem(new FileStream(app, FileMode.Open, FileAccess.Read).AsStorage()); foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca")) { nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath, OpenMode.Read).ThrowIfFailure(); Nca nca = new Nca(_keySet, ncaFile.AsStorage()); int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); if (nca.Header.ContentType == NcaContentType.Program && !nca.Header.GetFsHeader(dataIndex).IsPatchSection()) { hasMainNca = true; } } if (!hasMainNca) { continue; } } catch (InvalidDataException) { Logger.PrintWarning(LogClass.Application, $"{app}: The header key is incorrect or missing and therefore the NCA header content type check has failed."); } applications.Add(app); numApplicationsFound++; } else if (Path.GetExtension(app) == ".nca") { try { Nca nca = new Nca(_keySet, new FileStream(app, FileMode.Open, FileAccess.Read).AsStorage()); int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); if (nca.Header.ContentType != NcaContentType.Program || nca.Header.GetFsHeader(dataIndex).IsPatchSection()) { continue; } } catch (InvalidDataException) { Logger.PrintWarning(LogClass.Application, $"{app}: The header key is incorrect or missing and therefore the NCA header content type check has failed."); } applications.Add(app); numApplicationsFound++; } } } // Loops through applications list, creating a struct and then firing an event containing the struct for each application foreach (string applicationPath in applications) { double fileSize = new FileInfo(applicationPath).Length * 0.000000000931; string titleName = "Unknown"; string titleId = "0000000000000000"; string developer = "Unknown"; string version = "0"; string saveDataPath = null; byte[] applicationIcon = null; using (FileStream file = new FileStream(applicationPath, FileMode.Open, FileAccess.Read)) { if ((Path.GetExtension(applicationPath) == ".nsp") || (Path.GetExtension(applicationPath) == ".pfs0") || (Path.GetExtension(applicationPath) == ".xci")) { try { PartitionFileSystem pfs; if (Path.GetExtension(applicationPath) == ".xci") { Xci xci = new Xci(_keySet, file.AsStorage()); pfs = xci.OpenPartition(XciPartitionType.Secure); } else { pfs = new PartitionFileSystem(file.AsStorage()); } // Store the ControlFS in variable called controlFs IFileSystem controlFs = GetControlFs(pfs); // If this is null then this is probably not a normal NSP, it's probably an ExeFS as an NSP if (controlFs == null) { applicationIcon = _nspIcon; Result result = pfs.OpenFile(out IFile npdmFile, "/main.npdm", OpenMode.Read); if (result != ResultFs.PathNotFound) { Npdm npdm = new Npdm(npdmFile.AsStream()); titleName = npdm.TitleName; titleId = npdm.Aci0.TitleId.ToString("x16"); } } else { // Creates NACP class from the NACP file controlFs.OpenFile(out IFile controlNacpFile, "/control.nacp", OpenMode.Read).ThrowIfFailure(); Nacp controlData = new Nacp(controlNacpFile.AsStream()); // Get the title name, title ID, developer name and version number from the NACP version = controlData.DisplayVersion; titleName = controlData.Descriptions[(int)_desiredTitleLanguage].Title; if (string.IsNullOrWhiteSpace(titleName)) { titleName = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title; } titleId = controlData.PresenceGroupId.ToString("x16"); if (string.IsNullOrWhiteSpace(titleId)) { titleId = controlData.SaveDataOwnerId.ToString("x16"); } if (string.IsNullOrWhiteSpace(titleId)) { titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16"); } developer = controlData.Descriptions[(int)_desiredTitleLanguage].Developer; if (string.IsNullOrWhiteSpace(developer)) { developer = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Developer)).Developer; } // Read the icon from the ControlFS and store it as a byte array try { controlFs.OpenFile(out IFile icon, $"/icon_{_desiredTitleLanguage}.dat", OpenMode.Read).ThrowIfFailure(); using (MemoryStream stream = new MemoryStream()) { icon.AsStream().CopyTo(stream); applicationIcon = stream.ToArray(); } } catch (HorizonResultException) { foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*")) { if (entry.Name == "control.nacp") { continue; } controlFs.OpenFile(out IFile icon, entry.FullPath, OpenMode.Read).ThrowIfFailure(); using (MemoryStream stream = new MemoryStream()) { icon.AsStream().CopyTo(stream); applicationIcon = stream.ToArray(); } if (applicationIcon != null) { break; } } if (applicationIcon == null) { applicationIcon = Path.GetExtension(applicationPath) == ".xci" ? _xciIcon : _nspIcon; } } } } catch (MissingKeyException exception) { applicationIcon = Path.GetExtension(applicationPath) == ".xci" ? _xciIcon : _nspIcon; Logger.PrintWarning(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}"); } catch (InvalidDataException) { applicationIcon = Path.GetExtension(applicationPath) == ".xci" ? _xciIcon : _nspIcon; Logger.PrintWarning(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {applicationPath}"); } } else if (Path.GetExtension(applicationPath) == ".nro") { BinaryReader reader = new BinaryReader(file); byte[] Read(long position, int size) { file.Seek(position, SeekOrigin.Begin); return(reader.ReadBytes(size)); } file.Seek(24, SeekOrigin.Begin); int assetOffset = reader.ReadInt32(); if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET") { byte[] iconSectionInfo = Read(assetOffset + 8, 0x10); long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0); long iconSize = BitConverter.ToInt64(iconSectionInfo, 8); ulong nacpOffset = reader.ReadUInt64(); ulong nacpSize = reader.ReadUInt64(); // Reads and stores game icon as byte array applicationIcon = Read(assetOffset + iconOffset, (int)iconSize); // Creates memory stream out of byte array which is the NACP using (MemoryStream stream = new MemoryStream(Read(assetOffset + (int)nacpOffset, (int)nacpSize))) { // Creates NACP class from the memory stream Nacp controlData = new Nacp(stream); // Get the title name, title ID, developer name and version number from the NACP version = controlData.DisplayVersion; titleName = controlData.Descriptions[(int)_desiredTitleLanguage].Title; if (string.IsNullOrWhiteSpace(titleName)) { titleName = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title; } titleId = controlData.PresenceGroupId.ToString("x16"); if (string.IsNullOrWhiteSpace(titleId)) { titleId = controlData.SaveDataOwnerId.ToString("x16"); } if (string.IsNullOrWhiteSpace(titleId)) { titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16"); } developer = controlData.Descriptions[(int)_desiredTitleLanguage].Developer; if (string.IsNullOrWhiteSpace(developer)) { developer = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Developer)).Developer; } } } else { applicationIcon = _nroIcon; } } // If its an NCA or NSO we just set defaults else if ((Path.GetExtension(applicationPath) == ".nca") || (Path.GetExtension(applicationPath) == ".nso")) { applicationIcon = Path.GetExtension(applicationPath) == ".nca" ? _ncaIcon : _nsoIcon; titleName = Path.GetFileNameWithoutExtension(applicationPath); } } ApplicationMetadata appMetadata = LoadAndSaveMetaData(titleId); if (ulong.TryParse(titleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdNum)) { SaveDataFilter filter = new SaveDataFilter(); filter.SetUserId(new UserId(1, 0)); filter.SetTitleId(new TitleId(titleIdNum)); Result result = fsClient.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, ref filter); if (result.IsSuccess()) { saveDataPath = Path.Combine(vfs.GetNandPath(), $"user/save/{saveDataInfo.SaveDataId:x16}"); } } ApplicationData data = new ApplicationData() { Favorite = appMetadata.Favorite, Icon = applicationIcon, TitleName = titleName, TitleId = titleId, Developer = developer, Version = version, TimePlayed = ConvertSecondsToReadableString(appMetadata.TimePlayed), LastPlayed = appMetadata.LastPlayed, FileExtension = Path.GetExtension(applicationPath).ToUpper().Remove(0, 1), FileSize = (fileSize < 1) ? (fileSize * 1024).ToString("0.##") + "MB" : fileSize.ToString("0.##") + "GB", Path = applicationPath, SaveDataPath = saveDataPath }; numApplicationsLoaded++; OnApplicationAdded(new ApplicationAddedEventArgs() { AppData = data, NumAppsFound = numApplicationsFound, NumAppsLoaded = numApplicationsLoaded }); } }