public override PlatformData Create(string path, Game game, ProgressIndicator progress)
        {
            PlatformData  data    = new PlatformData(this, game);
            DirectoryNode maindir = data.GetDirectoryStructure(path);

            List <DirectoryNode> dirs = new List <DirectoryNode>(maindir.Directories);

            dirs.Add(maindir);

            progress.NewTask(dirs.Count);
            foreach (DirectoryNode dir in dirs)
            {
                SongData song = new SongData(data);
                song.Name = dir.Name;
                try {
                    data.Session["songdir"] = dir;
                    AddSong(data, song, progress);
                    data.Session.Remove("songdir");
                } catch (Exception exception) {
                    Exceptions.Warning(exception, "Unable to parse the Frets on Fire song from " + song.Name);
                }
                progress.Progress();
            }
            progress.EndTask();

            return(data);
        }
        public override PlatformData Create(string path, Game game, ProgressIndicator progress)
        {
            PlatformData data = new PlatformData(this, game);

            DirectoryNode dir = data.GetDirectoryStructure(path);

            data.Game = Platform.DetermineGame(data);

            FileNode  tracklist = dir.Navigate("/Common/AUDIO/Audiotracks/TrackListing.xml") as FileNode;
            XmlReader reader    = XmlReader.Create(tracklist.Data);

            tracklist.Data.Close();
            XmlDocument doc = new XmlDocument();

            doc.Load(reader);

            var elements = doc.DocumentElement.GetElementsByTagName("Track");

            progress.NewTask(elements.Count);

            foreach (XmlElement element in elements)
            {
                SongData song = FreeStyleGamesMetadata.GetSongData(element);

                AddSong(data, song, progress);

                progress.Progress();
            }

            return(data);
        }
        public override PlatformData Create(string path, Game game, ProgressIndicator progress)
        {
            PlatformData data = new PlatformData(this, game);

            DirectoryNode dir = data.GetDirectoryStructure(path);

            data.Game = Platform.DetermineGame(data);

            FileNode qbpak = dir.Navigate("pak/qb.pak.ngc") as FileNode;

            if (qbpak == null)
            {
                Exceptions.Error("Couldn't find qb.pak.ngc on Guitar Hero 3 Wii disc.");
            }

            try {
                Pak          qb           = new Pak(new EndianReader(qbpak.Data, Endianness.BigEndian));
                FileNode     songlistfile = qb.Root.Find("songlist.qb.ngc", SearchOption.AllDirectories) as FileNode;
                FileNode     albumfile    = dir.Navigate("pak/album_covers/album_covers.pak.ngc", false, true) as FileNode;
                QbFile       songlist     = new QbFile(songlistfile.Data, PakFormat);
                QbItemStruct list         = songlist.FindItem(QbKey.Create(NeversoftMetadata.SonglistKeys[0]), true) as QbItemStruct;

                data.Session["rootdir"] = dir;
                data.Session["rootqb"]  = qb;

                if (albumfile != null)
                {
                    data.Session["albumpak"] = new Pak(new EndianReader(albumfile.Data, Endianness.BigEndian));
                }

                var items = list.Items;
                progress.NewTask(items.Count);
                foreach (QbItemStruct item in items)
                {
                    SongData song = NeversoftMetadata.GetSongData(data, item);

                    try {
                        AddSong(data, song, progress);
                    } catch (Exception exception) {
                        Exceptions.Warning(exception, "Unable to properly parse " + song.Name);
                    }

                    progress.Progress();
                }
                progress.EndTask();
            } catch (Exception exception) {
                Exceptions.Error(exception, "An error occurred while parsing the Guitar Hero 3 Wii disc.");
            }

            return(data);
        }
Exemple #4
0
        public static void Transcode(FormatType type, FormatData data, IList <IFormat> targets, FormatData destination, ProgressIndicator progress)
        {
            foreach (IFormat format in targets)
            {
                if (format.HasFormat(data))
                {
                    Transfer(format, data, destination, progress);
                    return;
                }
            }

            IList <IFormat> formats = FindTranscodePath(data.GetFormats(type), targets);

            if (formats.Count == 0)
            {
                throw new UnsupportedTranscodeException("Could not find a supported transcode path.");
            }

            if (formats.Count == 1)
            {
                if (formats[0].CanTransfer(data))
                {
                    Transfer(formats[0], data, destination, progress);
                    return;
                }
                else
                {
                    formats.Add(formats[0]);
                }
            }

            FormatData tempdata = null;

            if (formats.Count > 2)
            {
                tempdata = new TemporaryFormatData();
            }

            progress.NewTask(formats.Count - 1);

            for (int i = 1; i < formats.Count; i++)
            {
                FormatData dest = i < formats.Count - 1 ? tempdata : destination;
                Transcode(formats[i - 1], data, formats[i], dest, progress);
                data = dest;
                progress.Progress();
            }

            progress.EndTask();
        }
