コード例 #1
0
        public static void EnsureApplicationCacheStorage_SdCardNotAvailable_CreatesCacheStorageOnBis()
        {
            FileSystemClient fs = FileSystemServerFactory.CreateClient(false);

            var applicationId = new Ncm.ApplicationId(11);

            var nacp = new ApplicationControlProperty
            {
                CacheStorageSize        = 0x1000,
                CacheStorageJournalSize = 0x1000
            };

            Assert.Success(fs.EnsureApplicationCacheStorage(out _, out CacheStorageTargetMedia target, applicationId,
                                                            ref nacp));

            Assert.Equal(CacheStorageTargetMedia.Nand, target);

            fs.OpenSaveDataIterator(out SaveDataIterator iterator, SaveDataSpaceId.User);

            var info = new SaveDataInfo[2];

            Assert.Success(iterator.ReadSaveDataInfo(out long entriesRead, info));

            Assert.Equal(1, entriesRead);
            Assert.Equal(applicationId, info[0].ProgramId);
            Assert.Equal(SaveDataType.Cache, info[0].Type);
        }
コード例 #2
0
        public static void EnsureApplicationSaveData_CreatesTemporaryStorage()
        {
            FileSystemClient fs = FileSystemServerFactory.CreateClient(true);

            var applicationId = new Ncm.ApplicationId(11);
            var userId        = new Uid(2, 3);

            var nacp = new ApplicationControlProperty
            {
                TemporaryStorageSize = 0x1000
            };

            Assert.Success(EnsureApplicationSaveData(fs, out _, applicationId, ref nacp, ref userId));

            fs.OpenSaveDataIterator(out SaveDataIterator iterator, SaveDataSpaceId.Temporary);

            var info = new SaveDataInfo[2];

            Assert.Success(iterator.ReadSaveDataInfo(out long entriesRead, info));

            Assert.Equal(1, entriesRead);
            Assert.Equal(applicationId, info[0].ProgramId);
            Assert.Equal(UserId.Zero, info[0].UserId);
            Assert.Equal(SaveDataType.Temporary, info[0].Type);
        }
コード例 #3
0
ファイル: NacpItem.cs プロジェクト: Myster-Tee/NxFileViewer
 public NacpItem(ApplicationControlProperty nacp, SectionItem parentItem, DirectoryEntryEx directoryEntry)
     : base(parentItem, directoryEntry)
 {
     Nacp               = nacp;
     ParentItem         = parentItem ?? throw new ArgumentNullException(nameof(parentItem));
     AddOnContentBaseId = Nacp.AddOnContentBaseId.ToStrId();
 }
