Exemplo n.º 1
0
        public void LoadCart(string exeFsDir, string romFsFile = null)
        {
            if (romFsFile != null)
            {
                Device.FileSystem.LoadRomFs(romFsFile);
            }

            string npdmFileName = Path.Combine(exeFsDir, "main.npdm");

            Npdm metaData = null;

            if (File.Exists(npdmFileName))
            {
                Logger.PrintInfo(LogClass.Loader, $"Loading main.npdm...");

                using (FileStream input = new FileStream(npdmFileName, FileMode.Open))
                {
                    metaData = new Npdm(input);
                }
            }
            else
            {
                Logger.PrintWarning(LogClass.Loader, $"NPDM file not found, using default values!");

                metaData = GetDefaultNpdm();
            }

            List <IExecutable> staticObjects = new List <IExecutable>();

            void LoadNso(string searchPattern)
            {
                foreach (string file in Directory.GetFiles(exeFsDir, searchPattern))
                {
                    if (Path.GetExtension(file) != string.Empty)
                    {
                        continue;
                    }

                    Logger.PrintInfo(LogClass.Loader, $"Loading {Path.GetFileNameWithoutExtension(file)}...");

                    using (FileStream input = new FileStream(file, FileMode.Open))
                    {
                        NxStaticObject staticObject = new NxStaticObject(input);

                        staticObjects.Add(staticObject);
                    }
                }
            }

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

            LoadNso("rtld");
            LoadNso("main");
            LoadNso("subsdk*");
            LoadNso("sdk");

            ContentManager.LoadEntries();

            ProgramLoader.LoadStaticObjects(this, metaData, staticObjects.ToArray());
        }
Exemplo n.º 2
0
        public Process(Switch Device, KProcessScheduler Scheduler, int ProcessId, Npdm MetaData)
        {
            this.Device    = Device;
            this.Scheduler = Scheduler;
            this.MetaData  = MetaData;
            this.ProcessId = ProcessId;

            Memory = new AMemory(Device.Memory.RamPointer);

            MemoryManager = new KMemoryManager(this);

            TlsPages = new List <KTlsPageManager>();

            ThreadArbiterList = new List <KThread>();

            ThreadSyncLock = new object();

            HandleTable = new KProcessHandleTable();

            AppletState = new AppletStateMgr();

            SvcHandler = new SvcHandler(Device, this);

            Threads = new ConcurrentDictionary <long, KThread>();

            Executables = new List <Executable>();

            ImageBase = MemoryManager.CodeRegionStart;
        }
Exemplo n.º 3
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 });
        }
Exemplo n.º 4
0
        public void LoadProgram(string filePath)
        {
            Npdm metaData = GetDefaultNpdm();

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

            using (FileStream input = new FileStream(filePath, FileMode.Open))
            {
                IExecutable staticObject = isNro
                    ? (IExecutable) new NxRelocatableObject(input)
                    : new NxStaticObject(input);

                ProgramLoader.LoadStaticObjects(this, metaData, new IExecutable[] { staticObject });
            }
        }
Exemplo n.º 5
0
        private void LoadExeFs(IFileSystem codeFs, out Npdm metaData)
        {
            Result result = codeFs.OpenFile(out IFile npdmFile, "/main.npdm", OpenMode.Read);

            if (result == ResultFs.PathNotFound)
            {
                Logger.PrintWarning(LogClass.Loader, "NPDM file not found, using default values!");

                metaData = GetDefaultNpdm();
            }
            else
            {
                metaData = new Npdm(npdmFile.AsStream());
            }

            List <IExecutable> staticObjects = new List <IExecutable>();

            void LoadNso(string filename)
            {
                foreach (DirectoryEntryEx file in codeFs.EnumerateEntries("/", $"{filename}*"))
                {
                    if (Path.GetExtension(file.Name) != string.Empty)
                    {
                        continue;
                    }

                    Logger.PrintInfo(LogClass.Loader, $"Loading {file.Name}...");

                    codeFs.OpenFile(out IFile nsoFile, file.FullPath, OpenMode.Read).ThrowIfFailure();

                    NxStaticObject staticObject = new NxStaticObject(nsoFile.AsStream());

                    staticObjects.Add(staticObject);
                }
            }

            TitleId = metaData.Aci0.TitleId;

            LoadNso("rtld");
            LoadNso("main");
            LoadNso("subsdk");
            LoadNso("sdk");

            ContentManager.LoadEntries(Device);

            ProgramLoader.LoadStaticObjects(this, metaData, staticObjects.ToArray());
        }