Exemple #5
0
        public override PlatformData Create(string path, Game game, ProgressIndicator progress)
        {
            PlatformData data = new PlatformData(this, game);

            DirectoryNode dir = data.GetDirectoryStructure(path);

            List <DirectoryNode> dirs = new List <DirectoryNode>();

            dirs.Add(dir);
            dirs.AddRange(dir.Directories);

            progress.NewTask(dirs.Count);

            foreach (DirectoryNode songdir in dirs)
            {
                data.Session["songdir"] = songdir;

                FileNode datafile    = songdir.Navigate("data", false, true) as FileNode;
                FileNode newdatafile = songdir.Navigate("songdata", false, true) as FileNode;
                if (datafile == null && newdatafile == null)
                {
                    Exceptions.Warning("Unable to find a custom in " + songdir.Filename);
                    continue;
                }

                try {
                    SongData song = null;
                    if (datafile != null)
                    {
                        song = HarmonixMetadata.GetSongData(data, DTB.Create(new EndianReader(datafile.Data, Endianness.LittleEndian)));
                        datafile.Data.Close();
                        AddSongOld(data, song, progress);
                    }
                    else
                    {
                        song = SongData.Create(newdatafile.Data);
                        newdatafile.Data.Close();
                        AddSongNew(data, song, progress);
                    }
                } catch (Exception exception) {
                    Exceptions.Error(exception, "Unable to open the custom from " + songdir.Filename);
                }

                progress.Progress();
            }
            progress.EndTask();

            return(data);
        }
        public static void TranscodePreview(IList <int> previewtimes, List <AudioFormat.Mapping> maps, IDecoder decoder, Stream stream, ProgressIndicator progress)
        {
            RawkAudio.Encoder encoder;
            if (maps != null && maps.Count(m => m.Instrument == Instrument.Preview) > 0)
            {
                decoder.Seek(0);
                List <ushort> masks = new List <ushort>();
                foreach (var m in maps)
                {
                    if (m.Instrument == Instrument.Preview)
                    {
                        masks.Add((ushort)(1 << maps.IndexOf(m)));
                    }
                }
                ushort[] mask = masks.ToArray();

                encoder = new RawkAudio.Encoder(stream, mask.Length, decoder.SampleRate, 28000);
                long samples = decoder.Samples;
                progress.NewTask("Transcoding Preview", samples);
                JaggedShortArray buffer = new JaggedShortArray(encoder.Channels, decoder.AudioBuffer.Rank2);
                while (samples > 0)
                {
                    int read = decoder.Read((int)Math.Min(samples, decoder.AudioBuffer.Rank2));
                    if (read <= 0)
                    {
                        break;
                    }

                    decoder.AudioBuffer.DownmixTo(buffer, mask, read);

                    encoder.Write(buffer, read);
                    samples -= read;
                    progress.Progress(read);
                }
                progress.EndTask();
            }
            else
            {
                long start = Math.Min(decoder.Samples, (long)previewtimes[0] * decoder.SampleRate / 1000);
                decoder.Seek(start);
                long duration = Math.Min(decoder.Samples - start, (long)(previewtimes[1] - previewtimes[0]) * decoder.SampleRate / 1000);
                encoder = new RawkAudio.Encoder(stream, 1, decoder.SampleRate);
                AudioFormat.Transcode(encoder, decoder, duration, progress);
            }
            encoder.Dispose();
        }
Exemple #7
0
        internal void EncodeOggAudio(AudioFormat data, FormatData destination, IFormat format, Stream stream, ProgressIndicator progress)
        {
            IDecoder decoder = data.Decoder;

            RawkAudio.Encoder encoder = new RawkAudio.Encoder(stream, decoder.Channels, decoder.SampleRate);

            AudioFormat.ProcessOffset(decoder, encoder, data.InitialOffset);

            progress.NewTask(1);

            AudioFormat.Transcode(encoder, decoder, progress);
            progress.Progress();

            encoder.Dispose();
            destination.CloseStream(format, AudioName);

            decoder.Dispose();

            data.Save(destination.AddStream(format, FormatName));
            destination.CloseStream(format, FormatName);

            progress.EndTask();
        }
        public override PlatformData Create(string path, Game game, ProgressIndicator progress)
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            PlatformData data = new PlatformData(this, game);

            data.Session["rootpath"] = path;

            DirectoryInfo[] dirs = new DirectoryInfo(path).GetDirectories();
            progress.NewTask(dirs.Length);
            foreach (DirectoryInfo dir in dirs)
            {
                progress.Progress();

                if (!File.Exists(Path.Combine(dir.FullName, "songdata")))
                {
                    continue;
                }

                try {
                    FormatData format = new FolderFormatData(data, dir.FullName);

                    if (format.Song != null)
                    {
                        data.AddSong(format);
                    }
                } catch (Exception exception) {
                    Exceptions.Warning(exception, "Unable to open the custom at " + dir.FullName);
                }
            }
            progress.EndTask();

            return(data);
        }
