static void Main(string[] args) { string dir; if (args.Length == 1) { dir = Path.Combine(Path.GetDirectoryName(args[0]), Path.GetFileNameWithoutExtension(args[0])); } else if (args.Length != 2) { Console.WriteLine("Usage: u8extractor /path/to/file.arc [/extract/path]"); return; } else { dir = args[1]; } Stream filestream = new FileStream(args[0], FileMode.Open, FileAccess.Read, FileShare.Read); Stream stream = filestream; try { DlcBin dlc = new DlcBin(filestream); stream = dlc.Data; } catch (FormatException) { } U8 u8 = new U8(stream); u8.Root.Extract(dir); filestream.Close(); }
static void PlatformDetection_DetectWiiDlcBin(string path, DlcBin dlc, PlatformList platforms) { if (DetectDirectoryNode != null) { try { U8 u8 = new U8(dlc.Data); DetectDirectoryNode(path, u8.Root, platforms); } catch (FormatException) { } catch (Exception exception) { Exceptions.Warning(exception, "Trying to open as DLC U8: " + path); } } }
private void AddSongFromBins(PlatformData data, SongData song, string dtapath, string contentpath, ProgressIndicator progress, bool replace = false) { if (File.Exists(contentpath) && File.Exists(dtapath)) { Stream contentfile = null; Stream dtafile = null; if (IterateBins) { contentfile = new DelayedStream(data.Cache.GenerateFileStream(contentpath, FileMode.Open)); DlcBin content = new DlcBin(contentfile); U8 u8 = new U8(content.Data); // Read album art from the preview bin dtafile = new DelayedStream(data.Cache.GenerateFileStream(dtapath, FileMode.Open)); DlcBin dtabin = new DlcBin(dtafile); U8 dtau8 = new U8(dtabin.Data); string genpath = "/content/songs/" + song.ID + "/gen"; DirectoryNode dtagen = dtau8.Root.Navigate(genpath) as DirectoryNode; if (dtagen != null) { DirectoryNode contentgen = u8.Root.Navigate(genpath) as DirectoryNode; if (contentgen != null) { contentgen.AddChildren(dtagen.Files); } } data.Session["songdir"] = u8.Root; } if (replace) { foreach (FormatData formatdata in data.Songs) { if (formatdata.Song.ID == song.ID) { base.DeleteSong(data, formatdata, progress); break; } } } AddSong(data, song, progress); // TODO: Add dta bin to songdir for album art if (IterateBins) { data.Session.Remove("songdir"); contentfile.Close(); dtafile.Close(); } } }
static void PlatformDetection_DetectDirectoryNode(string path, DirectoryNode root, List <Pair <Engine, Game> > platforms) { FileNode file = root.Navigate("001.bin") as FileNode; if (file == null) { return; } try { DlcBin bin = new DlcBin(file.Data); if (bin.Bk.TitleID == 0x0001000053584145) { platforms.Add(new Pair <Engine, Game>(Instance, Game.GuitarHeroWorldTour)); } } catch { } file.Data.Close(); }
public override bool AddSong(PlatformData data, SongData song, ProgressIndicator progress) { int index = int.Parse(song.ID.Substring(3)); //song.ID = "dlc" + ImportMap.GetShortName(song.Name); FormatData formatdata = new TemporaryFormatData(song, data); NeversoftMetadata.SaveSongItem(formatdata); DirectoryNode dir = data.Session["rootdir"] as DirectoryNode; FileNode binfile = dir.Navigate(Util.Pad(index.ToString(), 3) + ".bin") as FileNode; if (binfile == null) { return(false); } DlcBin bin = new DlcBin(binfile.Data); U8 u8 = new U8(bin.Data); FileNode chartpak = u8.Root.Find(song.ID + "_song.pak.ngc", SearchOption.AllDirectories) as FileNode; FileNode textpak = u8.Root.Find(song.ID + "_text.pak.ngc", SearchOption.AllDirectories) as FileNode; FileNode audiofile = u8.Root.Find(song.ID + ".bik", SearchOption.AllDirectories) as FileNode; if (chartpak == null || textpak == null || audiofile == null) { return(false); } ChartFormatGH4.Instance.Create(formatdata, new Stream[] { chartpak.Data, textpak.Data }, PlatformGH5WiiDisc.ImportExpertPlus); if (audiofile != null) { AudioFormatBink.Instance.Create(formatdata, audiofile.Data, null, null); } data.AddSong(formatdata); chartpak.Data.Close(); return(true); }
public override PlatformData Create(string path, Game game, ProgressIndicator progress) { PlatformData data = new PlatformData(this, game); DirectoryNode maindir = DirectoryNode.FromPath(path, data.Cache, FileAccess.Read); char[] regions = new char[] { 'E', 'P' }; DirectoryNode dir = maindir.Navigate("private/wii/data", false, true) as DirectoryNode; if (dir == null) dir = maindir; for (char letter = 'A'; letter <= 'Z'; letter++) { foreach (char region in regions) { DirectoryNode subdir = dir.Find("SZ" + letter + region, true) as DirectoryNode; if (subdir == null) continue; foreach (FileNode file in subdir.Files) { if (String.Compare(Path.GetExtension(file.Name), ".bin", true) != 0) continue; try { file.Data.Position = 0; DlcBin bin = new DlcBin(file.Data); U8 u8; try { u8 = new U8(bin.Data); } catch (FormatException) { file.Data.Close(); continue; } FileNode songsdta = u8.Root.Find("songs.dta", SearchOption.AllDirectories) as FileNode; if (songsdta == null) { file.Data.Close(); continue; } DTB.NodeTree dtb = DTA.Create(songsdta.Data); SongsDTA dta = SongsDTA.Create(dtb); file.Data.Close(); SongData song = HarmonixMetadata.GetSongData(data, dtb); string contentbin = dta.Song.Name.Substring(9, 3); // Example, "dlc/sZAE/023/content/songs/simpleman/simpleman" FileNode contentfile = subdir.Find(contentbin + ".bin", true) as FileNode; if (contentfile == null) continue; FormatData formatdata = new TemporaryFormatData(song, data); Create(formatdata, file.Data, contentfile.Data); data.AddSong(formatdata); contentfile.Data.Close(); } catch (FormatException) { } // Not a DLC bin we care about } } } return data; }
static void PlatformDetection_DetectFile(string path, Stream stream, PlatformList platforms) { if (DetectWiiDisc != null) { try { stream.Position = 0; Disc disc = new Disc(stream); DetectWiiDisc(path, disc, platforms); } catch (FormatException) { } catch (Exception exception) { Exceptions.Warning(exception, "Trying to open as Wiidisc: " + path); } } if (DetectIso9660 != null) { try { stream.Position = 0; Iso9660 disc = new Iso9660(stream); DetectIso9660(path, disc, platforms); } catch (FormatException) { } catch (Exception exception) { Exceptions.Warning(exception, "Trying to open as ISO: " + path); } } if (DetectXbox360Dlc != null) { try { stream.Position = 0; StfsArchive stfs = new StfsArchive(stream); DetectXbox360Dlc(path, stfs, platforms); } catch (FormatException) { } catch (Exception exception) { Exceptions.Warning(exception, "Trying to open as 360 DLC: " + path); } } if (DetectWiiU8 != null) { try { stream.Position = 0; U8 u8 = new U8(stream); DetectWiiU8(path, u8, platforms); } catch (FormatException) { } catch (Exception exception) { Exceptions.Warning(exception, "Trying to open as U8: " + path); } } if (DetectWiiDlcBin != null) { try { stream.Position = 0; DlcBin dlc = new DlcBin(stream); DetectWiiDlcBin(path, dlc, platforms); } catch (FormatException) { } catch (Exception exception) { Exceptions.Warning(exception, "Trying to open as Wii DLC: " + path); } } if (DetectHarmonixArk != null) { string extension = Path.GetExtension(path).ToLower(); if (extension.EndsWith(".ark") || extension.EndsWith(".hdr")) { PlatformDetection_DetectDirectory(Path.GetDirectoryName(path), platforms); } } }
public override PlatformData Create(string path, Game game, ProgressIndicator progress) { PlatformData data = new PlatformData(this, game); DirectoryNode dir = data.GetDirectoryStructure(path); FileNode binfile = dir.Navigate("001.bin") as FileNode; if (binfile == null) { Exceptions.Error("Unable to open Guitar Hero World Tour DLC because 001.bin is missing."); } data.Session["rootdir"] = dir; try { DlcBin bin = new DlcBin(binfile.Data); U8 u8 = new U8(bin.Data); FileNode listfile = u8.Root.Navigate("DLC1.pak.ngc") as FileNode; Pak qb = new Pak(new EndianReader(listfile.Data, Endianness.BigEndian)); FileNode songlistfile = qb.Root.Find("catalog_info.qb.ngc", SearchOption.AllDirectories) as FileNode; QbFile songlist = new QbFile(songlistfile.Data, PakFormat); StringList strings = new StringList(); foreach (Pak.Node node in qb.Nodes) { if (!node.Filename.HasValue()) { strings.ParseFromStream(node.Data); } } List <QbKey> listkeys = new List <QbKey>(); foreach (uint songlistkey in NeversoftMetadata.SonglistKeys) { QbKey key = QbKey.Create(songlistkey); QbItemStruct list = songlist.FindItem(key, true) as QbItemStruct; if (list != null && list.Items.Count > 0) { listkeys.Add(key); } } Stream str = new FileStream(@"C:\ghwt.xml", FileMode.Create); StreamWriter writer = new StreamWriter(str); progress.NewTask(listkeys.Count); foreach (QbKey songlistkey in listkeys) { QbItemStruct list = songlist.FindItem(songlistkey, true) as QbItemStruct; progress.NewTask(list.Items.Count); foreach (QbItemArray item in list.Items.OfType <QbItemArray>()) { item.Items[0].ItemQbKey = item.ItemQbKey; SongData song = NeversoftMetadata.GetSongData(data, item.Items[0] as QbItemStruct, strings); writer.WriteLine("\t<song id=\"" + song.ID + "\">"); writer.WriteLine("\t\t<pack>Guitar Hero World Tour DLC</pack>"); writer.WriteLine("\t\t<nameprefix>[GHWT DLC]</nameprefix>"); writer.WriteLine("\t\t<name>" + song.Name + "</name>"); writer.WriteLine("\t\t<artist>" + song.Artist + "</artist>"); writer.WriteLine("\t\t<album>" + song.Album + "</album>"); writer.WriteLine("\t\t<genre>" + song.Genre + "</genre>"); writer.WriteLine("\t\t<track>" + song.AlbumTrack.ToString() + "</track>"); writer.WriteLine("\t\t<difficulty instrument=\"band\" rank=\"1\" />"); writer.WriteLine("\t\t<difficulty instrument=\"guitar\" rank=\"1\" />"); writer.WriteLine("\t\t<difficulty instrument=\"bass\" rank=\"1\" />"); writer.WriteLine("\t\t<difficulty instrument=\"drum\" rank=\"1\" />"); writer.WriteLine("\t\t<difficulty instrument=\"vocals\" rank=\"1\" />"); writer.WriteLine("\t</song>"); try { AddSong(data, song, progress); } catch (Exception exception) { Exceptions.Warning(exception, "Unable to properly parse " + song.Name); } progress.Progress(); } progress.EndTask(); progress.Progress(); } progress.EndTask(); writer.Close(); binfile.Data.Close(); } catch (Exception exception) { Exceptions.Error(exception, "An error occurred while parsing the Guitar Hero World Tour DLC list."); } return(data); }
static void Main(string[] args) { string dir = string.Empty; if (args.Length == 2) { dir = args[1]; } else if (args.Length == 1) { dir = args[0] + ".ext"; } else { Console.WriteLine("Usage: wiidiscextractor /path/to/disc.iso /extract/path"); return; } Directory.CreateDirectory(dir); try { if (!Directory.Exists(args[0])) { throw new FormatException(); } DelayedStreamCache cache = new DelayedStreamCache(); DirectoryNode dirn = DirectoryNode.FromPath(args[0], cache, FileAccess.Read, FileShare.Read); DirectoryNode gen = dirn.Navigate("gen", false, true) as DirectoryNode; if (gen == null) // Just in case we're given the "wrong" directory that directly contains the ark { gen = dirn; } List <Pair <int, Stream> > arkfiles = new List <Pair <int, Stream> >(); Stream hdrfile = null; foreach (FileNode file in gen.Files) { if (file.Name.ToLower().EndsWith(".hdr")) { hdrfile = file.Data; } else if (file.Name.ToLower().EndsWith(".ark")) { Match match = Regex.Match(file.Name.ToLower(), @"_(\d+).ark"); if (match.Success) { arkfiles.Add(new Pair <int, Stream>(int.Parse(match.Groups[1].Value), file.Data)); } else { arkfiles.Add(new Pair <int, Stream>(0, file.Data)); } } } // FreQuency/Amplitude where the header is the ark if (hdrfile == null) { if (arkfiles.Count == 1) { hdrfile = arkfiles[0].Value; arkfiles.Clear(); } else { throw new FormatException(); } } Ark ark = new Ark(new EndianReader(hdrfile, Endianness.LittleEndian), arkfiles.OrderBy(f => f.Key).Select(f => f.Value).ToArray()); ark.Root.Extract(dir); cache.Dispose(); } catch (FormatException) { Stream stream = new FileStream(args[0], FileMode.Open, FileAccess.Read); try { Iso9660 iso = new Iso9660(stream); iso.Root.Extract(dir); } catch (Exception) { try { stream.Position = 0; Disc disc = new Disc(stream); File.WriteAllText(Path.Combine(dir, "title"), disc.Title); foreach (var partition in disc.Partitions) { string path = Path.Combine(dir, "partition" + disc.Partitions.IndexOf(partition).ToString()); Directory.CreateDirectory(path); partition.Root.Root.Extract(Path.Combine(path, "data")); FileStream file = new FileStream(Path.Combine(path, "partition.tik"), FileMode.Create, FileAccess.Write); partition.Ticket.Save(file); file.Close(); file = new FileStream(Path.Combine(path, "partition.tmd"), FileMode.Create, FileAccess.Write); partition.TMD.Save(file); file.Close(); file = new FileStream(Path.Combine(path, "partition.certs"), FileMode.Create, FileAccess.Write); file.Write(partition.CertificateChain); file.Close(); } } catch { try { stream.Position = 0; DlcBin bin = new DlcBin(stream); U8 u8 = new U8(bin.Data); u8.Root.Extract(dir); } catch { try { stream.Position = 0; U8 u8 = new U8(stream); u8.Root.Extract(dir); } catch { stream.Position = 0; Rarc rarc = new Rarc(stream); rarc.Root.Extract(dir); } } } } stream.Close(); } }
public override void SaveSong(PlatformData data, FormatData formatdata, ProgressIndicator progress) { string path = data.Session["maindirpath"] as string; string otitle; ushort oindex; progress.NewTask(10); using (DelayedStreamCache cache = new DelayedStreamCache()) { progress.SetNextWeight(6); string audioextension = ".mogg"; Stream audio = null; Stream preview = null; AudioFormat audioformat = null; IList <IFormat> formats = formatdata.Formats; if (formats.Contains(AudioFormatRB2Mogg.Instance)) { audio = AudioFormatRB2Mogg.Instance.GetAudioStream(formatdata); preview = AudioFormatRB2Mogg.Instance.GetPreviewStream(formatdata); audioformat = AudioFormatRB2Mogg.Instance.DecodeAudioFormat(formatdata); } else if (formats.Contains(AudioFormatRB2Bink.Instance)) { audio = AudioFormatRB2Bink.Instance.GetAudioStream(formatdata); preview = AudioFormatRB2Bink.Instance.GetPreviewStream(formatdata, progress); if (!formatdata.HasStream(preview)) { cache.AddStream(preview); } audioformat = AudioFormatRB2Bink.Instance.DecodeAudioFormat(formatdata); audioextension = ".bik"; } else { throw new NotSupportedException(); } progress.Progress(6); ChartFormat chartformat = (formatdata.GetFormat(FormatType.Chart) as IChartFormat).DecodeChart(formatdata, progress); Stream album = null; Stream chart = formatdata.GetStream(ChartFormatRB.Instance, ChartFormatRB.ChartFile); Stream pan = formatdata.GetStream(ChartFormatRB.Instance, ChartFormatRB.PanFile); Stream weights = formatdata.GetStream(ChartFormatRB.Instance, ChartFormatRB.WeightsFile); Stream milo = formatdata.GetStream(ChartFormatRB.Instance, ChartFormatRB.MiloFile); progress.SetNextWeight(2); if (chart != null && ChartFormatRB.Instance.NeedsFixing(formatdata)) { formatdata.CloseStream(chart); chart = null; } if (chart == null) { chart = new TemporaryStream(); cache.AddStream(chart); AdjustChart(formatdata.Song, audioformat, chartformat).ToMidi().ToMid().Save(chart); chart.Position = 0; } if (weights == null) { weights = new TemporaryStream(); cache.AddStream(weights); CreateWeights(weights, chartformat); weights.Position = 0; } if (pan == null) { pan = new TemporaryStream(); cache.AddStream(pan); CreatePan(pan, chartformat); pan.Position = 0; } if (milo == null) { milo = formatdata.GetStream(ChartFormatRB.Instance, ChartFormatRB.Milo3File); if (milo == null) { milo = new MemoryStream(Properties.Resources.rawksd_milo); } else { Stream milostream = new TemporaryStream(); cache.AddStream(milostream); Milo milofile = new Milo(new EndianReader(milo, Endianness.LittleEndian)); FaceFX fx = new FaceFX(new EndianReader(milofile.Data[0], Endianness.BigEndian)); TemporaryStream fxstream = new TemporaryStream(); fx.Save(new EndianReader(fxstream, Endianness.LittleEndian)); milofile.Data[0] = fxstream; milofile.Compressed = true; milofile.Save(new EndianReader(milostream, Endianness.LittleEndian)); fxstream.Close(); formatdata.CloseStream(milo); milo = milostream; milo.Position = 0; } } //if (album == null) // album = new MemoryStream(Properties.Resources.rawksd_albumart); progress.Progress(2); SongData song = new SongData(formatdata.Song); SongsDTA dta = GetSongsDTA(song, audioformat); if (album == null) { dta.AlbumArt = false; } else { dta.AlbumArt = true; } dta.Song.MidiFile = "dlc/content/songs/" + song.ID + "/" + song.ID + ".mid"; DTB.NodeTree dtb = dta.ToDTB(PlatformRawkFile.Instance.IsRawkSD2(song)); MemoryStream songsdta = new MemoryStream(); cache.AddStream(songsdta); dtb.SaveDTA(songsdta); songsdta.Position = 0; U8 appdta = new U8(); DirectoryNode dir = new DirectoryNode("content"); appdta.Root.AddChild(dir); DirectoryNode songsdir = new DirectoryNode("songs"); dir.AddChild(songsdir); DirectoryNode songdir = new DirectoryNode(song.ID); songsdir.AddChild(songdir); songdir.AddChild(new FileNode(song.ID + "_prev.mogg", preview)); songdir.AddChild(new FileNode("songs.dta", songsdta)); DirectoryNode gendir; if (dta.AlbumArt.Value && album != null) { gendir = new DirectoryNode("gen"); songdir.AddChild(gendir); gendir.AddChild(new FileNode(song.ID + "_nomip_keep.bmp_wii", album)); } U8 appsong = new U8(); dir = new DirectoryNode("content"); appsong.Root.AddChild(dir); songsdir = new DirectoryNode("songs"); dir.AddChild(songsdir); songdir = new DirectoryNode(song.ID); songsdir.AddChild(songdir); songdir.AddChild(new FileNode(song.ID + audioextension, audio)); songdir.AddChild(new FileNode(song.ID + ".mid", chart)); songdir.AddChild(new FileNode(song.ID + ".pan", pan)); gendir = new DirectoryNode("gen"); songdir.AddChild(gendir); gendir.AddChild(new FileNode(song.ID + ".milo_wii", milo)); gendir.AddChild(new FileNode(song.ID + "_weights.bin", weights)); Stream memoryDta = new TemporaryStream(); cache.AddStream(memoryDta); appdta.Save(memoryDta); Stream memorySong = new TemporaryStream(); cache.AddStream(memorySong); appsong.Save(memorySong); formatdata.CloseStream(audio); formatdata.CloseStream(preview); formatdata.CloseStream(chart); formatdata.CloseStream(album); formatdata.CloseStream(pan); formatdata.CloseStream(weights); formatdata.CloseStream(milo); FindUnusedContent(data, formatdata.Song, out otitle, out oindex); TMD tmd = GenerateDummyTMD(otitle); dta.Song.Name = "dlc/" + otitle + "/" + Util.Pad(oindex.ToString(), 3) + "/content/songs/" + song.ID + "/" + song.ID; dtb = dta.ToDTB(PlatformRawkFile.Instance.IsRawkSD2(song)); HarmonixMetadata.SetSongsDTA(song, dtb); string dirpath = Path.Combine(Path.Combine(path, "rawk"), "rb2"); if (!Directory.Exists(Path.Combine(dirpath, "customs"))) { Directory.CreateDirectory(Path.Combine(dirpath, "customs")); } Directory.CreateDirectory(Path.Combine(Path.Combine(dirpath, "customs"), song.ID)); FileStream savestream = new FileStream(Path.Combine(Path.Combine(Path.Combine(dirpath, "customs"), song.ID), "data"), FileMode.Create); dtb.Save(new EndianReader(savestream, Endianness.LittleEndian)); savestream.Close(); TmdContent contentDta = new TmdContent(); contentDta.ContentID = oindex; contentDta.Index = oindex; contentDta.Type = 0x4001; TmdContent contentSong = new TmdContent(); contentSong.ContentID = oindex + 1U; contentSong.Index = (ushort)(oindex + 1); contentSong.Type = 0x4001; memoryDta.Position = 0; contentDta.Hash = Util.SHA1Hash(memoryDta); contentDta.Size = memoryDta.Length; memorySong.Position = 0; contentSong.Hash = Util.SHA1Hash(memorySong); contentSong.Size = memorySong.Length; for (int i = 1; i <= oindex + 1; i++) { if (i == oindex) { tmd.Contents.Add(contentDta); } else if (i == oindex + 1) { tmd.Contents.Add(contentSong); } else { tmd.Contents.Add(new TmdContent() { Index = (ushort)i, ContentID = (uint)i, Size = 1, Type = 0x4001 }); } } tmd.Fakesign(); uint consoleid = GetConsoleID(path); progress.Progress(); dirpath = Path.Combine(Path.Combine(Path.Combine(Path.Combine(path, "private"), "wii"), "data"), "sZAE"); TemporaryStream binstream; DlcBin bin; if (consoleid != 0 && !File.Exists(Path.Combine(dirpath, "000.bin"))) { Directory.CreateDirectory(dirpath); binstream = new TemporaryStream(); binstream.Write(Properties.Resources.rawksd_000bin, 0, Properties.Resources.rawksd_000bin.Length); binstream.Position = 8; new EndianReader(binstream, Endianness.BigEndian).Write(consoleid); binstream.ClosePersist(); File.Move(binstream.Name, Path.Combine(dirpath, "000.bin")); binstream.Close(); } dirpath = Path.Combine(Path.Combine(Path.Combine(Path.Combine(path, "private"), "wii"), "data"), otitle); if (!Directory.Exists(dirpath)) { Directory.CreateDirectory(dirpath); } binstream = new TemporaryStream(); bin = new DlcBin(); bin.Bk.ConsoleID = consoleid; bin.TMD = tmd; bin.Content = tmd.Contents[oindex]; bin.Data = memoryDta; bin.Generate(); bin.Bk.ContentSize = bin.Bk.TotalSize = 0; bin.Bk.TitleID = 0x00010000535A4145UL; bin.Save(binstream); binstream.ClosePersist(); string dtabinpath = Path.Combine(dirpath, Util.Pad(oindex.ToString(), 3) + ".bin"); Util.Delete(dtabinpath); File.Move(binstream.Name, dtabinpath); binstream.Close(); binstream = new TemporaryStream(); bin = new DlcBin(); bin.Bk.ConsoleID = consoleid; bin.TMD = tmd; bin.Content = tmd.Contents[oindex + 1]; bin.Data = memorySong; bin.Generate(); bin.Bk.ContentSize = bin.Bk.TotalSize = 0; bin.Bk.TitleID = 0x00010000535A4145UL; bin.Save(binstream); binstream.ClosePersist(); string songbinpath = Path.Combine(dirpath, Util.Pad((oindex + 1).ToString(), 3) + ".bin"); Util.Delete(songbinpath); File.Move(binstream.Name, songbinpath); binstream.Close(); data.Mutex.WaitOne(); string mainbinpath = Path.Combine(dirpath, "000.bin"); if (!File.Exists(mainbinpath)) { binstream = new TemporaryStream(); bin = new DlcBin(); bin.Bk.ConsoleID = consoleid; bin.TMD = tmd; bin.Content = tmd.Contents[0]; bin.Data = new MemoryStream(Properties.Resources.rawksd_savebanner, false); bin.Generate(); bin.Bk.TitleID = 0x00010000535A4145UL; bin.Save(binstream); binstream.ClosePersist(); File.Move(binstream.Name, mainbinpath); binstream.Close(); } AddSongFromBins(data, song, dtabinpath, songbinpath, progress, true); SaveDTBCache(data); data.Mutex.ReleaseMutex(); cache.Dispose(); progress.Progress(); } progress.EndTask(); }