Exemplo n.º 6
0
        private void LoadExeFs(IFileSystem codeFs, out Npdm metaData)
        {
            if (codeFs.FileExists("/main.npdm"))
            {
                Logger.PrintInfo(LogClass.Loader, "Loading main.npdm...");

                metaData = new Npdm(codeFs.OpenFile("/main.npdm", OpenMode.Read).AsStream());
            }
            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 (DirectoryEntry file in codeFs.EnumerateEntries($"{filename}*"))
                {
                    if (Path.GetExtension(file.Name) != string.Empty)
                    {
                        continue;
                    }

                    Logger.PrintInfo(LogClass.Loader, $"Loading {file.Name}...");

                    NxStaticObject staticObject = new NxStaticObject(codeFs.OpenFile(file.FullPath, OpenMode.Read).AsStream());

                    staticObjects.Add(staticObject);
                }
            }

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

            LoadNso("rtld");
            LoadNso("main");
            LoadNso("subsdk");
            LoadNso("sdk");

            ContentManager.LoadEntries();

            ProgramLoader.LoadStaticObjects(this, metaData, staticObjects.ToArray());
        }
Exemplo n.º 7
0
        public void LoadCart(string exeFsDir, string romFsFile = null)
        {
            if (romFsFile != null)
            {
                _fileSystem.LoadRomFs(romFsFile);
            }

            LocalFileSystem codeFs = new LocalFileSystem(exeFsDir);

            Npdm metaData = ReadNpdm(codeFs);

            if (TitleId != 0)
            {
                EnsureSaveData(new TitleId(TitleId));
            }

            LoadExeFs(codeFs, metaData);
        }
Exemplo n.º 8
0
        public void LoadCart(string exeFsDir, string romFsFile = null)
        {
            if (romFsFile != null)
            {
                _device.Configuration.VirtualFileSystem.LoadRomFs(romFsFile);
            }

            LocalFileSystem codeFs = new LocalFileSystem(exeFsDir);

            Npdm metaData = ReadNpdm(codeFs);

            _device.Configuration.VirtualFileSystem.ModLoader.CollectMods(new[] { TitleId }, _device.Configuration.VirtualFileSystem.ModLoader.GetModsBasePath());

            if (TitleId != 0)
            {
                EnsureSaveData(new ApplicationId(TitleId));
            }

            LoadExeFs(codeFs, metaData);
        }
Exemplo n.º 9
0
        public Process(Switch Device, int ProcessId, Npdm MetaData)
        {
            this.Device    = Device;
            this.MetaData  = MetaData;
            this.ProcessId = ProcessId;

            Memory = new AMemory(Device.Memory.RamPointer);

            Memory.InvalidAccess += CpuInvalidAccessHandler;

            MemoryManager = new KMemoryManager(this);

            TlsPages = new List <KTlsPageManager>();

            int HandleTableSize = 1024;

            if (MetaData != null)
            {
                foreach (KernelAccessControlItem Item in MetaData.ACI0.KernelAccessControl.Items)
                {
                    if (Item.HasHandleTableSize)
                    {
                        HandleTableSize = Item.HandleTableSize;

                        break;
                    }
                }
            }

            HandleTable = new KProcessHandleTable(Device.System, HandleTableSize);

            AppletState = new AppletStateMgr(Device.System);

            SvcHandler = new SvcHandler(Device, this);

            Threads = new ConcurrentDictionary <long, KThread>();

            Executables = new List <Executable>();

            ImageBase = MemoryManager.CodeRegionStart;
        }
Exemplo n.º 10
0
        private Process MakeProcess(Npdm MetaData = null)
        {
            Process Process;

            lock (Processes)
            {
                int ProcessId = 0;

                while (Processes.ContainsKey(ProcessId))
                {
                    ProcessId++;
                }

                Process = new Process(Device, Scheduler, ProcessId, MetaData);

                Processes.TryAdd(ProcessId, Process);
            }

            InitializeProcess(Process);

            return(Process);
        }