コード例 #4
0
        private bool IsUpdateApplied(string titleId, out string version)
        {
            string updatePath = "(unknown)";

            try
            {
                (Nca patchNca, Nca controlNca) = ApplicationLoader.GetGameUpdateData(_virtualFileSystem, titleId, 0, out updatePath);

                if (patchNca != null && controlNca != null)
                {
                    ApplicationControlProperty controlData = new ApplicationControlProperty();

                    controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(out IFile nacpFile, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();

                    nacpFile.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();

                    version = controlData.DisplayVersion.ToString();

                    return(true);
                }
            }
            catch (InvalidDataException)
            {
                Logger.Warning?.Print(LogClass.Application,
                                      $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {updatePath}");
            }
            catch (MissingKeyException exception)
            {
                Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}. Errored File: {updatePath}");
            }

            version = "";

            return(false);
        }
コード例 #5
0
        private void GetGameInformation(ref ApplicationControlProperty controlData, out string titleName, out string titleId, out string publisher, out string version)
        {
            _ = Enum.TryParse(_desiredTitleLanguage.ToString(), out TitleLanguage desiredTitleLanguage);

            if (controlData.Title.ItemsRo.Length > (int)desiredTitleLanguage)
            {
                titleName = controlData.Title[(int)desiredTitleLanguage].NameString.ToString();
                publisher = controlData.Title[(int)desiredTitleLanguage].PublisherString.ToString();
            }
            else
            {
                titleName = null;
                publisher = null;
            }

            if (string.IsNullOrWhiteSpace(titleName))
            {
                foreach (ref readonly var controlTitle in controlData.Title.ItemsRo)
                {
                    if (!controlTitle.NameString.IsEmpty())
                    {
                        titleName = controlTitle.NameString.ToString();

                        break;
                    }
                }
            }

            if (string.IsNullOrWhiteSpace(publisher))
            {
                foreach (ref readonly var controlTitle in controlData.Title.ItemsRo)
                {
                    if (!controlTitle.PublisherString.IsEmpty())
                    {
                        publisher = controlTitle.PublisherString.ToString();

                        break;
                    }
                }
            }

            if (controlData.PresenceGroupId != 0)
            {
                titleId = controlData.PresenceGroupId.ToString("x16");
            }
            else if (controlData.SaveDataOwnerId != 0)
            {
                titleId = controlData.SaveDataOwnerId.ToString();
            }
            else if (controlData.AddOnContentBaseId != 0)
            {
                titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16");
            }
            else
            {
                titleId = "0000000000000000";
            }

            version = controlData.DisplayVersionString.ToString();
        }
コード例 #6
0
        public static void EnsureApplicationSaveData_CreatesAccountSaveData()
        {
            FileSystemClient fs = FileSystemServerFactory.CreateClient(true);

            var applicationId = new Ncm.ApplicationId(11);
            var userId        = new Uid(2, 3);

            var nacp = new ApplicationControlProperty
            {
                UserAccountSaveDataSize        = 0x1000,
                UserAccountSaveDataJournalSize = 0x1000
            };

            Assert.Success(EnsureApplicationSaveData(fs, out _, applicationId, ref nacp, ref userId));

            fs.OpenSaveDataIterator(out SaveDataIterator iterator, SaveDataSpaceId.User);

            var info = new SaveDataInfo[2];

            Assert.Success(iterator.ReadSaveDataInfo(out long entriesRead, info));

            Assert.Equal(1, entriesRead);
            Assert.Equal(applicationId, info[0].ProgramId);
            Assert.Equal(ConvertAccountUidToFsUserId(userId), info[0].UserId);
            Assert.Equal(SaveDataType.Account, info[0].Type);
        }
コード例 #7
0
        private void GetNameIdDeveloper(ref ApplicationControlProperty controlData, out string titleName, out string titleId, out string publisher)
        {
            _ = Enum.TryParse(_desiredTitleLanguage.ToString(), out TitleLanguage desiredTitleLanguage);

            if (controlData.Titles.Length > (int)desiredTitleLanguage)
            {
                titleName = controlData.Titles[(int)desiredTitleLanguage].Name.ToString();
                publisher = controlData.Titles[(int)desiredTitleLanguage].Publisher.ToString();
            }
            else
            {
                titleName = null;
                publisher = null;
            }

            if (string.IsNullOrWhiteSpace(titleName))
            {
                foreach (ApplicationControlTitle controlTitle in controlData.Titles)
                {
                    if (!((U8Span)controlTitle.Name).IsEmpty())
                    {
                        titleName = controlTitle.Name.ToString();

                        break;
                    }
                }
            }

            if (string.IsNullOrWhiteSpace(publisher))
            {
                foreach (ApplicationControlTitle controlTitle in controlData.Titles)
                {
                    if (!((U8Span)controlTitle.Publisher).IsEmpty())
                    {
                        publisher = controlTitle.Publisher.ToString();

                        break;
                    }
                }
            }

            if (controlData.PresenceGroupId != 0)
            {
                titleId = controlData.PresenceGroupId.ToString("x16");
            }
            else if (controlData.SaveDataOwnerId.Value != 0)
            {
                titleId = controlData.SaveDataOwnerId.ToString();
            }
            else if (controlData.AddOnContentBaseId != 0)
            {
                titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16");
            }
            else
            {
                titleId = "0000000000000000";
            }
        }
コード例 #8
0
        private void AddUpdate(string path, bool showErrorDialog = true)
        {
            if (File.Exists(path))
            {
                using (FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                    PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage());

                    try
                    {
                        (Nca patchNca, Nca controlNca) = ApplicationLoader.GetGameUpdateDataFromPartition(_virtualFileSystem, nsp, _titleId, 0);

                        if (controlNca != null && patchNca != null)
                        {
                            ApplicationControlProperty controlData = new ApplicationControlProperty();

                            controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(out IFile nacpFile, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
                            nacpFile.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();

                            RadioButton radioButton = new RadioButton($"Version {controlData.DisplayVersion.ToString()} - {path}");
                            radioButton.JoinGroup(_noUpdateRadioButton);

                            _availableUpdatesBox.Add(radioButton);
                            _radioButtonToPathDictionary.Add(radioButton, path);

                            radioButton.Show();
                            radioButton.Active = true;
                        }
                        else
                        {
                            GtkDialog.CreateErrorDialog("The specified file does not contain an update for the selected title!");
                        }
                    }
                    catch (InvalidDataException exception)
                    {
                        Logger.Error?.Print(LogClass.Application, $"{exception.Message}. Errored File: {path}");

                        if (showErrorDialog)
                        {
                            GtkDialog.CreateInfoDialog("Ryujinx - Error", "Add Update Failed!", "The NCA header content type check has failed. This is usually because the header key is incorrect or missing.");
                        }
                    }
                    catch (MissingKeyException exception)
                    {
                        Logger.Error?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}. Errored File: {path}");

                        if (showErrorDialog)
                        {
                            GtkDialog.CreateInfoDialog("Ryujinx - Error", "Add Update Failed!", $"Your key set is missing a key with the name: {exception.Name}");
                        }
                    }
                }
            }
        }
