Exemplo n.º 1
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());
        }