Exemple #9
0
        public static void Transcode(IEncoder encoder, IDecoder decoder, long samples, ProgressIndicator progress)
        {
            long downmix = decoder.Channels == encoder.Channels ? 0 : encoder.Channels;

            progress.NewTask("Transcoding Audio", samples);
            while (samples > 0)
            {
                int read = decoder.Read((int)Math.Min(samples, RawkAudio.Decoder.BufferSize));
                if (read <= 0)
                {
                    break;
                }

                if (downmix == 1)
                {
                    decoder.AudioBuffer.DownmixTo(decoder.AudioBuffer, new ushort[] { 0xFFFF }, read);
                }

                encoder.Write(decoder.AudioBuffer, read);
                samples -= read;
                progress.Progress(read);
            }
            progress.EndTask();
        }
Exemple #10
0
        public static void Transfer(IFormat format, FormatData data, FormatData destination, ProgressIndicator progress)
        {
            string[] streams = data.GetStreamNames();
            progress.NewTask(streams.Length);
            foreach (string fullname in streams)
            {
                if (fullname.StartsWith(format.ID + "."))
                {
                    string name = fullname.Split(new char[] { '.' }, 2)[1];

                    Stream ostream = destination.AddStream(format, name);
                    Stream istream = data.GetStream(format, name);

                    Util.StreamCopy(ostream, istream);

                    destination.CloseStream(ostream);
                    data.CloseStream(istream);

                    progress.Progress();
                }
            }

            progress.EndTask();
        }
Exemple #11
0
        public override PlatformData Create(string path, Game game, ProgressIndicator progress)
        {
            PlatformData data = new PlatformData(this, game);

            DirectoryNode dir = data.GetDirectoryStructure(path);

            data.Game = Platform.DetermineGame(data);

            try {
                FileNode qbpak = dir.Navigate("pak/qb.pak.ngc") as FileNode;
                if (qbpak == null)
                {
                    throw new FormatException("Couldn't find qb.pak on Guitar Hero Wii disc.");
                }

                FileNode qspak = dir.Navigate("pak/qs.pak.ngc") as FileNode;
                if (qspak == null)
                {
                    throw new FormatException("Couldn't find qs.pak on Guitar Hero Wii disc.");
                }

                Pak qs = new Pak(new EndianReader(qspak.Data, Endianness.BigEndian));

                StringList strings = new StringList();
                foreach (Pak.Node node in qs.Nodes)
                {
                    strings.ParseFromStream(node.Data);
                }

                Pak      qb           = new Pak(new EndianReader(qbpak.Data, Endianness.BigEndian));
                FileNode songlistfile = qb.FindFile(@"scripts\guitar\songlist.qb.ngc");
                if (songlistfile == null)
                {
                    songlistfile = qb.FindFile(@"scripts\guitar\songlist.qb");
                }

                if (songlistfile == null)
                {
                    throw new FormatException("Couldn't find the songlist on the Guitar Hero Wii disc pak.");
                }
                QbFile songlist = new QbFile(songlistfile.Data, PakFormat);

                data.Session["rootdir"] = dir;

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

                progress.NewTask(listkeys.Count);
                List <string> songsadded = new List <string>();
                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);

                        progress.Progress();

                        if (songsadded.Contains(song.ID))
                        {
                            continue;
                        }

                        try {
                            if (AddSong(data, song, progress))
                            {
                                songsadded.Add(song.ID);
                            }
                        } catch (Exception exception) {
                            Exceptions.Warning(exception, "Unable to properly parse " + song.Name);
                        }
                    }

                    progress.EndTask();
                    progress.Progress();
                }
                progress.EndTask();

                qbpak.Data.Close();
                qspak.Data.Close();
            } catch (Exception exception) {
                Exceptions.Error(exception, "An error occurred while parsing the Guitar Hero Wii disc.");
            }

            return(data);
        }
