Пример #1
0
        private void RemoveFile(FileEntry parent, FileEntry fileEntry)
        {
            var block = fileEntry.StartingBlockNum;

            for (var i = 0; i < fileEntry.BlocksForFile; i++)
            {
                var he = GetHashEntry(block);
                he.Status = BlockStatus.PreviouslyAllocated;
                if (UnallocatedHashEntries.Contains(block))
                {
                    throw new Exception("qwe");
                }
                UnallocatedHashEntries.Add(block);
                block = he.NextBlock;
            }
            fileEntry.BlocksForFile = 0;
            fileEntry.Name          = string.Empty;
            parent.Files.Remove(fileEntry);
        }
Пример #2
0
        public void ReplaceFile(FileEntry fileEntry, byte[] content)
        {
            if (fileEntry.IsDirectory)
            {
                throw new NotSupportedException("Directories doesn't have content!");
            }

            var remaining = content.Length;

            var allocatedBlockCount = fileEntry.BlocksForFile;
            var newBlockCount       = (content.Length + 0xFFF) / 0x1000;
            var blocks = AllocateBlocks(newBlockCount - allocatedBlockCount);
            var block  = fileEntry.StartingBlockNum;

            if (allocatedBlockCount == 0)
            {
                block = blocks[0];
                fileEntry.StartingBlockNum = blocks[0];
            }
            var consecutive = true;

            for (var i = 0; i < newBlockCount; i++)
            {
                var pos  = GetRealAddressOfBlock(block);
                var size = remaining > 0x1000 ? 0x1000 : remaining;
                remaining -= size;
                var buffer = new byte[0x1000];
                Buffer.BlockCopy(content, i * 0x1000, buffer, 0, size);
                Binary.WriteBytes(pos, buffer, 0, 0x1000);

                var he = GetHashEntry(block);
                if (i < allocatedBlockCount - 1)
                {
                    he.Status = BlockStatus.Allocated;
                    if (he.NextBlock != block + 1)
                    {
                        consecutive = false;
                    }
                    block = he.NextBlock;
                }
                else if (i < newBlockCount - 1)
                {
                    he.Status    = BlockStatus.NewlyAllocated;
                    block        = blocks[i - allocatedBlockCount + 1];
                    he.NextBlock = block;
                    if (he.NextBlock != he.Block + 1)
                    {
                        consecutive = false;
                    }
                }
                else
                {
                    he.Status    = BlockStatus.NewlyAllocated;
                    he.NextBlock = 0xFFFFFF;
                }
            }

            for (var i = newBlockCount; i < allocatedBlockCount; i++)
            {
                var he = GetHashEntry(block);
                if (UnallocatedHashEntries.Contains(block))
                {
                    throw new Exception("qwe");
                }
                UnallocatedHashEntries.Add(block);
                he.Status    = BlockStatus.PreviouslyAllocated;
                block        = he.NextBlock;
                he.NextBlock = 0xFFFFFF;
            }

            fileEntry.FileSize             = content.Length;
            fileEntry.BlocksForFile        = newBlockCount;
            fileEntry.BlocksForFileCopy    = newBlockCount;
            fileEntry.BlocksAreConsecutive = consecutive;
        }