Exemplo n.º 11
0
        public void LoadCart(string ExeFsDir, string RomFsFile = null)
        {
            if (RomFsFile != null)
            {
                Device.FileSystem.LoadRomFs(RomFsFile);
            }

            string NpdmFileName = Path.Combine(ExeFsDir, "main.npdm");

            Npdm MetaData = null;

            if (File.Exists(NpdmFileName))
            {
                Logger.PrintInfo(LogClass.Loader, $"Loading main.npdm...");

                using (FileStream Input = new FileStream(NpdmFileName, FileMode.Open))
                {
                    MetaData = new Npdm(Input);
                }
            }
            else
            {
                Logger.PrintWarning(LogClass.Loader, $"NPDM file not found, using default values!");
            }

            Process MainProcess = MakeProcess(MetaData);

            void LoadNso(string FileName)
            {
                foreach (string File in Directory.GetFiles(ExeFsDir, FileName))
                {
                    if (Path.GetExtension(File) != string.Empty)
                    {
                        continue;
                    }

                    Logger.PrintInfo(LogClass.Loader, $"Loading {Path.GetFileNameWithoutExtension(File)}...");

                    using (FileStream Input = new FileStream(File, FileMode.Open))
                    {
                        string Name = Path.GetFileNameWithoutExtension(File);

                        Nso Program = new Nso(Input, Name);

                        MainProcess.LoadProgram(Program);
                    }
                }
            }

            if (!(MainProcess.MetaData?.Is64Bits ?? true))
            {
                throw new NotImplementedException("32-bit titles are unsupported!");
            }

            CurrentTitle = MainProcess.MetaData.ACI0.TitleId.ToString("x16");

            LoadNso("rtld");

            MainProcess.SetEmptyArgs();

            LoadNso("main");
            LoadNso("subsdk*");
            LoadNso("sdk");

            MainProcess.Run();
        }
Exemplo n.º 12
0
        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());
        }
Exemplo n.º 13
0
        public static bool LoadNsos(
            KernelContext context,
            Npdm metaData,
            byte[]        arguments = null,
            params IExecutable[] executables)
        {
            ulong argsStart = 0;
            int   argsSize  = 0;
            ulong codeStart = metaData.Is64Bit ? 0x8000000UL : 0x200000UL;
            int   codeSize  = 0;

            ulong[] nsoBase = new ulong[executables.Length];

            for (int index = 0; index < executables.Length; index++)
            {
                IExecutable staticObject = executables[index];

                int textEnd = staticObject.TextOffset + staticObject.Text.Length;
                int roEnd   = staticObject.RoOffset + staticObject.Ro.Length;
                int dataEnd = staticObject.DataOffset + staticObject.Data.Length + staticObject.BssSize;

                int nsoSize = textEnd;

                if ((uint)nsoSize < (uint)roEnd)
                {
                    nsoSize = roEnd;
                }

                if ((uint)nsoSize < (uint)dataEnd)
                {
                    nsoSize = dataEnd;
                }

                nsoSize = BitUtils.AlignUp(nsoSize, KMemoryManager.PageSize);

                nsoBase[index] = codeStart + (ulong)codeSize;

                codeSize += nsoSize;

                if (arguments != null && argsSize == 0)
                {
                    argsStart = (ulong)codeSize;

                    argsSize = BitUtils.AlignDown(arguments.Length * 2 + ArgsTotalSize - 1, KMemoryManager.PageSize);

                    codeSize += argsSize;
                }
            }

            PtcProfiler.StaticCodeStart = codeStart;
            PtcProfiler.StaticCodeSize  = codeSize;

            int codePagesCount = codeSize / KMemoryManager.PageSize;

            int personalMmHeapPagesCount = metaData.PersonalMmHeapSize / KMemoryManager.PageSize;

            ProcessCreationInfo creationInfo = new ProcessCreationInfo(
                metaData.TitleName,
                metaData.Version,
                metaData.Aci0.TitleId,
                codeStart,
                codePagesCount,
                metaData.MmuFlags,
                0,
                personalMmHeapPagesCount);

            KernelResult result;

            KResourceLimit resourceLimit = new KResourceLimit(context);

            long applicationRgSize = (long)context.MemoryRegions[(int)MemoryRegion.Application].Size;

            result  = resourceLimit.SetLimitValue(LimitableResource.Memory, applicationRgSize);
            result |= resourceLimit.SetLimitValue(LimitableResource.Thread, 608);
            result |= resourceLimit.SetLimitValue(LimitableResource.Event, 700);
            result |= resourceLimit.SetLimitValue(LimitableResource.TransferMemory, 128);
            result |= resourceLimit.SetLimitValue(LimitableResource.Session, 894);

            if (result != KernelResult.Success)
            {
                Logger.PrintError(LogClass.Loader, $"Process initialization failed setting resource limit values.");

                return(false);
            }

            KProcess process = new KProcess(context);

            MemoryRegion memoryRegion = (MemoryRegion)((metaData.Acid.Flags >> 2) & 0xf);

            if (memoryRegion > MemoryRegion.NvServices)
            {
                Logger.PrintError(LogClass.Loader, $"Process initialization failed due to invalid ACID flags.");

                return(false);
            }

            result = process.Initialize(
                creationInfo,
                metaData.Aci0.KernelAccessControl.Capabilities,
                resourceLimit,
                memoryRegion);

            if (result != KernelResult.Success)
            {
                Logger.PrintError(LogClass.Loader, $"Process initialization returned error \"{result}\".");

                return(false);
            }

            for (int index = 0; index < executables.Length; index++)
            {
                Logger.PrintInfo(LogClass.Loader, $"Loading image {index} at 0x{nsoBase[index]:x16}...");

                result = LoadIntoMemory(process, executables[index], nsoBase[index]);

                if (result != KernelResult.Success)
                {
                    Logger.PrintError(LogClass.Loader, $"Process initialization returned error \"{result}\".");

                    return(false);
                }
            }

            process.DefaultCpuCore = metaData.DefaultCpuId;

            result = process.Start(metaData.MainThreadPriority, (ulong)metaData.MainThreadStackSize);

            if (result != KernelResult.Success)
            {
                Logger.PrintError(LogClass.Loader, $"Process start returned error \"{result}\".");

                return(false);
            }

            context.Processes.TryAdd(process.Pid, process);

            return(true);
        }