Exemple #12
0
        public override void EncodeAudio(AudioFormat audioformat, FormatData formatdata, ProgressIndicator progress)
        {
            progress.NewTask(20);

            Stream audio = formatdata.AddStream(this, AudioName);

            progress.SetNextWeight(1);
            List <AudioFormat.Mapping> oldmaps = audioformat.Mappings;

            ushort[] masks = PlatformRB2WiiCustomDLC.RemixAudioTracks(formatdata.Song, audioformat);

            progress.SetNextWeight(14);
            long samples           = audioformat.Decoder.Samples;
            CryptedMoggStream mogg = new CryptedMoggStream(audio);

            //mogg.WriteHeader(samples);
            mogg.WriteHeader();
            RawkAudio.Encoder encoder = new RawkAudio.Encoder(mogg, audioformat.Channels, audioformat.Decoder.SampleRate, 28000);
            progress.NewTask("Transcoding Audio", samples);
            JaggedShortArray buffer = new JaggedShortArray(encoder.Channels, audioformat.Decoder.AudioBuffer.Rank2);

            AudioFormat.ProcessOffset(audioformat.Decoder, encoder, audioformat.InitialOffset);
            while (samples > 0)
            {
                //int read = audioformat.Decoder.Read((int)Math.Min(samples, 0x4E20));
                //int read = audioformat.Decoder.Read((int)Math.Min(samples, 0x20));
                int read = audioformat.Decoder.Read((int)Math.Min(samples, buffer.Rank2));
                if (read <= 0)
                {
                    break;
                }

                audioformat.Decoder.AudioBuffer.DownmixTo(buffer, masks, read);

                encoder.Write(buffer, read);
                samples -= read;
                progress.Progress(read);
                //mogg.Update(read);
            }
            progress.EndTask();
            progress.Progress(14);
            encoder.Dispose();
            mogg.WriteEntries();
            formatdata.CloseStream(audio);

            progress.SetNextWeight(6);
            Stream preview = formatdata.AddStream(this, PreviewName);

            mogg = new CryptedMoggStream(preview);
            mogg.WriteHeader();
            PlatformRB2WiiCustomDLC.TranscodePreview(formatdata.Song.PreviewTimes, oldmaps, audioformat.Decoder != null ? audioformat.Decoder : new ZeroDecoder(1, 28000, 0x7FFFFFFFFFFFFFFF), mogg, progress);
            formatdata.CloseStream(preview);

            progress.EndTask();
            progress.Progress(6);

            Stream formatstream = formatdata.AddStream(this, FormatName);

            audioformat.Save(formatstream);
            formatdata.CloseStream(formatstream);
        }
