Example #1
0
        public override void Remux(IFormat format, FormatData data, FormatData destination, ProgressIndicator progress)
        {
            if (!(format is AudioFormatOgg))
            {
                throw new FormatException();
            }

            bool musttranscode = AudioFormatOgg.Instance.GetAudioStreams(data).Count > 1;

            if (musttranscode)               // Remuxing isn't possible with more than one audio stream
            {
                Platform.TranscodeOnly(format, data, AudioFormatMogg.Instance, destination, progress);
                return;
            }

            Util.StreamCopy(destination.AddStream(this, FormatName), AudioFormatOgg.Instance.GetFormatStream(data));

            CryptedMoggStream audio = new CryptedMoggStream(destination.AddStream(this, AudioName));

            audio.WriteHeader();
            Util.StreamCopy(audio, AudioFormatOgg.Instance.GetAudioStream(data));

            destination.CloseStream(this, AudioName);
            destination.CloseStream(this, FormatName);
        }
Example #2
0
        public static void Save(FormatData data, SongData song)
        {
            if (!FormatData.LocalSongCache || (data.PlatformData != null && data.PlatformData.Platform == PlatformLocalStorage.Instance))
            {
                CacheMutex.WaitOne();
                try {
                    Stream stream = data.AddStream("songdata");
                    song.Save(stream);
                    data.CloseStream(stream);
                } catch (Exception ex) {
                    CacheMutex.ReleaseMutex();
                    throw ex;
                }
                CacheMutex.ReleaseMutex();
            }
            SongData songdata = null;

            if (Cache.ContainsKey(data))
            {
                songdata = Cache[data];
            }
            if (FormatData.LocalSongCache && songdata != song)
            {
                songdata = song;
                songdata.PropertyChanged += new Action <SongData>(data.Song_PropertyChanged);
                Cache[data] = songdata;
            }
        }
Example #3
0
        public static SongData Load(FormatData data)
        {
            if (FormatData.LocalSongCache && Cache.ContainsKey(data))
            {
                return(Cache[data]);
            }
            CacheMutex.WaitOne();
            SongData song;

            try {
                Stream stream = data.GetStream("songdata");
                song = SongData.Create(stream);
                data.CloseStream(stream);
            } catch (Exception ex) {
                CacheMutex.ReleaseMutex();
                throw ex;
            }
            CacheMutex.ReleaseMutex();
            song.PropertyChanged += new Action <SongData>(data.Song_PropertyChanged);
            if (FormatData.LocalSongCache)
            {
                Cache[data] = song;
            }
            return(song);
        }
Example #4
0
        public override void Remux(IFormat format, FormatData data, FormatData destination, ProgressIndicator progress)
        {
            if (!(format is AudioFormatMogg))
            {
                throw new FormatException();
            }

            Stream stream = destination.AddStream(this, AudioName);

            Util.StreamCopy(stream, AudioFormatMogg.Instance.GetDecryptedAudioStream(data));
            destination.CloseStream(stream);

            stream = destination.AddStream(this, FormatName);
            Util.StreamCopy(stream, AudioFormatMogg.Instance.GetFormatStream(data));
            destination.CloseStream(stream);
        }
Example #5
0
        public override ChartFormat DecodeChart(FormatData data, ProgressIndicator progress)
        {
            if (!data.HasStream(this, ChartFile))
            {
                throw new FormatException();
            }

            Stream stream = data.GetStream(this, ChartFile);
            Midi   midi   = Midi.Create(Mid.Create(stream));

            if (data.Song.Data.GetValue <bool>("RBChartExpertPlus"))
            {
                Midi.Track track = midi.GetTrack("PART DRUMS");
                if (track != null)
                {
                    foreach (Midi.NoteEvent note in track.Notes)
                    {
                        if (note.Note == 95)
                        {
                            note.Note = 96;
                        }
                    }
                }
            }
            ChartFormat chart = ChartFormat.Create(midi);

            data.CloseStream(stream);
            return(chart);
        }