コード例 #9
0
        private bool TryFindSaveData(string titleName, ulong titleId, BlitStruct <ApplicationControlProperty> controlHolder, SaveDataFilter filter, out ulong saveDataId)
        {
            saveDataId = default;

            Result result = _virtualFileSystem.FsClient.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, ref filter);

            if (ResultFs.TargetNotFound.Includes(result))
            {
                // Savedata was not found. Ask the user if they want to create it
                using MessageDialog messageDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Question, ButtonsType.YesNo, null)
                      {
                          Title          = "PangoNX Debugger",
                          Icon           = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"),
                          Text           = $"There is no savedata for {titleName} [{titleId:x16}]",
                          SecondaryText  = "Would you like to create savedata for this game?",
                          WindowPosition = WindowPosition.Center
                      };

                if (messageDialog.Run() != (int)ResponseType.Yes)
                {
                    return(false);
                }

                ref ApplicationControlProperty control = ref controlHolder.Value;

                if (LibHac.Util.IsEmpty(controlHolder.ByteSpan))
                {
                    // If the current application doesn't have a loaded control property, create a dummy one
                    // and set the savedata sizes so a user savedata will be created.
                    control = ref new BlitStruct <ApplicationControlProperty>(1).Value;

                    // The set sizes don't actually matter as long as they're non-zero because we use directory savedata.
                    control.UserAccountSaveDataSize        = 0x4000;
                    control.UserAccountSaveDataJournalSize = 0x4000;

                    Logger.PrintWarning(LogClass.Application,
                                        "No control file was found for this game. Using a dummy one instead. This may cause inaccuracies in some games.");
                }

                Uid user = new Uid(1, 0);

                result = EnsureApplicationSaveData(_virtualFileSystem.FsClient, out _, new TitleId(titleId), ref control, ref user);

                if (result.IsFailure())
                {
                    GtkDialog.CreateErrorDialog($"There was an error creating the specified savedata: {result.ToStringWithName()}");

                    return(false);
                }

                // Try to find the savedata again after creating it
                result = _virtualFileSystem.FsClient.FindSaveDataWithFilter(out saveDataInfo, SaveDataSpaceId.User, ref filter);
            }
