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()); }