Exemple #13
0
        public override PlatformData Create(string path, Game game, ProgressIndicator progress)
        {
            if (File.Exists(path))
            {
                if (String.Compare(Path.GetExtension(path), ".ark", true) == 0 || String.Compare(Path.GetExtension(path), ".hdr", true) == 0)
                {
                    path = Path.GetDirectoryName(path);
                }
            }

            PlatformData data = new PlatformData(this, game);

            data.Game = Platform.DetermineGame(data);

            Ark ark = data.GetHarmonixArk(path);

            DirectoryNode songdir = ark.Root.Find("songs", true) as DirectoryNode;

            if (songdir == null)
            {
                Exceptions.Error("This is not a Guitar Hero PS2 disc; the songs dir is missing from the ark.");
            }

            FileNode songsdtbfile = ark.Root.Navigate("config/gen/songs.dtb", false, true) as FileNode;

            if (songsdtbfile == null)
            {
                Exceptions.Error("Couldn't find songs.dtb; this is not a Guitar Hero PS2 disc.");
            }

            data.Session["songdir"] = songdir;

            try {
                List <SongsDTA> dtas      = new List <SongsDTA>();
                Stream          dtbstream = new MemoryStream((int)songsdtbfile.Size);
                CryptedDtbStream.DecryptOld(dtbstream, new EndianReader(songsdtbfile.Data, Endianness.LittleEndian), (int)songsdtbfile.Size);
                dtbstream.Position = 0;
                DTB.NodeTree dtb = DTB.Create(new EndianReader(dtbstream, Endianness.LittleEndian));
                progress.NewTask(dtb.Nodes.Count);
                foreach (DTB.Node node in dtb.Nodes)
                {
                    DTB.NodeTree tree = node as DTB.NodeTree;
                    if (tree == null || tree.Nodes[0].Type != 0x00000005 || songdir.Find((tree.Nodes[0] as DTB.NodeString).Text) == null)
                    {
                        progress.Progress();
                        continue;
                    }

                    SongsDTA dta = SongsDTA.Create(tree);
                    if (dtas.FirstOrDefault(d => d.BaseName == dta.BaseName) != null)
                    {
                        progress.Progress();
                        continue;                         // Don't import songs twice
                    }
                    dtas.Add(dta);

                    SongData song = HarmonixMetadata.GetSongData(data, tree);
                    try {
                        AddSong(data, song, progress);
                    } catch (Exception exception) {
                        Exceptions.Warning(exception, "Unable to properly parse " + song.Name);
                    }
                    progress.Progress();
                }
                progress.EndTask();
            } catch (Exception exception) {
                Exceptions.Error(exception, "An error occurred while parsing the Guitar Hero PS2 disc.");
            }

            return(data);
        }
        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();
        }
        public override void SaveSong(PlatformData data, FormatData formatdata, ProgressIndicator progress)
        {
            string path = data.Session["path"] as string;

            SongData song = formatdata.Song;

            progress.NewTask(8);

            int    i;
            string songpath = null;

            for (i = 0; i < 0x1000; i++)
            {
                songpath = Path.Combine(path, song.ID + (i == 0 ? "" : i.ToString()));
                if (!Directory.Exists(songpath))
                {
                    break;
                }
            }
            Directory.CreateDirectory(songpath);
            AudioFormat audio = (formatdata.GetFormat(FormatType.Audio) as IAudioFormat).DecodeAudio(formatdata, progress);

            progress.Progress();
            ChartFormat chart = (formatdata.GetFormat(FormatType.Chart) as IChartFormat).DecodeChart(formatdata, progress);

            progress.Progress();

            Stream chartstream = new FileStream(Path.Combine(songpath, "notes.mid"), FileMode.Create, FileAccess.Write);

            chart.Save(chartstream);
            chartstream.Close();

            Ini ini = new Ini();

            ini.SetValue("song", "name", song.Name);
            ini.SetValue("song", "artist", song.Artist);
            ini.SetValue("song", "album", song.Album);
            ini.SetValue("song", "genre", song.Genre);
            ini.SetValue("song", "year", song.Year.ToString());
            ini.SetValue("song", "diff_band", ImportMap.GetBaseTier(Instrument.Ambient, song.Difficulty[Instrument.Ambient]).ToString());
            ini.SetValue("song", "diff_guitar", ImportMap.GetBaseTier(Instrument.Guitar, song.Difficulty[Instrument.Guitar]).ToString());
            ini.SetValue("song", "diff_bass", ImportMap.GetBaseTier(Instrument.Bass, song.Difficulty[Instrument.Bass]).ToString());
            ini.SetValue("song", "diff_drums", ImportMap.GetBaseTier(Instrument.Drums, song.Difficulty[Instrument.Drums]).ToString());
            Stream inistream = new FileStream(Path.Combine(songpath, "song.ini"), FileMode.Create, FileAccess.Write);

            ini.Save(inistream);
            inistream.Close();

            if (song.AlbumArt != null)
            {
                Stream albumart = new FileStream(Path.Combine(songpath, "album.png"), FileMode.Create, FileAccess.Write);
                song.AlbumArt.Save(albumart, ImageFormat.Png);
                albumart.Close();
            }

            JaggedShortArray encoderdata;

            var instruments = audio.Mappings.GroupBy(m => m.Instrument == Instrument.Vocals ? Instrument.Ambient : m.Instrument);

            encoderdata = new JaggedShortArray(2, RawkAudio.Decoder.BufferSize);
            int count = instruments.Count();

            Stream[]   streams  = new Stream[count];
            IEncoder[] encoders = new IEncoder[count];
            ushort[][] masks    = new ushort[count][];

            i = 0;
            foreach (var item in instruments)
            {
                string filename = null;
                switch (item.Key)
                {
                case Instrument.Guitar:
                    filename = "guitar.ogg";
                    break;

                case Instrument.Bass:
                    filename = "rhythm.ogg";
                    break;

                case Instrument.Drums:
                    filename = "drums.ogg";
                    break;

                case Instrument.Ambient:
                    filename = "song.ogg";
                    break;

                case Instrument.Preview:
                    filename = "preview.ogg";
                    break;
                }

                streams[i] = new FileStream(Path.Combine(songpath, filename), FileMode.Create, FileAccess.Write);
                masks[i]   = new ushort[2];

                foreach (var map in item)
                {
                    int index = audio.Mappings.IndexOf(map);
                    if (map.Balance <= 0)
                    {
                        masks[i][0] |= (ushort)(1 << index);
                    }
                    if (map.Balance >= 0)
                    {
                        masks[i][1] |= (ushort)(1 << index);
                    }
                }

                encoders[i] = new RawkAudio.Encoder(streams[i], 2, audio.Decoder.SampleRate, 44100);

                i++;
            }

            if (audio.InitialOffset > 0)
            {
                AudioFormat.ProcessOffset(audio.Decoder, encoders[0], audio.InitialOffset);
            }
            else
            {
                for (i = 0; i < encoders.Length; i++)
                {
                    AudioFormat.ProcessOffset(audio.Decoder, encoders[i], audio.InitialOffset);
                }
            }

            long samples = audio.Decoder.Samples;

            progress.NewTask("Transcoding Audio", samples, 6);
            while (samples > 0)
            {
                int read = audio.Decoder.Read();
                if (read <= 0)
                {
                    break;
                }

                // TODO: Apply volumes to each channel
                for (i = 0; i < count; i++)
                {
                    audio.Decoder.AudioBuffer.DownmixTo(encoderdata, masks[i], read, false);
                    encoders[i].Write(encoderdata, read);
                }

                samples -= read;
                progress.Progress(read);
            }

            for (i = 0; i < count; i++)
            {
                encoders[i].Dispose();
                streams[i].Close();
            }
            progress.EndTask();
            progress.Progress(6);
            progress.EndTask();
        }
        public override PlatformData Create(string path, Game game, ProgressIndicator progress)
        {
            progress.NewTask(10);
            progress.SetNextWeight(9);

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            PlatformData data = new PlatformData(this, game);

            data.Session["maindirpath"] = path;

            string customdir = Path.Combine(path, "rawk/rb2/customs");

            if (Directory.Exists(customdir))
            {
                string       dtapath = Path.Combine(customdir, "data");
                DTB.NodeTree dtb     = null;
                if (File.Exists(dtapath))
                {
                    Stream dtafile = new FileStream(dtapath, FileMode.Open, FileAccess.Read, FileShare.Read);
                    try {
                        dtb = DTB.Create(new EndianReader(dtafile, Endianness.LittleEndian));
                    } catch (Exception exception) {
                        Exceptions.Warning(exception, "The rawk/rb2/customs/data cache DTB is corrupt.");
                    }
                    dtafile.Close();
                }

                if (dtb != null)
                {
                    progress.NewTask(dtb.Nodes.Count);
                    foreach (DTB.NodeTree node in dtb.Nodes)
                    {
                        try {
                            AddSongFromDTB(path, data, node, progress);
                        } catch (Exception exception) {
                            Exceptions.Warning(exception, "Could not import RawkSD custom from data cache.");
                        }
                        progress.Progress();
                    }
                    progress.EndTask();
                }
                else
                {
                    string[] dirs = Directory.GetDirectories(customdir);
                    progress.NewTask(dirs.Length);
                    foreach (string folder in dirs)
                    {
                        try {
                            dtapath = Path.Combine(folder, "data");
                            if (File.Exists(dtapath))
                            {
                                dtb = null;
                                Stream dtafile = new FileStream(dtapath, FileMode.Open, FileAccess.Read, FileShare.Read);
                                try {
                                    dtb = DTB.Create(new EndianReader(dtafile, Endianness.LittleEndian));
                                } catch (Exception exception) {
                                    Exceptions.Warning(exception, "The data file for \"" + folder + "\" is corrupt.");
                                }
                                dtafile.Close();

                                if (dtb != null)
                                {
                                    AddSongFromDTB(path, data, dtb, progress);
                                }
                            }
                        } catch (Exception exception) {
                            Exceptions.Warning(exception, "Could not import RawkSD custom from " + folder);
                        }
                        progress.Progress();
                    }
                    progress.EndTask();
                }
                progress.Progress(9);
            }

            RefreshUnusedContent(data);
            progress.Progress();
            progress.EndTask();

            return(data);
        }