コード例 #10
0
ファイル: ProcessSwitchFs.cs プロジェクト: ckurtz22/LibHac
        static string ListApplications(SwitchFs sdfs)
        {
            var sb = new StringBuilder();

            foreach (Application app in sdfs.Applications.Values.OrderBy(x => x.Name))
            {
                if (app.Main != null)
                {
                    sb.AppendLine($"{app.Name} v{app.DisplayVersion} ({app.Main.Id.ToString("X16")})");
                    sb.AppendLine($"Software: {Utilities.GetBytesReadable(app.Main.GetSize())}");
                }
                else
                {
                    sb.AppendLine($"{app.Name} v{app.DisplayVersion}");
                }

                if (app.Patch != null)
                {
                    sb.AppendLine($"Update Data: {Utilities.GetBytesReadable(app.Patch.GetSize())}");
                }

                if (app.AddOnContent.Count > 0)
                {
                    sb.AppendLine($"DLC: {Utilities.GetBytesReadable(app.AddOnContent.Sum(x => x.GetSize()))}");
                }

                ref ApplicationControlProperty nacp = ref app.Nacp.Value;

                long userTotalSaveDataSize   = nacp.UserAccountSaveDataSize + nacp.UserAccountSaveDataJournalSize;
                long deviceTotalSaveDataSize = nacp.DeviceSaveDataSize + nacp.DeviceSaveDataJournalSize;

                if (userTotalSaveDataSize > 0)
                {
                    sb.AppendLine($"User save: {Utilities.GetBytesReadable(userTotalSaveDataSize)}");
                }
                if (deviceTotalSaveDataSize > 0)
                {
                    sb.AppendLine($"System save: {Utilities.GetBytesReadable(deviceTotalSaveDataSize)}");
                }
                if (nacp.BcatDeliveryCacheStorageSize > 0)
                {
                    sb.AppendLine($"BCAT save: {Utilities.GetBytesReadable(nacp.BcatDeliveryCacheStorageSize)}");
                }

                sb.AppendLine();
            }
コード例 #11
0
        public static void GetCacheStorageTargetMedia_ReturnsTargetOfNewCacheStorage(bool isSdCardInserted)
        {
            FileSystemClient fs = FileSystemServerFactory.CreateClient(isSdCardInserted);

            var applicationId = new Ncm.ApplicationId(11);

            var nacp = new ApplicationControlProperty
            {
                CacheStorageSize        = 0x1000,
                CacheStorageJournalSize = 0x1000
            };

            fs.EnsureApplicationCacheStorage(out _, out CacheStorageTargetMedia targetFromCreation, applicationId, ref nacp);

            Assert.Success(fs.GetCacheStorageTargetMedia(out CacheStorageTargetMedia target, applicationId));
            Assert.Equal(targetFromCreation, target);
        }
コード例 #12
0
ファイル: TitleUpdateWindow.cs プロジェクト: mailwl/Ryujinx
        private void AddUpdate(string path)
        {
            if (File.Exists(path))
            {
                using (FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                    PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage());

                    try
                    {
                        (Nca patchNca, Nca controlNca) = ApplicationLoader.GetGameUpdateDataFromPartition(_virtualFileSystem, nsp, _titleId, 0);

                        if (controlNca != null && patchNca != null)
                        {
                            ApplicationControlProperty controlData = new ApplicationControlProperty();

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

                            controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(ref nacpFile.Ref(), "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
                            nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();

                            RadioButton radioButton = new RadioButton($"Version {controlData.DisplayVersion.ToString()} - {path}");
                            radioButton.JoinGroup(_noUpdateRadioButton);

                            _availableUpdatesBox.Add(radioButton);
                            _radioButtonToPathDictionary.Add(radioButton, path);

                            radioButton.Show();
                            radioButton.Active = true;
                        }
                        else
                        {
                            GtkDialog.CreateErrorDialog("The specified file does not contain an update for the selected title!");
                        }
                    }
                    catch (Exception exception)
                    {
                        GtkDialog.CreateErrorDialog($"{exception.Message}. Errored File: {path}");
                    }
                }
            }
        }
コード例 #13
0
ファイル: IFriendService.cs プロジェクト: scese250/Ryujinx
        // nn::friends::AddPlayHistory(nn::account::Uid, u64, pid, buffer<nn::friends::PlayHistoryRegistrationKey, 0x19>, buffer<nn::friends::InAppScreenName, 0x19>, buffer<nn::friends::InAppScreenName, 0x19>)
        public ResultCode AddPlayHistory(ServiceCtx context)
        {
            UserId userId = context.RequestData.ReadStruct <UserId>();

            // Pid placeholder
            context.RequestData.ReadInt64();
            long pid = context.Request.HandleDesc.PId;

            ulong playHistoryRegistrationKeyPosition = context.Request.PtrBuff[0].Position;
            ulong PlayHistoryRegistrationKeySize     = context.Request.PtrBuff[0].Size;

            ulong inAppScreenName1Position = context.Request.PtrBuff[1].Position;
            ulong inAppScreenName1Size     = context.Request.PtrBuff[1].Size;

            ulong inAppScreenName2Position = context.Request.PtrBuff[2].Position;
            ulong inAppScreenName2Size     = context.Request.PtrBuff[2].Size;

            if (userId.IsNull || inAppScreenName1Size > 0x48 || inAppScreenName2Size > 0x48)
            {
                return(ResultCode.InvalidArgument);
            }

            // TODO: Call nn::arp::GetApplicationControlProperty here when implemented.
            ApplicationControlProperty controlProperty = context.Device.Application.ControlData.Value;

            /*
             *
             * NOTE: The service calls nn::friends::detail::service::core::PlayHistoryManager to store informations using the registration key computed in GetPlayHistoryRegistrationKey.
             *    Then calls nn::friends::detail::service::core::FriendListManager to update informations on the friend list.
             *    We currently don't support play history and online services so it's fine to do nothing.
             *
             */

            Logger.Stub?.PrintStub(LogClass.ServiceFriend);

            return(ResultCode.Success);
        }
コード例 #14
0
ファイル: Horizon.cs プロジェクト: gamedropswithpops/Ryujinx
        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}\"");
                        }
                    }
                }
            }