Example #6
0
        public override void EncodeChart(ChartFormat data, FormatData destination, ProgressIndicator progress)
        {
            Stream stream = destination.AddStream(this, ChartFile);

            data.Save(stream);
            destination.CloseStream(stream);
        }
Example #7
0
        public override ChartFormat DecodeChart(FormatData data, ProgressIndicator progress)
        {
            Stream stream = data.GetStream(this, ChartName);
            Chart  chart  = Chart.Create(stream);

            data.CloseStream(stream);
            return(new ChartFormat(chart.GetChart()));
        }
Example #8
0
        public override AudioFormat DecodeAudioFormat(FormatData data)
        {
            Stream      stream = data.GetStream(this, FormatName);
            AudioFormat format = AudioFormat.Create(stream);

            data.CloseStream(stream);
            return(format);
        }
        public override AudioFormat DecodeAudio(FormatData data, ProgressIndicator progress)
        {
            if (!data.HasStream(this, WadName) && !data.HasStream(this, DatName))
            {
                throw new FormatException();
            }

            AudioFormat format = new AudioFormat();

            format.Decoder = new MultiDecoder(RawkAudio.Decoder.BufferSize);

            Stream wad = data.GetStream(this, WadName);
            Stream dat = data.GetStream(this, DatName);

            DatWad audio = new DatWad(new EndianReader(dat, Endianness.BigEndian), wad);

            data.CloseStream(dat);

            foreach (DatWad.Node node in audio.Nodes)
            {
                string     name       = node.Filename.Substring(node.Filename.LastIndexOf('_') + 1).ToLower().Trim();
                Instrument instrument = Instrument.Ambient;
                if ("preview.wav".StartsWith(name))
                {
                    instrument = Instrument.Preview;
                }
                else if ("guitar.wav".StartsWith(name))
                {
                    instrument = Instrument.Guitar;
                }
                else if ("rhythm.wav".StartsWith(name))
                {
                    instrument = Instrument.Bass;
                }
                else if ("song.wav".StartsWith(name))
                {
                    instrument = Instrument.Ambient;
                }
                else
                {
                    continue;
                }

                IDecoder decoder = new RawkAudio.Decoder(node.Data, RawkAudio.Decoder.AudioFormat.FmodSoundBank);
                (format.Decoder as MultiDecoder).AddDecoder(decoder);

                for (int i = 0; i < decoder.Channels; i++)
                {
                    format.Mappings.Add(new AudioFormat.Mapping(0, 0, instrument));
                }
            }

            format.SetDisposeStreams(data, new Stream[] { wad, dat });

            format.AutoBalance();

            return(format);
        }
Example #10
0
 public void Create(FormatData data, Stream audio, AudioFormat format)
 {
     data.SetStream(this, AudioName, audio);
     if (format != null)
     {
         Stream formatstream = data.AddStream(this, FormatName);
         format.Save(formatstream);
         data.CloseStream(formatstream);
     }
 }
Example #11
0
        public void Create(FormatData data, Stream[] streams, AudioFormat format)
        {
            Stream formatstream = data.AddStream(this, FormatName);

            format.Save(formatstream);
            data.CloseStream(formatstream);

            for (int i = 0; i < streams.Length; i++)
            {
                data.SetStream(this, AudioName + (i == 0 ? string.Empty : ("." + i.ToString())), streams[i]);
            }
        }
Example #12
0
        public override AudioFormat DecodeAudioFormat(FormatData data)
        {
            Stream stream = GetFormatStream(data);

            if (stream == null)
            {
                return(HarmonixMetadata.GetAudioFormat(data.Song));
            }
            AudioFormat format = AudioFormat.Create(stream);

            data.CloseStream(stream);
            return(format);
        }
Example #13
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();
        }
Example #14
0
        public void SetDisposeStreams(FormatData data, IEnumerable <Stream> streams)
        {
            List <Stream> list = new List <Stream>(streams);

            SetDisposeCallback(delegate() {
                foreach (Stream stream in list)
                {
                    if (stream != null)
                    {
                        data.CloseStream(stream);
                    }
                }
            });
        }