Пример #3
0
        public void MergeWith(StfsPackage otherProfile)
        {
            if (!IsModified)
            {
                SwitchTables();
            }

            var count = otherProfile.ProfileInfo.TitlesPlayed.Count;

            NotifyContentCountDetermined(count);

            var otherPec     = otherProfile.ExtractPec();
            var pecFileEntry = GetFileEntry("PEC");
            var pec          = ExtractPec();

            //HACK horizon
            int?newBlock = AllocateBlocks(1)[0];

            foreach (var title in otherProfile.ProfileInfo.TitlesPlayed)
            {
                var watch = new Stopwatch();
                watch.Start();
                var name              = title.TitleCode + ".gpd";
                var otherGame         = otherProfile.GetGameFile(name, true);
                var otherAvatarAwards = otherPec.GetGameFile(name, true);

                var fileEntry = GetFileEntry(name, true);
                if (fileEntry != null)
                {
                    var titleEntry = ProfileInfo.TitlesPlayed.FirstOrDefault(t => t.TitleCode == title.TitleCode);
                    if (titleEntry != null)
                    {
                        //Title already exists in target, merge is necessary
                        var game = GetGameFile(fileEntry, true);
                        if (game.MergeWith(otherGame))
                        {
                            RebuildGame(game);
                        }

                        if (otherAvatarAwards != null)
                        {
                            var avatarAwards = pec.GetGameFile(name, true);
                            if (avatarAwards != null)
                            {
                                if (avatarAwards.MergeWith(otherAvatarAwards))
                                {
                                    avatarAwards.Rebuild();
                                    var pecGpdEntry = pec.GetFileEntry(name);
                                    pec.ReplaceFile(pecGpdEntry, avatarAwards);
                                }
                            }
                            else
                            {
                                pec.AddFile(name, otherAvatarAwards.Binary.ReadAll());
                            }
                        }
                    }
                    else
                    {
                        throw new Exception("Title doesn't exists, but the gpd file does");
                        //Title doesn't exists, but the gpd file does, we just replace that

                        //var otherBinary = otherGame.Binary.ReadAll();
                        //ReplaceFile(fileEntry, otherBinary);
                        //var tid = title.TitleId.ToArray();
                        //Array.Reverse(tid);
                        //var id = BitConverter.ToUInt32(tid, 0);
                        //ProfileInfo.AddNewEntry<TitleEntry>(EntryType.Title, title.AllBytes, id);
                        //info = "added";
                    }
                }
                else
                {
                    if (otherAvatarAwards != null)
                    {
                        pec.AddFile(name, otherAvatarAwards.Binary.ReadAll());
                    }

                    if (otherGame != null)
                    {
                        //Add gpd and title
                        var otherBinary = otherGame.Binary.ReadAll();

                        //File.WriteAllBytes(@"d:\NTX-CNT\Contour\Resources\mergeable\aktualis\q\" + i + "_" + name, otherBinary);

                        fileEntry = AddFile(name, otherBinary);
                        CreateGameFileModel(fileEntry, otherBinary, true);

                        var tid = title.TitleId.ToArray();
                        Array.Reverse(tid);
                        var id = BitConverter.ToUInt32(tid, 0);
                        ProfileInfo.AddNewEntry <TitleEntry>(EntryType.Title, title.AllBytes, id);
                    }
                }
                watch.Stop();
                //LogHelper.NotifyStatusBarChange(++i);
                //LogHelper.NotifyStatusBarText(string.Format("{0}/{1} {2} merged", i, count, title.TitleName));
            }

            //LogHelper.NotifyStatusBarText("Rebuilding profile...");
            foreach (var title in ProfileInfo.TitlesPlayed)
            {
                var name = title.TitleCode + ".gpd";
                var game = GetGameFile(name, true);
                title.LastAchievementEarnedOn = game.AchievementCount > 0 ? game.Achievements.Max(a => a.UnlockTime) : DateTime.MinValue;
            }

            //HACK: Horizon
            var previous = 0;
            var block    = VolumeDescriptor.FileTableBlockNum;

            for (var k = 0; k < VolumeDescriptor.FileTableBlockCount - 1; k++)
            {
                var hek = GetHashEntry(block);
                previous = block;
                block    = hek.NextBlock;
            }
            Binary.WriteBytes(GetRealAddressOfBlock(newBlock.Value), Binary.ReadBytes(GetRealAddressOfBlock(block), 0x1000), 0, 0x1000);
            var he = GetHashEntry(block);

            he.Status = BlockStatus.PreviouslyAllocated;
            he        = GetHashEntry(newBlock.Value);
            he.Status = BlockStatus.NewlyAllocated;
            UnallocatedHashEntries.Add(block);
            GetHashEntry(previous).NextBlock = newBlock.Value;

            ProfileInfo.Recalculate();
            ProfileInfo.Rebuild();
            ReplaceFile(ProfileEntry, ProfileInfo);

            pec.Rehash();
            pec.Resign();
            ReplaceFile(pecFileEntry, pec.Binary.ReadAll());
        }