コード例 #15
0
 public static Result EnsureApplicationBcatDeliveryCacheStorage(this FileSystemClient fs, out long requiredSize,
                                                                Ncm.ApplicationId applicationId, ref ApplicationControlProperty nacp)
 {
     return(EnsureApplicationBcatDeliveryCacheStorageImpl(fs, out requiredSize, applicationId, ref nacp));
 }
コード例 #16
0
        public static Result EnsureApplicationCacheStorage(this FileSystemClient fs, out long requiredSize,
                                                           out CacheStorageTargetMedia target, Ncm.ApplicationId applicationId, ref ApplicationControlProperty nacp)
        {
            if (nacp.CacheStorageSize <= 0)
            {
                requiredSize = default;
                target       = default;
                return(Result.Success);
            }

            return(EnsureApplicationCacheStorageImpl(fs, out requiredSize, out target, applicationId,
                                                     nacp.SaveDataOwnerId.Value, 0, nacp.CacheStorageSize, nacp.CacheStorageJournalSize, true));
        }
コード例 #17
0
 public static Result EnsureApplicationCacheStorage(this FileSystemClient fs, out long requiredSize,
                                                    Ncm.ApplicationId applicationId, ref ApplicationControlProperty nacp)
 {
     return(EnsureApplicationCacheStorageImpl(fs, out requiredSize, out _, applicationId, nacp.SaveDataOwnerId.Value,
                                              0, nacp.CacheStorageSize, nacp.CacheStorageJournalSize, true));
 }
コード例 #18
0
        private static Result EnsureApplicationBcatDeliveryCacheStorageImpl(FileSystemClient fs, out long requiredSize,
                                                                            Ncm.ApplicationId applicationId, ref ApplicationControlProperty nacp)
        {
            const long bcatDeliveryCacheJournalSize = 0x200000;

            long bcatStorageSize = nacp.BcatDeliveryCacheStorageSize;

            if (bcatStorageSize <= 0)
            {
                requiredSize = 0;
                return(Result.Success);
            }

            requiredSize = default;
            long requiredSizeBcat = 0;

            var filter = new SaveDataFilter();

            filter.SetProgramId(applicationId);
            filter.SetSaveDataType(SaveDataType.Bcat);

            Result CreateBcatStorageFunc() => fs.CreateBcatSaveData(applicationId, bcatStorageSize);

            Result rc = EnsureAndExtendSaveData(fs, CreateBcatStorageFunc,
                                                ref requiredSizeBcat, ref filter, 0x4000, bcatStorageSize, bcatDeliveryCacheJournalSize);

            if (rc.IsFailure())
            {
                return(rc);
            }

            requiredSize = requiredSizeBcat;
            return(requiredSizeBcat > 0 ? ResultFs.InsufficientFreeSpace.Log() : Result.Success);
        }