Exemplo n.º 14
0
        public void LoadNsp(string nspFile)
        {
            FileStream file = new FileStream(nspFile, FileMode.Open, FileAccess.Read);

            Pfs nsp = new Pfs(file.AsStorage(false));

            foreach (PfsFileEntry ticketEntry in nsp.Files.Where(x => x.Name.EndsWith(".tik")))
            {
                Ticket ticket = new Ticket(nsp.OpenFile(ticketEntry).AsStream());

                if (!KeySet.TitleKeys.ContainsKey(ticket.RightsId))
                {
                    KeySet.TitleKeys.Add(ticket.RightsId, ticket.GetTitleKey(KeySet));
                }
            }

            Nca mainNca    = null;
            Nca controlNca = null;

            foreach (PfsFileEntry ncaFile in nsp.Files.Where(x => x.Name.EndsWith(".nca")))
            {
                Nca nca = new Nca(KeySet, nsp.OpenFile(ncaFile), true);

                if (nca.Header.ContentType == ContentType.Program)
                {
                    mainNca = nca;
                }
                else if (nca.Header.ContentType == ContentType.Control)
                {
                    controlNca = nca;
                }
            }

            if (mainNca != null)
            {
                LoadNca(mainNca, controlNca);

                return;
            }

            // This is not a normal NSP, it's actually a ExeFS as a NSP
            Npdm metaData = null;

            PfsFileEntry npdmFile = nsp.Files.FirstOrDefault(x => x.Name.Equals("main.npdm"));

            if (npdmFile != null)
            {
                Logger.PrintInfo(LogClass.Loader, $"Loading main.npdm...");

                metaData = new Npdm(nsp.OpenFile(npdmFile).AsStream());
            }
            else
            {
                Logger.PrintWarning(LogClass.Loader, $"NPDM file not found, using default values!");

                metaData = GetDefaultNpdm();
            }

            List <IExecutable> staticObjects = new List <IExecutable>();

            void LoadNso(string searchPattern)
            {
                PfsFileEntry entry = nsp.Files.FirstOrDefault(x => x.Name.Equals(searchPattern));

                if (entry != null)
                {
                    Logger.PrintInfo(LogClass.Loader, $"Loading {entry.Name}...");

                    NxStaticObject staticObject = new NxStaticObject(nsp.OpenFile(entry).AsStream());

                    staticObjects.Add(staticObject);
                }
            }

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

            LoadNso("rtld");
            LoadNso("main");
            LoadNso("subsdk*");
            LoadNso("sdk");

            ContentManager.LoadEntries();

            if (staticObjects.Count == 0)
            {
                Logger.PrintError(LogClass.Loader, "Could not find an Application NCA in the provided NSP file");
            }
            else
            {
                ProgramLoader.LoadStaticObjects(this, metaData, staticObjects.ToArray());
            }
        }