Exemple #17
0
        public override ChartFormat DecodeChart(FormatData data, ProgressIndicator progress)
        {
            if (!data.HasStream(this, ChartName) || !data.HasStream(this, SectionsName))
            {
                throw new FormatException();
            }

            progress.NewTask(6 + 8);

            Stream chartstream   = data.GetStream(this, ChartName);
            Stream sectionstream = data.GetStream(this, SectionsName);

            PakFormat format     = NeversoftMetadata.GetSongItemType(data.Song);
            SongData  song       = NeversoftMetadata.GetSongData(data.PlatformData, NeversoftMetadata.GetSongItem(data));
            Pak       chartpak   = new Pak(new EndianReader(chartstream, Endianness.BigEndian));     // TODO: Endianness based on format?
            FileNode  chartfile  = chartpak.Root.Find(song.ID + ".mid.qb.ngc", SearchOption.AllDirectories, true) as FileNode;
            QbFile    qbsections = new QbFile(sectionstream, format);
            QbFile    qbchart    = new QbFile(chartfile.Data, format);

            NoteChart chart = new NoteChart();

            chart.PartGuitar = new NoteChart.Guitar(chart);
            chart.PartBass   = new NoteChart.Bass(chart);
            chart.Events     = new NoteChart.EventsTrack(chart);
            chart.Venue      = new NoteChart.VenueTrack(chart);
            chart.Beat       = new NoteChart.BeatTrack(chart);

            progress.Progress();

            DecodeChartFretbars(song, qbchart, chart);

            progress.Progress();

            DecodeChartMarkers(song, qbsections, qbchart, chart);

            progress.Progress();

            for (NoteChart.TrackType track = NoteChart.TrackType.Guitar; track <= NoteChart.TrackType.Bass; track++)
            {
                for (NoteChart.Difficulty difficulty = NoteChart.Difficulty.Easy; difficulty <= NoteChart.Difficulty.Expert; difficulty++)
                {
                    DecodeChartNotes(data, song, qbchart, chart, track, difficulty, data.Song.Data.GetValue <bool>("GH3ChartCoop"));
                    progress.Progress();
                }
            }

            progress.Progress();

            DecodeChartDrums(song, qbchart, chart);

            progress.Progress();

            DecodeChartVenue(song, qbchart, chart);

            ImportMap.ImportChart(data.Song, chart);

            progress.Progress();

            data.CloseStream(chartstream);
            data.CloseStream(sectionstream);

            progress.EndTask();

            return(new ChartFormat(chart));
        }
        public override PlatformData Create(string path, Game game, ProgressIndicator progress)
        {
            PlatformData data = new PlatformData(this, game);

            Ark ark = data.GetHarmonixArk(path);

            data.Game = Platform.DetermineGame(data);

            if (data.Game == Game.RockBand2 || data.Game == Game.RockBandBeatles)
            {
                Exceptions.Error("Unable to parse song list from Rock Band Wii disc.");
            }

            data.Session["songdir"] = ark.Root;

            string[] songdirs = new string[] { "songs", "songs_regional/na", "songs_regional/eu" };
            progress.NewTask(songdirs.Length);
            foreach (string songdirname in songdirs)
            {
                DirectoryNode songdir = ark.Root.Navigate(songdirname) as DirectoryNode;
                if (songdir == null)
                {
                    continue;
                }

                FileNode songsdtbfile = songdir.Navigate("gen/songs.dtb") as FileNode;
                if (songsdtbfile == null)
                {
                    continue;
                }

                try {
                    List <SongsDTA> dtas = new List <SongsDTA>();
                    DTB.NodeTree    dtb  = DTB.Create(new EndianReader(new CryptedDtbStream(new EndianReader(songsdtbfile.Data, Endianness.LittleEndian)), Endianness.LittleEndian));
                    progress.NewTask(dtb.Nodes.Count);
                    foreach (DTB.Node node in dtb.Nodes)
                    {
                        DTB.NodeTree tree = node as DTB.NodeTree;
                        if (tree == null || tree.Nodes[0].Type != 0x00000005 || songdir.Find((tree.Nodes[0] as DTB.NodeString).Text) == null)
                        {
                            progress.Progress();
                            continue;
                        }

                        SongsDTA dta = SongsDTA.Create(tree);
                        if (dtas.Find(d => d.BaseName == dta.BaseName) != null)
                        {
                            progress.Progress();
                            continue;                             // Don't import songs twice
                        }

                        dtas.Add(dta);

                        try {
                            SongData song = HarmonixMetadata.GetSongData(data, tree);

                            AddSong(data, song, progress);
                        } catch (Exception exception) {
                            Exceptions.Warning(exception, "Could not import " + dta.Name + " from the Rock Band Wii disc.");
                        }

                        progress.Progress();
                    }
                } catch (Exception exception) {
                    Exceptions.Warning(exception, "Unable to parse song list from Rock Band Wii disc: " + songdirname);
                }
                progress.EndTask();
                progress.Progress();
            }

            progress.EndTask();

            return(data);
        }