コード例 #19
0
        public static Result EnsureApplicationSaveData(FileSystemClient fs, out long requiredSize, Ncm.ApplicationId applicationId,
                                                       ref ApplicationControlProperty nacp, ref Uid uid)
        {
            requiredSize = default;
            long requiredSizeSum = 0;

            // Create local variable for use in closures
            ProgramId saveDataOwnerId = nacp.SaveDataOwnerId;

            // Ensure the user account save exists
            if (uid != Uid.Zero && nacp.UserAccountSaveDataSize > 0)
            {
                // More local variables for use in closures
                Uid  uidLocal               = uid;
                long accountSaveDataSize    = nacp.UserAccountSaveDataSize;
                long accountSaveJournalSize = nacp.UserAccountSaveDataJournalSize;

                Result CreateAccountSaveFunc()
                {
                    UserId userId = ConvertAccountUidToFsUserId(uidLocal);

                    return(fs.CreateSaveData(applicationId, userId, saveDataOwnerId.Value, accountSaveDataSize,
                                             accountSaveJournalSize, SaveDataFlags.None));
                }

                var filter = new SaveDataFilter();
                filter.SetProgramId(applicationId);
                filter.SetSaveDataType(SaveDataType.Account);
                filter.SetUserId(new UserId(uid.Id.High, uid.Id.Low));

                // The 0x4c000 includes the save meta and other stuff
                Result rc = EnsureAndExtendSaveData(fs, CreateAccountSaveFunc, ref requiredSizeSum, ref filter, 0x4c000,
                                                    accountSaveDataSize, accountSaveJournalSize);

                if (rc.IsFailure())
                {
                    return(rc);
                }
            }

            // Ensure the device save exists
            if (nacp.DeviceSaveDataSize > 0)
            {
                long deviceSaveDataSize    = nacp.DeviceSaveDataSize;
                long deviceSaveJournalSize = nacp.DeviceSaveDataJournalSize;

                Result CreateDeviceSaveFunc() => fs.CreateDeviceSaveData(applicationId, saveDataOwnerId.Value,
                                                                         deviceSaveDataSize, deviceSaveJournalSize, 0);

                var filter = new SaveDataFilter();
                filter.SetProgramId(applicationId);
                filter.SetSaveDataType(SaveDataType.Device);

                Result rc = EnsureAndExtendSaveData(fs, CreateDeviceSaveFunc, ref requiredSizeSum, ref filter, 0x4000,
                                                    deviceSaveDataSize, deviceSaveJournalSize);

                if (rc.IsFailure())
                {
                    return(rc);
                }
            }

            Result bcatRc = EnsureApplicationBcatDeliveryCacheStorageImpl(fs,
                                                                          out long requiredSizeBcat, applicationId, ref nacp);

            if (bcatRc.IsFailure())
            {
                if (!ResultFs.InsufficientFreeSpace.Includes(bcatRc))
                {
                    return(bcatRc);
                }

                requiredSizeSum += requiredSizeBcat;
            }

            if (nacp.TemporaryStorageSize > 0)
            {
                if (requiredSizeSum > 0)
                {
                    // If there was already insufficient space to create the previous saves, check if the temp
                    // save already exists instead of trying to create a new one.
                    var filter = new SaveDataFilter();
                    filter.SetProgramId(applicationId);
                    filter.SetSaveDataType(SaveDataType.Temporary);

                    Result rc = fs.FindSaveDataWithFilter(out _, SaveDataSpaceId.Temporary, ref filter);

                    if (rc.IsFailure())
                    {
                        if (!ResultFs.TargetNotFound.Includes(rc))
                        {
                            return(rc);
                        }

                        Result queryRc = fs.QuerySaveDataTotalSize(out long tempSaveTotalSize,
                                                                   nacp.TemporaryStorageSize, 0);

                        if (queryRc.IsFailure())
                        {
                            return(queryRc);
                        }

                        requiredSizeSum += Utilities.AlignUp(tempSaveTotalSize, 0x4000) + 0x4000;
                    }
                }
                else
                {
                    Result createRc = fs.CreateTemporaryStorage(applicationId, nacp.SaveDataOwnerId.Value,
                                                                nacp.TemporaryStorageSize, 0);

                    if (createRc.IsFailure())
                    {
                        if (ResultFs.InsufficientFreeSpace.Includes(createRc))
                        {
                            Result queryRc = fs.QuerySaveDataTotalSize(out long tempSaveTotalSize,
                                                                       nacp.TemporaryStorageSize, 0);

                            if (queryRc.IsFailure())
                            {
                                return(queryRc);
                            }

                            requiredSizeSum += Utilities.AlignUp(tempSaveTotalSize, 0x4000) + 0x4000;
                        }
                        else if (ResultFs.PathAlreadyExists.Includes(createRc))
                        {
                            requiredSizeSum += 0;
                        }
                        else
                        {
                            return(createRc);
                        }
                    }
                }
            }

            requiredSize = requiredSizeSum;

            return(requiredSize == 0 ? Result.Success : ResultFs.InsufficientFreeSpace.Log());
        }
コード例 #20
0
ファイル: ArpClient.cs プロジェクト: leo60228/LibHac
        public Result GetApplicationControlProperty(out ApplicationControlProperty controlProperty, ApplicationId applicationId)
        {
            EnsureReaderInitialized();

            return(Reader.GetApplicationControlPropertyWithApplicationId(out controlProperty, applicationId));
        }
コード例 #21
0
ファイル: LibHacIReader.cs プロジェクト: ski982/Ryujinx-1
 public Result GetApplicationControlProperty(out ApplicationControlProperty controlProperty, ulong processId)
 {
     throw new NotImplementedException();
 }
コード例 #22
0
 public TitleUpdateModel(ApplicationControlProperty control, string path, bool isNoUpdate = false)
 {
     Control    = control;
     Path       = path;
     IsNoUpdate = isNoUpdate;
 }