Exemplo n.º 15
0
        public static bool LoadStaticObjects(
            Horizon system,
            Npdm metaData,
            IExecutable[] staticObjects,
            byte[]        arguments = null)
        {
            ulong argsStart = 0;
            int   argsSize  = 0;
            ulong codeStart = 0x8000000;
            int   codeSize  = 0;

            ulong[] nsoBase = new ulong[staticObjects.Length];

            for (int index = 0; index < staticObjects.Length; index++)
            {
                IExecutable staticObject = staticObjects[index];

                int textEnd = staticObject.TextOffset + staticObject.Text.Length;
                int roEnd   = staticObject.RoOffset + staticObject.Ro.Length;
                int dataEnd = staticObject.DataOffset + staticObject.Data.Length + staticObject.BssSize;

                int nsoSize = textEnd;

                if ((uint)nsoSize < (uint)roEnd)
                {
                    nsoSize = roEnd;
                }

                if ((uint)nsoSize < (uint)dataEnd)
                {
                    nsoSize = dataEnd;
                }

                nsoSize = BitUtils.AlignUp(nsoSize, KMemoryManager.PageSize);

                nsoBase[index] = codeStart + (ulong)codeSize;

                codeSize += nsoSize;

                if (arguments != null && argsSize == 0)
                {
                    argsStart = (ulong)codeSize;

                    argsSize = BitUtils.AlignDown(arguments.Length * 2 + ArgsTotalSize - 1, KMemoryManager.PageSize);

                    codeSize += argsSize;
                }
            }

            int codePagesCount = codeSize / KMemoryManager.PageSize;

            int personalMmHeapPagesCount = metaData.PersonalMmHeapSize / KMemoryManager.PageSize;

            ProcessCreationInfo creationInfo = new ProcessCreationInfo(
                metaData.TitleName,
                metaData.ProcessCategory,
                metaData.Aci0.TitleId,
                codeStart,
                codePagesCount,
                metaData.MmuFlags,
                0,
                personalMmHeapPagesCount);

            KernelResult result;

            KResourceLimit resourceLimit = new KResourceLimit(system);

            long applicationRgSize = (long)system.MemoryRegions[(int)MemoryRegion.Application].Size;

            result  = resourceLimit.SetLimitValue(LimitableResource.Memory, applicationRgSize);
            result |= resourceLimit.SetLimitValue(LimitableResource.Thread, 608);
            result |= resourceLimit.SetLimitValue(LimitableResource.Event, 700);
            result |= resourceLimit.SetLimitValue(LimitableResource.TransferMemory, 128);
            result |= resourceLimit.SetLimitValue(LimitableResource.Session, 894);

            if (result != KernelResult.Success)
            {
                Logger.PrintError(LogClass.Loader, $"Process initialization failed setting resource limit values.");

                return(false);
            }

            KProcess process = new KProcess(system);

            result = process.Initialize(
                creationInfo,
                metaData.Aci0.KernelAccessControl.Capabilities,
                resourceLimit,
                MemoryRegion.Application);

            if (result != KernelResult.Success)
            {
                Logger.PrintError(LogClass.Loader, $"Process initialization returned error \"{result}\".");

                return(false);
            }

            for (int index = 0; index < staticObjects.Length; index++)
            {
                Logger.PrintInfo(LogClass.Loader, $"Loading image {index} at 0x{nsoBase[index]:x16}...");

                result = LoadIntoMemory(process, staticObjects[index], nsoBase[index]);

                if (result != KernelResult.Success)
                {
                    Logger.PrintError(LogClass.Loader, $"Process initialization returned error \"{result}\".");

                    return(false);
                }
            }

            result = process.Start(metaData.MainThreadPriority, (ulong)metaData.MainThreadStackSize);

            if (result != KernelResult.Success)
            {
                Logger.PrintError(LogClass.Loader, $"Process start returned error \"{result}\".");

                return(false);
            }

            system.Processes.Add(process.Pid, process);

            return(true);
        }
Exemplo n.º 16
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 });
        }
Exemplo n.º 17
0
        public void LoadCart(string ExeFsDir, string RomFsFile = null)
        {
            if (RomFsFile != null)
            {
                Device.FileSystem.LoadRomFs(RomFsFile);
            }

            string NpdmFileName = Path.Combine(ExeFsDir, "main.npdm");

            Npdm MetaData = null;

            if (File.Exists(NpdmFileName))
            {
                Logger.PrintInfo(LogClass.Loader, $"Loading main.npdm...");

                using (FileStream Input = new FileStream(NpdmFileName, FileMode.Open))
                {
                    MetaData = new Npdm(Input);
                }
            }
            else
            {
                Logger.PrintWarning(LogClass.Loader, $"NPDM file not found, using default values!");

                MetaData = GetDefaultNpdm();
            }

            List <IExecutable> StaticObjects = new List <IExecutable>();

            void LoadNso(string SearchPattern)
            {
                foreach (string File in Directory.GetFiles(ExeFsDir, SearchPattern))
                {
                    if (Path.GetExtension(File) != string.Empty)
                    {
                        continue;
                    }

                    Logger.PrintInfo(LogClass.Loader, $"Loading {Path.GetFileNameWithoutExtension(File)}...");

                    using (FileStream Input = new FileStream(File, FileMode.Open))
                    {
                        NxStaticObject StaticObject = new NxStaticObject(Input);

                        StaticObjects.Add(StaticObject);
                    }
                }
            }

            if (!MetaData.Is64Bits)
            {
                throw new NotImplementedException("32-bit titles are unsupported!");
            }

            CurrentTitle = MetaData.ACI0.TitleId.ToString("x16");

            LoadNso("rtld");
            LoadNso("main");
            LoadNso("subsdk*");
            LoadNso("sdk");

            ContentManager.LoadEntries();

            ProgramLoader.LoadStaticObjects(this, MetaData, StaticObjects.ToArray());
        }