Exemple #19
0
        public ChartFormat DecodeChart(FormatData data, ProgressIndicator progress, params Stream[] chartstreams)
        {
            progress.NewTask(5 + 12);

            PakFormat format = NeversoftMetadata.GetSongItemType(data.Song);
            SongData  song   = NeversoftMetadata.GetSongData(data.PlatformData, NeversoftMetadata.GetSongItem(data));

            List <Pak> chartpaks = new List <Pak>();

            foreach (Stream stream in chartstreams)
            {
                chartpaks.Add(new Pak(new EndianReader(stream, Endianness.BigEndian)));                 // TODO: Endianness based on format?
            }

            FileNode chartfile = null;

            foreach (Pak pak in chartpaks)
            {
                chartfile = pak.FindFile(song.ID + ".mid.qb.ngc") ?? chartfile;
                chartfile = pak.FindFile(song.ID + ".mid.qb") ?? chartfile;
            }
            if (chartfile == null)
            {
                foreach (Pak pak in chartpaks)
                {
                    chartfile = chartfile ?? pak.FindFileType(0xa7f505c4);
                }
            }
            QbFile qbchart = null;

            if (chartfile != null)
            {
                qbchart = new QbFile(chartfile.Data, format);
            }

            StringList strings = new StringList();

            foreach (Pak pak in chartpaks)
            {
                foreach (Pak.Node n in pak.Nodes)
                {
                    if (!n.Filename.HasValue())
                    {
                        strings.ParseFromStream(n.Data);
                    }
                }
            }

            QbFile   qbsections    = null;
            FileNode qbsectionfile = null;

            foreach (Pak pak in chartpaks)
            {
                qbsectionfile = pak.FindFile(song.ID + ".mid_text.qb.ngc") as FileNode ?? qbsectionfile;
                qbsectionfile = pak.FindFile(song.ID + ".mid_text.qb") as FileNode ?? qbsectionfile;
            }
            if (qbsectionfile != null)
            {
                qbsections = new QbFile(qbsectionfile.Data, format);
            }

            Notes    notes     = null;
            FileNode notesfile = null;

            foreach (Pak pak in chartpaks)
            {
                notesfile = notesfile ?? pak.FindFileType(0xa9d5bc8f);
                notesfile = pak.FindFile(song.ID + ".note.ngc") as FileNode ?? notesfile;
                notesfile = pak.FindFile(song.ID + ".note") as FileNode ?? notesfile;
            }
            if (notesfile == null)
            {
                foreach (Pak pak in chartpaks)
                {
                    notesfile = pak.FindFileType(0xa9d5bc8f) ?? notesfile;
                }
            }
            if (notesfile != null)
            {
                notesfile.Data.Position = 0;
                notes = Notes.Create(new EndianReader(notesfile.Data, Endianness.BigEndian));
            }

            NoteChart chart = new NoteChart();

            chart.PartGuitar = new NoteChart.Guitar(chart);
            chart.PartBass   = new NoteChart.Bass(chart);
            chart.PartDrums  = new NoteChart.Drums(chart);
            chart.PartVocals = new NoteChart.Vocals(chart);
            chart.Events     = new NoteChart.EventsTrack(chart);
            chart.Venue      = new NoteChart.VenueTrack(chart);
            chart.Beat       = new NoteChart.BeatTrack(chart);

            bool   gh4v2      = NeversoftMetadata.IsGuitarHero4(data.PlatformData.Game) && data.PlatformData.Game != Game.GuitarHeroWorldTour;
            string drumconfig = gh4v2 ? "drums3" : "drums2";

            chart.PartDrums.Mixing.Add(new Pair <NoteChart.Point, Pair <NoteChart.Difficulty, string> >(new NoteChart.Point(0), new Pair <NoteChart.Difficulty, string>(NoteChart.Difficulty.Easy, drumconfig + "easy")));
            chart.PartDrums.Mixing.Add(new Pair <NoteChart.Point, Pair <NoteChart.Difficulty, string> >(new NoteChart.Point(0), new Pair <NoteChart.Difficulty, string>(NoteChart.Difficulty.Medium, drumconfig)));
            chart.PartDrums.Mixing.Add(new Pair <NoteChart.Point, Pair <NoteChart.Difficulty, string> >(new NoteChart.Point(0), new Pair <NoteChart.Difficulty, string>(NoteChart.Difficulty.Hard, drumconfig)));
            chart.PartDrums.Mixing.Add(new Pair <NoteChart.Point, Pair <NoteChart.Difficulty, string> >(new NoteChart.Point(0), new Pair <NoteChart.Difficulty, string>(NoteChart.Difficulty.Expert, drumconfig)));

            progress.Progress();

            DecodeChartFretbars(song, qbchart, notes, chart);

            progress.Progress();

            DecodeChartSections(song, qbchart, strings, qbsections, notes, chart);

            progress.Progress();

            for (NoteChart.TrackType track = NoteChart.TrackType.Guitar; track <= NoteChart.TrackType.Drums;)
            {
                for (NoteChart.Difficulty difficulty = NoteChart.Difficulty.Easy; difficulty <= NoteChart.Difficulty.Expert; difficulty++)
                {
                    DecodeChartNotes(song, qbchart, notes, chart, track, difficulty);
                    progress.Progress();
                }
                switch (track)
                {
                case NoteChart.TrackType.Guitar: track = NoteChart.TrackType.Bass; break;

                case NoteChart.TrackType.Bass: track = NoteChart.TrackType.Drums; break;

                case NoteChart.TrackType.Drums: track = NoteChart.TrackType.Events; break;
                }
            }

            // Automatic Drum Fills - 1-measure fills every 4 measures, if there's no overdrive overlap
            FillSections(chart, 1, 4, 3, chart.PartDrums.DrumFills, chart.PartDrums.Overdrive);

            progress.Progress();

            if (DecodeChartVocals(song, qbchart, strings, notes, chart))
            {
                DecodeChartVocalPhrases(song, qbchart, notes, chart);
            }

            ImportMap.ImportChart(data.Song, chart);

            progress.Progress();

            progress.EndTask();

            return(new ChartFormat(chart));
        }
        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);
        }