コード例 #23
0
        public static Result CreateApplicationCacheStorage(this FileSystemClient fs, out long requiredSize,
                                                           out CacheStorageTargetMedia target, Ncm.ApplicationId applicationId, ref ApplicationControlProperty nacp,
                                                           ushort index, long dataSize, long journalSize)
        {
            UnsafeHelpers.SkipParamInit(out requiredSize, out target);

            if (index > nacp.CacheStorageMaxIndex)
            {
                return(ResultFs.CacheStorageIndexTooLarge.Log());
            }

            if (dataSize + journalSize > nacp.CacheStorageMaxSizeAndMaxJournalSize)
            {
                return(ResultFs.CacheStorageSizeTooLarge.Log());
            }

            Result rc = fs.EnsureApplicationCacheStorage(out requiredSize, out target, applicationId,
                                                         nacp.SaveDataOwnerId.Value, index, dataSize, journalSize, false);

            fs.Impl.AbortIfNeeded(rc);
            return(rc);
        }
コード例 #24
0
        public static Result EnsureApplicationSaveData(FileSystemClient fs, out long requiredSize, TitleId applicationId,
                                                       ref ApplicationControlProperty nacp, ref Uid uid)
        {
            requiredSize = default;

            long requiredSizeSum = 0;

            if (uid != Uid.Zero && nacp.UserAccountSaveDataSize > 0)
            {
                var filter = new SaveDataFilter();
                filter.SetTitleId(applicationId);
                filter.SetSaveDataType(SaveDataType.SaveData);
                filter.SetUserId(new UserId(uid.Id.High, uid.Id.Low));

                Result rc = fs.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, ref filter);

                if (rc.IsSuccess())
                {
                    rc = ExtendSaveDataIfNeeded(fs, out long requiredSizeUser, SaveDataSpaceId.User,
                                                saveDataInfo.SaveDataId, nacp.UserAccountSaveDataSize, nacp.UserAccountSaveDataJournalSize);

                    if (rc.IsFailure())
                    {
                        if (!ResultRangeFs.InsufficientFreeSpace.Contains(rc))
                        {
                            return(rc);
                        }

                        requiredSizeSum = requiredSizeUser;
                    }
                }
                else if (rc != ResultFs.TargetNotFound)
                {
                    return(rc);
                }
                else
                {
                    UserId userId = ConvertAccountUidToFsUserId(uid);

                    Result createRc = fs.CreateSaveData(applicationId, userId, nacp.SaveDataOwnerId,
                                                        nacp.UserAccountSaveDataSize, nacp.UserAccountSaveDataJournalSize, 0);

                    if (createRc.IsFailure())
                    {
                        if (ResultRangeFs.InsufficientFreeSpace.Contains(createRc))
                        {
                            // todo: Call QuerySaveDataTotalSize and assign the value to requiredSizeSum
                            requiredSizeSum = 0;
                        }
                        else if (createRc == ResultFs.PathAlreadyExists)
                        {
                            requiredSizeSum = 0;
                        }
                        else
                        {
                            return(createRc);
                        }
                    }
                }
            }

            if (nacp.DeviceSaveDataSize > 0)
            {
                var filter = new SaveDataFilter();
                filter.SetTitleId(applicationId);
                filter.SetSaveDataType(SaveDataType.DeviceSaveData);

                Result rc = fs.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, ref filter);

                if (rc.IsSuccess())
                {
                    rc = ExtendSaveDataIfNeeded(fs, out long requiredSizeDevice, SaveDataSpaceId.User,
                                                saveDataInfo.SaveDataId, nacp.DeviceSaveDataSize, nacp.DeviceSaveDataJournalSize);

                    if (rc.IsFailure())
                    {
                        if (!ResultRangeFs.InsufficientFreeSpace.Contains(rc))
                        {
                            return(rc);
                        }

                        requiredSizeSum += requiredSizeDevice;
                    }
                }
                else if (rc != ResultFs.TargetNotFound)
                {
                    return(rc);
                }
                else
                {
                    Result createRc = fs.CreateDeviceSaveData(applicationId, nacp.SaveDataOwnerId,
                                                              nacp.DeviceSaveDataSize, nacp.DeviceSaveDataJournalSize, 0);

                    if (createRc.IsFailure())
                    {
                        if (ResultRangeFs.InsufficientFreeSpace.Contains(createRc))
                        {
                            // todo: Call QuerySaveDataTotalSize and add the value to requiredSizeSum
                            requiredSizeSum += 0;
                        }
                        else if (createRc == ResultFs.PathAlreadyExists)
                        {
                            requiredSizeSum += 0;
                        }
                        else
                        {
                            return(createRc);
                        }
                    }
                }
            }

            Result bcatRc = EnsureApplicationBcatDeliveryCacheStorageImpl(fs,
                                                                          out long requiredSizeBcat, applicationId, ref nacp);

            if (bcatRc.IsFailure())
            {
                if (!ResultRangeFs.InsufficientFreeSpace.Contains(bcatRc))
                {
                    return(bcatRc);
                }

                requiredSizeSum += requiredSizeBcat;
            }

            // Don't actually do this yet because the temp save indexer hasn't been implemented
            // todo: Flip the operator when it is
            if (nacp.TemporaryStorageSize < 0)
            {
                if (requiredSizeSum > 0)
                {
                    var filter = new SaveDataFilter();
                    filter.SetTitleId(applicationId);
                    filter.SetSaveDataType(SaveDataType.TemporaryStorage);

                    Result rc = fs.FindSaveDataWithFilter(out _, SaveDataSpaceId.User, ref filter);

                    if (rc.IsFailure())
                    {
                        if (rc != ResultFs.TargetNotFound)
                        {
                            return(rc);
                        }

                        // todo: Call QuerySaveDataTotalSize and add the value to requiredSizeSum
                        requiredSizeSum += 0;
                    }
                }
                else
                {
                    Result createRc = fs.CreateTemporaryStorage(applicationId, nacp.SaveDataOwnerId,
                                                                nacp.TemporaryStorageSize, 0);

                    if (createRc.IsFailure())
                    {
                        if (ResultRangeFs.InsufficientFreeSpace.Contains(createRc))
                        {
                            // todo: Call QuerySaveDataTotalSize and assign the value to requiredSizeSum
                            requiredSizeSum += 0;
                        }
                        else if (createRc == ResultFs.PathAlreadyExists)
                        {
                            requiredSizeSum += 0;
                        }
                        else
                        {
                            return(createRc);
                        }
                    }
                }
            }

            requiredSize = requiredSizeSum;

            return(requiredSize == 0 ? Result.Success : ResultFs.InsufficientFreeSpace.Log());
        }