Exemplo n.º 18
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
                });
            }
        }
Exemplo n.º 19
0
        public static bool LoadNsos(KernelContext context, out ProcessTamperInfo tamperInfo, Npdm metaData, byte[] arguments = null, params IExecutable[] executables)
        {
            ulong argsStart = 0;
            uint  argsSize  = 0;
            ulong codeStart = metaData.Is64Bit ? 0x8000000UL : 0x200000UL;
            uint  codeSize  = 0;

            var buildIds = executables.Select(e => (e switch
            {
                NsoExecutable nso => BitConverter.ToString(nso.BuildId.Bytes.ToArray()),
                NroExecutable nro => BitConverter.ToString(nro.Header.BuildId),
                _ => ""
            }).Replace("-", "").ToUpper());
Exemplo n.º 20
0
        public void LoadApplications(List <string> appDirs, Language desiredTitleLanguage)
        {
            int numApplicationsFound  = 0;
            int numApplicationsLoaded = 0;

            _desiredTitleLanguage = desiredTitleLanguage;

            _cancellationToken = new CancellationTokenSource();

            // Builds the applications list with paths to found applications
            List <string> applications = new List <string>();

            try
            {
                foreach (string appDir in appDirs)
                {
                    if (_cancellationToken.Token.IsCancellationRequested)
                    {
                        return;
                    }

                    if (!Directory.Exists(appDir))
                    {
                        Logger.Warning?.Print(LogClass.Application, $"The \"game_dirs\" section in \"Config.json\" contains an invalid directory: \"{appDir}\"");

                        continue;
                    }

                    foreach (string app in GetFilesInDirectory(appDir))
                    {
                        if (_cancellationToken.Token.IsCancellationRequested)
                        {
                            return;
                        }

                        string extension = Path.GetExtension(app).ToLower();

                        if ((extension == ".nsp") ||
                            (extension == ".pfs0") ||
                            (extension == ".xci") ||
                            (extension == ".nca") ||
                            (extension == ".nro") ||
                            (extension == ".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)
                {
                    if (_cancellationToken.Token.IsCancellationRequested)
                    {
                        return;
                    }

                    double fileSize        = new FileInfo(applicationPath).Length * 0.000000000931;
                    string titleName       = "Unknown";
                    string titleId         = "0000000000000000";
                    string developer       = "Unknown";
                    string version         = "0";
                    byte[] applicationIcon = null;

                    BlitStruct <ApplicationControlProperty> controlHolder = new BlitStruct <ApplicationControlProperty>(1);

                    try
                    {
                        string extension = Path.GetExtension(applicationPath).ToLower();

                        using (FileStream file = new FileStream(applicationPath, FileMode.Open, FileAccess.Read))
                        {
                            if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci")
                            {
                                try
                                {
                                    PartitionFileSystem pfs;

                                    bool isExeFs = false;

                                    if (extension == ".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")
                                            {
                                                using var ncaFile = new UniqueRef <IFile>();

                                                pfs.OpenFile(ref ncaFile.Ref(), fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();

                                                Nca nca       = new Nca(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage());
                                                int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);

                                                // Some main NCAs don't have a data partition, so check if the partition exists before opening it
                                                if (nca.Header.ContentType == NcaContentType.Program && !(nca.SectionExists(NcaSectionType.Data) && 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;

                                        using var npdmFile = new UniqueRef <IFile>();

                                        Result result = pfs.OpenFile(ref npdmFile.Ref(), "/main.npdm".ToU8Span(), OpenMode.Read);

                                        if (ResultFs.PathNotFound.Includes(result))
                                        {
                                            Npdm npdm = new Npdm(npdmFile.Get.AsStream());

                                            titleName = npdm.TitleName;
                                            titleId   = npdm.Aci0.TitleId.ToString("x16");
                                        }
                                    }
                                    else
                                    {
                                        GetControlFsAndTitleId(pfs, out IFileSystem controlFs, out titleId);

                                        // Check if there is an update available.
                                        if (IsUpdateApplied(titleId, out IFileSystem updatedControlFs))
                                        {
                                            // Replace the original ControlFs by the updated one.
                                            controlFs = updatedControlFs;
                                        }

                                        ReadControlData(controlFs, controlHolder.ByteSpan);

                                        GetGameInformation(ref controlHolder.Value, out titleName, out _, out developer, out version);

                                        // Read the icon from the ControlFS and store it as a byte array
                                        try
                                        {
                                            using var icon = new UniqueRef <IFile>();

                                            controlFs.OpenFile(ref icon.Ref(), $"/icon_{_desiredTitleLanguage}.dat".ToU8Span(), OpenMode.Read).ThrowIfFailure();

                                            using (MemoryStream stream = new MemoryStream())
                                            {
                                                icon.Get.AsStream().CopyTo(stream);
                                                applicationIcon = stream.ToArray();
                                            }
                                        }
                                        catch (HorizonResultException)
                                        {
                                            foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*"))
                                            {
                                                if (entry.Name == "control.nacp")
                                                {
                                                    continue;
                                                }

                                                using var icon = new UniqueRef <IFile>();

                                                controlFs.OpenFile(ref icon.Ref(), entry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();

                                                using (MemoryStream stream = new MemoryStream())
                                                {
                                                    icon.Get.AsStream().CopyTo(stream);
                                                    applicationIcon = stream.ToArray();
                                                }

                                                if (applicationIcon != null)
                                                {
                                                    break;
                                                }
                                            }

                                            if (applicationIcon == null)
                                            {
                                                applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon;
                                            }
                                        }
                                    }
                                }
                                catch (MissingKeyException exception)
                                {
                                    applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon;

                                    Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}");
                                }
                                catch (InvalidDataException)
                                {
                                    applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon;

                                    Logger.Warning?.Print(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.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. File: '{applicationPath}' Error: {exception}");

                                    numApplicationsFound--;

                                    continue;
                                }
                            }
                            else if (extension == ".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);

                                        // Read the NACP data
                                        Read(assetOffset + (int)nacpOffset, (int)nacpSize).AsSpan().CopyTo(controlHolder.ByteSpan);

                                        GetGameInformation(ref controlHolder.Value, out titleName, out titleId, out developer, out version);
                                    }
                                    else
                                    {
                                        applicationIcon = _nroIcon;
                                        titleName       = Path.GetFileNameWithoutExtension(applicationPath);
                                    }
                                }
                                catch
                                {
                                    Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");

                                    numApplicationsFound--;

                                    continue;
                                }
                            }
                            else if (extension == ".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.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection()))
                                    {
                                        numApplicationsFound--;

                                        continue;
                                    }
                                }
                                catch (InvalidDataException)
                                {
                                    Logger.Warning?.Print(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.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");

                                    numApplicationsFound--;

                                    continue;
                                }

                                applicationIcon = _ncaIcon;
                                titleName       = Path.GetFileNameWithoutExtension(applicationPath);
                            }
                            // If its an NSO we just set defaults
                            else if (extension == ".nso")
                            {
                                applicationIcon = _nsoIcon;
                                titleName       = Path.GetFileNameWithoutExtension(applicationPath);
                            }
                        }
                    }
                    catch (IOException exception)
                    {
                        Logger.Warning?.Print(LogClass.Application, exception.Message);

                        numApplicationsFound--;

                        continue;
                    }

                    ApplicationMetadata appMetadata = LoadAndSaveMetaData(titleId);

                    if (appMetadata.LastPlayed != "Never" && !DateTime.TryParse(appMetadata.LastPlayed, out _))
                    {
                        Logger.Warning?.Print(LogClass.Application, $"Last played datetime \"{appMetadata.LastPlayed}\" is invalid for current system culture, skipping (did current culture change?)");

                        appMetadata.LastPlayed = "Never";
                    }

                    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,
                        ControlHolder = controlHolder
                    };

                    numApplicationsLoaded++;

                    OnApplicationAdded(new ApplicationAddedEventArgs()
                    {
                        AppData = data
                    });

                    OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs()
                    {
                        NumAppsFound  = numApplicationsFound,
                        NumAppsLoaded = numApplicationsLoaded
                    });
                }

                OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs()
                {
                    NumAppsFound  = numApplicationsFound,
                    NumAppsLoaded = numApplicationsLoaded
                });
            }
            finally
            {
                _cancellationToken.Dispose();
                _cancellationToken = null;
            }
        }
Exemplo n.º 21
0
        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 GetFilesInDirectory(appDir))
                {
                    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;
                BlitStruct <ApplicationControlProperty> controlHolder = new BlitStruct <ApplicationControlProperty>(1);

                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.ToU8Span(), 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".ToU8Span(), 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);

                                    ReadControlData(controlFs, controlHolder.ByteSpan);

                                    // Creates NACP class from the NACP file
                                    controlFs.OpenFile(out IFile controlNacpFile, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();

                                    // Get the title name, title ID, developer name and version number from the NACP
                                    version = IsUpdateApplied(titleId, out string updateVersion) ? updateVersion : controlHolder.Value.DisplayVersion.ToString();

                                    GetNameIdDeveloper(ref controlHolder.Value, 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".ToU8Span(), 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.ToU8Span(), 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);

                                    // Read the NACP data
                                    Read(assetOffset + (int)nacpOffset, (int)nacpSize).AsSpan().CopyTo(controlHolder.ByteSpan);

                                    // Get the title name, title ID, developer name and version number from the NACP
                                    version = controlHolder.Value.DisplayVersion.ToString();

                                    GetNameIdDeveloper(ref controlHolder.Value, 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.ToString("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,
                    ControlHolder = controlHolder
                };

                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.");
                });
            }
        }
Exemplo n.º 22
0
        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();
        }
Exemplo n.º 23
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}\"");
                        }
                    }
                }
            }