Example #15
0
        public static void SaveSongItem(FormatData formatdata)
        {
            SongData song = formatdata.Song;

            byte[] data = song.Data.GetValue <byte[]>("NeversoftSongItem");
            if (data == null)
            {
                return;
            }

            Stream stream = formatdata.AddStream(Instance, "neversoftdata");

            stream.Write(data);
            formatdata.CloseStream(Instance, "neversoftdata");
            song.Data.SetValue("NeversoftSongItem", new byte[0]);
        }
Example #16
0
        public override ChartFormat DecodeChart(FormatData data, ProgressIndicator progress)
        {
            if (!data.HasStream(this, ChartName))
            {
                throw new FormatException();
            }

            Stream[] streams = GetChartStreams(data);

            ChartFormat format = ChartFormatGH5.Instance.DecodeChart(data, progress, streams);

            foreach (Stream stream in streams)
            {
                data.CloseStream(stream);
            }

            return(format);
        }
Example #17
0
 public virtual void SaveTo(FormatData data, FormatType type = FormatType.Unknown)
 {
     foreach (string name in Data)
     {
         if (type != FormatType.Unknown)
         {
             try {
                 int format = int.Parse(name.Split('.')[0]);
                 if (Platform.GetFormat(format).Type != type)
                 {
                     continue;
                 }
             } catch { }
         }
         Util.StreamCopy(data.AddStream(name), GetStream(name));
         data.CloseStream(name);
         CloseStream(name);
     }
 }
Example #18
0
        public static QbItemStruct GetSongItem(FormatData formatdata)
        {
            SongData song       = formatdata.Song;
            Stream   datastream = formatdata.GetStream(Instance, "neversoftdata");

            if (datastream == null || datastream.Length == 0)
            {
                SaveSongItem(formatdata);
                datastream = formatdata.GetStream(Instance, "neversoftdata");
            }
            QbItemBase item = new QbFile(datastream, GetSongItemType(song)).FindItem(QbKey.Create(song.Data.GetValue <uint>("NeversoftSongItemKey")), true);

            formatdata.CloseStream(datastream);
            if (item is QbItemArray)
            {
                item.Items[0].ItemQbKey = item.ItemQbKey;
                item = item.Items[0];
            }
            return(item as QbItemStruct);
        }
Example #19
0
        public override ChartFormat DecodeChart(FormatData data, ProgressIndicator progress)
        {
            if (!data.HasStream(this, ChartFile))
            {
                throw new FormatException();
            }

            Stream stream = data.GetStream(this, ChartFile);
            Midi   midi   = Midi.Create(Mid.Create(stream));

            data.CloseStream(stream);

            ChartFormat chart = new ChartFormat(NoteChart.Create(midi));

            DecodeLeftHandAnimations(chart.Chart, midi);
            ChartFormatGH2.DecodeDrums(chart.Chart, midi, true);
            ChartFormatGH2.DecodeOverdrive(chart.Chart);

            ImportMap.ImportChart(data.Song, chart.Chart);

            return(chart);
        }
Example #20
0
        public override ChartFormat DecodeChart(FormatData data, ProgressIndicator progress)
        {
            if (!data.HasStream(this, ChartFile))
            {
                throw new FormatException();
            }

            Stream stream = data.GetStream(this, ChartFile);
            Midi   midi   = Midi.Create(Mid.Create(stream));

            data.CloseStream(stream);

            DecodeCoop(midi, data.Song.Data.GetValue <bool>("GH2ChartCoop"));

            ChartFormat chart = new ChartFormat(NoteChart.Create(midi));

            DecodeDrums(chart.Chart, midi, false);
            DecodeOverdrive(chart.Chart);

            ImportMap.ImportChart(data.Song, chart.Chart);

            return(chart);
        }
Example #21
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();
        }
Example #22
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);
        }
Example #23
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 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();
        }