コード例 #25
0
ファイル: LibHacIReader.cs プロジェクト: ski982/Ryujinx-1
 public Result GetApplicationControlPropertyWithApplicationId(out ApplicationControlProperty controlProperty,
                                                              ApplicationId applicationId)
 {
     throw new NotImplementedException();
 }
コード例 #26
0
        private static Result EnsureApplicationBcatDeliveryCacheStorageImpl(FileSystemClient fs, out long requiredSize,
                                                                            TitleId applicationId, ref ApplicationControlProperty nacp)
        {
            const long bcatDeliveryCacheJournalSize = 0x200000;

            requiredSize = default;

            if (nacp.BcatDeliveryCacheStorageSize <= 0)
            {
                requiredSize = 0;
                return(Result.Success);
            }

            var filter = new SaveDataFilter();

            filter.SetTitleId(applicationId);
            filter.SetSaveDataType(SaveDataType.BcatDeliveryCacheStorage);

            Result rc = fs.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, ref filter);

            if (rc.IsSuccess())
            {
                rc = ExtendSaveDataIfNeeded(fs, out long requiredSizeBcat, SaveDataSpaceId.User,
                                            saveDataInfo.SaveDataId, nacp.DeviceSaveDataSize, bcatDeliveryCacheJournalSize);

                if (rc.IsFailure())
                {
                    if (!ResultRangeFs.InsufficientFreeSpace.Contains(rc))
                    {
                        return(rc);
                    }

                    requiredSize = requiredSizeBcat;
                }
            }
            else if (rc != ResultFs.TargetNotFound)
            {
                return(rc);
            }
            else
            {
                Result createRc = fs.CreateBcatSaveData(applicationId, nacp.BcatDeliveryCacheStorageSize);

                if (createRc.IsFailure())
                {
                    if (ResultRangeFs.InsufficientFreeSpace.Contains(createRc))
                    {
                        // todo: Call QuerySaveDataTotalSize and assign the value to requiredSize
                        requiredSize = 0;
                    }
                    else if (createRc == ResultFs.PathAlreadyExists)
                    {
                        requiredSize = 0;
                    }
                    else
                    {
                        return(createRc);
                    }
                }
            }

            return(requiredSize > 0 ? ResultFs.InsufficientFreeSpace.Log() : Result.Success);
        }
コード例 #27
0
ファイル: ArpClient.cs プロジェクト: leo60228/LibHac
        public Result GetApplicationControlProperty(out ApplicationControlProperty controlProperty, ulong processId)
        {
            EnsureReaderInitialized();

            return(Reader.GetApplicationControlProperty(out controlProperty, processId));
        }