Exemplo n.º 24
0
        public static bool LoadStaticObjects(
            Horizon System,
            Npdm MetaData,
            IExecutable[] StaticObjects,
            byte[]        Arguments = null)
        {
            ulong ArgsStart = 0;
            int   ArgsSize  = 0;
            ulong CodeStart = 0x8000000;
            int   CodeSize  = 0;

            ulong[] NsoBase = new ulong[StaticObjects.Length];

            for (int Index = 0; Index < StaticObjects.Length; Index++)
            {
                IExecutable StaticObject = StaticObjects[Index];

                int TextEnd = StaticObject.TextOffset + StaticObject.Text.Length;
                int ROEnd   = StaticObject.ROOffset + StaticObject.RO.Length;
                int DataEnd = StaticObject.DataOffset + StaticObject.Data.Length + StaticObject.BssSize;

                int NsoSize = TextEnd;

                if ((uint)NsoSize < (uint)ROEnd)
                {
                    NsoSize = ROEnd;
                }

                if ((uint)NsoSize < (uint)DataEnd)
                {
                    NsoSize = DataEnd;
                }

                NsoSize = BitUtils.AlignUp(NsoSize, KMemoryManager.PageSize);

                NsoBase[Index] = CodeStart + (ulong)CodeSize;

                CodeSize += NsoSize;

                if (Arguments != null && ArgsSize == 0)
                {
                    ArgsStart = (ulong)CodeSize;

                    ArgsSize = BitUtils.AlignDown(Arguments.Length * 2 + ArgsTotalSize - 1, KMemoryManager.PageSize);

                    CodeSize += ArgsSize;
                }
            }

            int CodePagesCount = CodeSize / KMemoryManager.PageSize;

            int PersonalMmHeapPagesCount = MetaData.PersonalMmHeapSize / KMemoryManager.PageSize;

            ProcessCreationInfo CreationInfo = new ProcessCreationInfo(
                MetaData.TitleName,
                MetaData.ProcessCategory,
                MetaData.ACI0.TitleId,
                CodeStart,
                CodePagesCount,
                MetaData.MmuFlags,
                0,
                PersonalMmHeapPagesCount);

            KernelResult Result;

            KResourceLimit ResourceLimit = new KResourceLimit(System);

            long ApplicationRgSize = (long)System.MemoryRegions[(int)MemoryRegion.Application].Size;

            Result  = ResourceLimit.SetLimitValue(LimitableResource.Memory, ApplicationRgSize);
            Result |= ResourceLimit.SetLimitValue(LimitableResource.Thread, 608);
            Result |= ResourceLimit.SetLimitValue(LimitableResource.Event, 700);
            Result |= ResourceLimit.SetLimitValue(LimitableResource.TransferMemory, 128);
            Result |= ResourceLimit.SetLimitValue(LimitableResource.Session, 894);

            if (Result != KernelResult.Success)
            {
                Logger.PrintError(LogClass.Loader, $"Process initialization failed setting resource limit values.");

                return(false);
            }

            KProcess Process = new KProcess(System);

            Result = Process.Initialize(
                CreationInfo,
                MetaData.ACI0.KernelAccessControl.Capabilities,
                ResourceLimit,
                MemoryRegion.Application);

            if (Result != KernelResult.Success)
            {
                Logger.PrintError(LogClass.Loader, $"Process initialization returned error \"{Result}\".");

                return(false);
            }

            for (int Index = 0; Index < StaticObjects.Length; Index++)
            {
                Logger.PrintInfo(LogClass.Loader, $"Loading image {Index} at 0x{NsoBase[Index]:x16}...");

                Result = LoadIntoMemory(Process, StaticObjects[Index], NsoBase[Index]);

                if (Result != KernelResult.Success)
                {
                    Logger.PrintError(LogClass.Loader, $"Process initialization returned error \"{Result}\".");

                    return(false);
                }
            }

            Result = Process.Start(MetaData.MainThreadPriority, (ulong)MetaData.MainThreadStackSize);

            if (Result != KernelResult.Success)
            {
                Logger.PrintError(LogClass.Loader, $"Process start returned error \"{Result}\".");

                return(false);
            }

            System.Processes.Add(Process.Pid, Process);

            return(true);
        }