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