Serialize() 공개 메소드

public Serialize ( Stream stream ) : void
stream Stream
리턴 void
        /// <summary>
        /// Regenerates the aggregategraph file
        /// </summary>
        private static void UpdateAggegrateGraph(string songDirectory, Platform targetPlatform, DLCPackageData info)
        {
            var dlcName = info.Name.ToLower();
            var aggregateGraphFileName = Path.Combine(songDirectory, String.Format("{0}_aggregategraph.nt", dlcName));
            var aggregateGraph         = new AggregateGraph2014.AggregateGraph2014(info, targetPlatform);

            using (var fs = new FileStream(aggregateGraphFileName, FileMode.Create))
                using (var aggregateGraphStream = new MemoryStream())
                {
                    aggregateGraph.Serialize(aggregateGraphStream);
                    aggregateGraphStream.Flush();
                    aggregateGraphStream.Seek(0, SeekOrigin.Begin);
                    aggregateGraphStream.CopyTo(fs);
                }
        }
예제 #2
0
        public static string DoLikeSongPack(string srcPath, string appId = "248750")
        {
            // create SongPack directory structure
            var dlcName              = Path.GetFileName(srcPath).ToLower();
            var songPackDir          = Path.Combine(Path.GetTempPath(), String.Format("{0}_songpack_p_Pc", dlcName));
            var audioWindowDir       = Path.Combine(songPackDir, "audio", "windows");
            var flatmodelsRsDir      = Path.Combine(songPackDir, "flatmodels", "rs");
            var gamexblocksNsongsDir = Path.Combine(songPackDir, "gamexblocks", "nsongs");
            var gfxassetsAlbumArtDir = Path.Combine(songPackDir, "gfxassets", "album_art");
            var manifestSongsDir     = Path.Combine(songPackDir, "manifests", String.Format("songs_dlc_{0}", dlcName));
            var songsArrDir          = Path.Combine(songPackDir, "songs", "arr");
            var binGenericDir        = Path.Combine(songPackDir, "songs", "bin", "generic");

            if (Directory.Exists(songPackDir))
            {
                IOExtension.DeleteDirectory(songPackDir);
            }

            Directory.CreateDirectory(songPackDir);
            Directory.CreateDirectory(audioWindowDir);
            Directory.CreateDirectory(flatmodelsRsDir);
            Directory.CreateDirectory(gamexblocksNsongsDir);
            Directory.CreateDirectory(gfxassetsAlbumArtDir);
            Directory.CreateDirectory(manifestSongsDir);
            Directory.CreateDirectory(songsArrDir);
            Directory.CreateDirectory(binGenericDir);

            // populate SongPack temporary directory
            var audioWemFiles = Directory.EnumerateFiles(srcPath, "*.wem", SearchOption.AllDirectories).ToArray();

            foreach (var wem in audioWemFiles)
            {
                File.Copy(wem, Path.Combine(audioWindowDir, Path.GetFileName(wem)));
            }

            var audioBnkFiles = Directory.EnumerateFiles(srcPath, "*.bnk", SearchOption.AllDirectories).ToArray();

            foreach (var bnk in audioBnkFiles)
            {
                File.Copy(bnk, Path.Combine(audioWindowDir, Path.GetFileName(bnk)));
            }

            var xblockFiles = Directory.EnumerateFiles(srcPath, "*.xblock", SearchOption.AllDirectories).ToArray();

            foreach (var xblock in xblockFiles)
            {
                File.Copy(xblock, Path.Combine(gamexblocksNsongsDir, Path.GetFileName(xblock)));
            }

            var albumArtFiles = Directory.EnumerateFiles(srcPath, "*.dds", SearchOption.AllDirectories).ToArray();

            foreach (var albumArt in albumArtFiles)
            {
                File.Copy(albumArt, Path.Combine(gfxassetsAlbumArtDir, Path.GetFileName(albumArt)));
            }

            var jsonFiles = Directory.EnumerateFiles(srcPath, "*.json", SearchOption.AllDirectories).ToArray();

            foreach (var json in jsonFiles)
            {
                File.Copy(json, Path.Combine(manifestSongsDir, Path.GetFileName(json)));
            }

            var hsanFiles = Directory.EnumerateFiles(srcPath, "*.hsan", SearchOption.AllDirectories).ToArray();

            foreach (var hsan in hsanFiles)
            {
                File.Copy(hsan, Path.Combine(manifestSongsDir, Path.GetFileName(hsan)));
            }

            var sngFiles = Directory.EnumerateFiles(srcPath, "*.sng", SearchOption.AllDirectories).ToArray();

            foreach (var sng in sngFiles)
            {
                File.Copy(sng, Path.Combine(binGenericDir, Path.GetFileName(sng)));
            }

            // declare variables one time for use in DDC generation
            DDCSettings.Instance.LoadConfigXml();
            var phraseLen = DDCSettings.Instance.PhraseLen;
            // removeSus may be depricated in latest DDC but left here for comptiblity
            var removeSus = DDCSettings.Instance.RemoveSus;
            var rampPath  = DDCSettings.Instance.RampPath;
            var cfgPath   = DDCSettings.Instance.CfgPath;

            // generate SongPack comment
            var spComment = "(Remastered by SongPack Maker)";
            var addDD     = false;

            if (ConfigRepository.Instance().GetBoolean("ddc_autogen"))
            {
                addDD      = true;
                spComment += " " + "(DDC by SongPack Maker)";
            }

            var xmlFiles = Directory.EnumerateFiles(srcPath, "*.xml", SearchOption.AllDirectories).ToArray();

            foreach (var xml in xmlFiles)
            {
                // completely skip dlc.xml template files
                if (xml.EndsWith("_RS2014.dlc.xml"))
                {
                    continue;
                }

                var xmlSongPack = Path.Combine(songsArrDir, Path.GetFileName(xml));
                File.Copy(xml, xmlSongPack);

                // skip vocal and showlight xml files
                if (xml.EndsWith("_vocals.xml") || xml.EndsWith("_showlights.xml"))
                {
                    continue;
                }

                // add DDC to xml arrangement
                if (addDD)
                {
                    // check if arrangment has pre existing DD and do not overwrite
                    var songXml = Song2014.LoadFromFile(xml);
                    var mf      = new ManifestFunctions(GameVersion.RS2014);
                    if (mf.GetMaxDifficulty(songXml) == 0)
                    {
                        var consoleOutput = String.Empty;
                        // apply DD to xml arrangments... 0 = Ends normally with no error
                        var result = DDCreator.ApplyDD(xmlSongPack, phraseLen, removeSus, rampPath, cfgPath, out consoleOutput, true);
                        if (result == 1)
                        {
                            Debug.WriteLine(String.Format("Arrangement file '{0}' => {1}", Path.GetFileNameWithoutExtension(xml), "DDC ended with system error " + consoleOutput));
                        }
                        else if (result == 2)
                        {
                            Debug.WriteLine(String.Format("Arrangement file '{0}' => {1}", Path.GetFileNameWithoutExtension(xml), "DDC ended with application error " + consoleOutput));
                        }
                    }
                }
            }

            // generate new Aggregate Graph
            var aggGraphPack = new AggregateGraph2014();

            aggGraphPack.JsonDB        = new List <GraphItem>();
            aggGraphPack.HsonDB        = new List <GraphItem>(); // used for consoles ONLY
            aggGraphPack.HsanDB        = new GraphItem();
            aggGraphPack.MusicgameSong = new List <GraphItemLLID>();
            aggGraphPack.SongXml       = new List <GraphItemLLID>();
            aggGraphPack.ShowlightXml  = new List <GraphItemLLID>();
            aggGraphPack.ImageArt      = new List <GraphItemLLID>();
            aggGraphPack.Soundbank     = new List <GraphItemLLID>();
            aggGraphPack.GameXblock    = new List <GraphItem>();

            // fix aggregate graph entries, reusing existing Persistent ID
            var currentPlatform     = new Platform(GamePlatform.Pc, GameVersion.RS2014);
            var aggregateGraphFiles = Directory.EnumerateFiles(srcPath, "*.nt", SearchOption.AllDirectories).ToArray();

            foreach (var aggGraph in aggregateGraphFiles)
            {
                var agg = LoadFromFile(aggGraph);

                foreach (var json in agg.JsonDB)
                {
                    json.Canonical        = String.Format(CANONICAL_MANIFEST_PC, dlcName);
                    json.RelPathDirectory = json.Canonical;
                    json.Tag = new List <string>();
                    json.Tag.Add(TagValue.Database.GetDescription());
                    json.Tag.Add(TagValue.JsonDB.GetDescription());
                    json.UUID        = IdGenerator.Guid();
                    json.RelPathFile = String.Format("{0}.json", json.Name);
                }

                aggGraphPack.JsonDB.AddRange(agg.JsonDB);
                aggGraphPack.MusicgameSong.AddRange(agg.MusicgameSong);
                aggGraphPack.SongXml.AddRange(agg.SongXml);
                aggGraphPack.ShowlightXml.AddRange(agg.ShowlightXml);
                aggGraphPack.ImageArt.AddRange(agg.ImageArt);
                aggGraphPack.Soundbank.AddRange(agg.Soundbank);

                aggGraphPack.GameXblock.AddRange(agg.GameXblock);
            }

            // create a single hsanDB entry
            aggGraphPack.HsanDB.Name             = String.Format("songs_dlc_{0}", dlcName);
            aggGraphPack.HsanDB.Canonical        = String.Format(CANONICAL_MANIFEST_PC, dlcName);
            aggGraphPack.HsanDB.RelPathDirectory = aggGraphPack.HsanDB.Canonical;
            aggGraphPack.HsanDB.Tag = new List <string>();
            aggGraphPack.HsanDB.Tag.Add(TagValue.Database.GetDescription());
            aggGraphPack.HsanDB.Tag.Add(TagValue.HsanDB.GetDescription());
            aggGraphPack.HsanDB.UUID        = IdGenerator.Guid();
            aggGraphPack.HsanDB.RelPathFile = String.Format("{0}.hsan", aggGraphPack.HsanDB.Name);

            var aggregateGraphFileName = Path.Combine(songPackDir, String.Format("{0}_aggregategraph.nt", dlcName));

            using (var fs = new FileStream(aggregateGraphFileName, FileMode.Create))
                using (var ms = new MemoryStream())
                {
                    aggGraphPack.Serialize(ms);
                    ms.Flush();
                    ms.Seek(0, SeekOrigin.Begin);
                    ms.CopyTo(fs);
                }

            MergeHsanFiles(songPackDir, dlcName, manifestSongsDir);

            var appIdFile = Path.Combine(songPackDir, "appid.appid");

            File.WriteAllText(appIdFile, appId);

            var toolkitVersionFile = Path.Combine(songPackDir, "toolkit.version");

            using (var fs = new FileStream(toolkitVersionFile, FileMode.Create))
                using (var ms = new MemoryStream())
                {
                    DLCPackageCreator.GenerateToolkitVersion(ms, packageVersion: "SongPack Maker v1.2", packageComment: spComment);
                    ms.Flush();
                    ms.Seek(0, SeekOrigin.Begin);
                    ms.CopyTo(fs);
                }

            var rootFlatFile = Path.Combine(flatmodelsRsDir, "rsenumerable_root.flat");

            using (var fs = new FileStream(rootFlatFile, FileMode.Create))
                using (var ms = new MemoryStream(Resources.rsenumerable_root))
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    ms.CopyTo(fs);
                }

            var songFlatFile = Path.Combine(flatmodelsRsDir, "rsenumerable_song.flat");

            using (var fs = new FileStream(songFlatFile, FileMode.Create))
                using (var ms = new MemoryStream(Resources.rsenumerable_song))
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    ms.CopyTo(fs);
                }

            return(songPackDir);
        }
        private static void GenerateRS2014SongPsarc(Stream output, DLCPackageData info, Platform platform, int pnum = -1)
        {
            // TODO: Benchmark processes and optimize speed
            dlcName = info.Name.ToLower();
            packPsarc = new PSARC.PSARC();

            // Stream objects
            Stream soundStream = null,
                   soundPreviewStream = null,
                   rsenumerableRootStream = null,
                   rsenumerableSongStream = null;

            try
            {
                // ALBUM ART
                var ddsfiles = info.ArtFiles;

                if (ddsfiles == null)
                {
                    string albumArtPath;
                    if (File.Exists(info.AlbumArtPath))
                    {
                        albumArtPath = info.AlbumArtPath;
                    }
                    else
                    {
                        using (var albumArtStream = new MemoryStream(Resources.albumart2014_256))
                        {
                            albumArtPath = GeneralExtensions.GetTempFileName(".dds");
                            albumArtStream.WriteFile(albumArtPath);
                            TMPFILES_ART.Add(albumArtPath);
                        }
                    }

                    ddsfiles = new List<DDSConvertedFile>();
                    ddsfiles.Add(new DDSConvertedFile() { sizeX = 64, sizeY = 64, sourceFile = albumArtPath, destinationFile = GeneralExtensions.GetTempFileName(".dds") });
                    ddsfiles.Add(new DDSConvertedFile() { sizeX = 128, sizeY = 128, sourceFile = albumArtPath, destinationFile = GeneralExtensions.GetTempFileName(".dds") });
                    ddsfiles.Add(new DDSConvertedFile() { sizeX = 256, sizeY = 256, sourceFile = albumArtPath, destinationFile = GeneralExtensions.GetTempFileName(".dds") });

                    // Convert to DDS
                    ToDDS(ddsfiles);

                    // Save for reuse
                    info.ArtFiles = ddsfiles;
                }

                foreach (var dds in info.ArtFiles)
                {
                    packPsarc.AddEntry(String.Format("gfxassets/album_art/album_{0}_{1}.dds", dlcName, dds.sizeX), new FileStream(dds.destinationFile, FileMode.Open, FileAccess.Read, FileShare.Read));
                    TMPFILES_ART.Add(dds.destinationFile);
                }

                // Lyric Art Texture
                if (File.Exists(info.LyricArtPath))
                    packPsarc.AddEntry(String.Format("assets/ui/lyrics/{0}/lyrics_{0}.dds", dlcName), new FileStream(info.LyricArtPath, FileMode.Open, FileAccess.Read, FileShare.Read));

                // AUDIO
                var audioFile = info.OggPath;
                if (File.Exists(audioFile))
                    if (platform.IsConsole != audioFile.GetAudioPlatform().IsConsole)
                        soundStream = OggFile.ConvertAudioPlatform(audioFile);
                    else
                        soundStream = File.OpenRead(audioFile);
                else
                    throw new InvalidOperationException(String.Format("Audio file '{0}' not found.", audioFile));

                // AUDIO PREVIEW
                var previewAudioFile = info.OggPreviewPath;
                if (File.Exists(previewAudioFile))
                    if (platform.IsConsole != previewAudioFile.GetAudioPlatform().IsConsole)
                        soundPreviewStream = OggFile.ConvertAudioPlatform(previewAudioFile);
                    else
                        soundPreviewStream = File.OpenRead(previewAudioFile);
                else
                    soundPreviewStream = soundStream;

                // FLAT MODEL
                rsenumerableRootStream = new MemoryStream(Resources.rsenumerable_root);
                packPsarc.AddEntry("flatmodels/rs/rsenumerable_root.flat", rsenumerableRootStream);
                rsenumerableSongStream = new MemoryStream(Resources.rsenumerable_song);
                packPsarc.AddEntry("flatmodels/rs/rsenumerable_song.flat", rsenumerableSongStream);

                using (var toolkitVersionStream = new MemoryStream())
                using (var appIdStream = new MemoryStream())
                using (var packageListStream = new MemoryStream())
                using (var soundbankStream = new MemoryStream())
                using (var soundbankPreviewStream = new MemoryStream())
                using (var aggregateGraphStream = new MemoryStream())
                using (var manifestHeaderHSANStream = new MemoryStream())
                using (var manifestHeaderHSONStreamList = new DisposableCollection<Stream>())
                using (var manifestStreamList = new DisposableCollection<Stream>())
                using (var arrangementStream = new DisposableCollection<Stream>())
                using (var showlightStream = new MemoryStream())
                using (var xblockStream = new MemoryStream())
                {
                    // TOOLKIT VERSION
                    GenerateToolkitVersion(toolkitVersionStream, info.PackageVersion);
                    packPsarc.AddEntry("toolkit.version", toolkitVersionStream);

                    // APP ID
                    if (!platform.IsConsole)
                    {
                        GenerateAppId(appIdStream, info.AppId, platform);
                        packPsarc.AddEntry("appid.appid", appIdStream);
                    }

                    if (platform.platform == GamePlatform.XBox360)
                    {
                        var packageListWriter = new StreamWriter(packageListStream);
                        packageListWriter.Write(dlcName);
                        packageListWriter.Flush();
                        packageListStream.Seek(0, SeekOrigin.Begin);
                        const string packageList = "PackageList.txt";
                        packageListStream.WriteTmpFile(packageList, platform);
                    }

                    // SOUNDBANK
                    var soundbankFileName = String.Format("song_{0}", dlcName);
                    var audioFileNameId = SoundBankGenerator2014.GenerateSoundBank(info.Name, soundStream, soundbankStream, info.Volume, platform);
                    packPsarc.AddEntry(String.Format("audio/{0}/{1}.bnk", platform.GetPathName()[0].ToLower(), soundbankFileName), soundbankStream);
                    packPsarc.AddEntry(String.Format("audio/{0}/{1}.wem", platform.GetPathName()[0].ToLower(), audioFileNameId), soundStream);

                    // SOUNDBANK PREVIEW
                    var soundbankPreviewFileName = String.Format("song_{0}_preview", dlcName);
                    dynamic audioPreviewFileNameId;
                    var previewVolume = (float)(info.PreviewVolume ?? info.Volume);
                    if (!soundPreviewStream.Equals(soundStream))
                        audioPreviewFileNameId = SoundBankGenerator2014.GenerateSoundBank(info.Name + "_Preview", soundPreviewStream, soundbankPreviewStream, previewVolume, platform, true);
                    else
                        audioPreviewFileNameId = SoundBankGenerator2014.GenerateSoundBank(info.Name + "_Preview", soundPreviewStream, soundbankPreviewStream, info.Volume, platform, true, true);
                    packPsarc.AddEntry(String.Format("audio/{0}/{1}.bnk", platform.GetPathName()[0].ToLower(), soundbankPreviewFileName), soundbankPreviewStream);
                    if (!soundPreviewStream.Equals(soundStream)) packPsarc.AddEntry(String.Format("audio/{0}/{1}.wem", platform.GetPathName()[0].ToLower(), audioPreviewFileNameId), soundPreviewStream);

                    // AGGREGATE GRAPH
                    var aggregateGraphFileName = String.Format("{0}_aggregategraph.nt", dlcName);
                    var aggregateGraph = new AggregateGraph2014.AggregateGraph2014(info, platform);
                    aggregateGraph.Serialize(aggregateGraphStream);
                    aggregateGraphStream.Flush();
                    aggregateGraphStream.Seek(0, SeekOrigin.Begin);
                    packPsarc.AddEntry(aggregateGraphFileName, aggregateGraphStream);

                    var manifestHeader = new ManifestHeader2014<AttributesHeader2014>(platform);
                    var songPartition = new SongPartition();
                    var songPartitionCount = new SongPartition();

                    foreach (var arrangement in info.Arrangements)
                    {
                        if (arrangement.ArrangementType == ArrangementType.ShowLight)
                            continue;

                        var arrangementFileName = songPartition.GetArrangementFileName(arrangement.Name, arrangement.ArrangementType).ToLower();

                        // GAME SONG (SNG)
                        UpdateToneDescriptors(info);
                        GenerateSNG(arrangement, platform);
                        var sngSongFile = File.OpenRead(arrangement.SongFile.File);
                        arrangementStream.Add(sngSongFile);
                        packPsarc.AddEntry(String.Format("songs/bin/{0}/{1}_{2}.sng", platform.GetPathName()[1].ToLower(), dlcName, arrangementFileName), sngSongFile);

                        // XML SONG
                        var xmlSongFile = File.OpenRead(arrangement.SongXml.File);
                        arrangementStream.Add(xmlSongFile);
                        packPsarc.AddEntry(String.Format("songs/arr/{0}_{1}.xml", dlcName, arrangementFileName), xmlSongFile);

                        // MANIFEST
                        var manifest = new Manifest2014<Attributes2014>();
                        var attribute = new Attributes2014(arrangementFileName, arrangement, info, platform);
                        if (arrangement.ArrangementType != ArrangementType.Vocal)
                        {
                            attribute.SongPartition = songPartitionCount.GetSongPartition(arrangement.Name, arrangement.ArrangementType);
                            if (attribute.SongPartition > 1)
                            {
                                // Make the second arrangement with the same arrangement type as ALTERNATE arrangement ingame
                                attribute.Representative = 0;
                                attribute.ArrangementProperties.Represent = 0;
                            }
                        }
                        var attributeDictionary = new Dictionary<string, Attributes2014> { { "Attributes", attribute } };
                        manifest.Entries.Add(attribute.PersistentID, attributeDictionary);
                        var manifestStream = new MemoryStream();
                        manifestStreamList.Add(manifestStream);
                        manifest.Serialize(manifestStream);
                        manifestStream.Seek(0, SeekOrigin.Begin);

                        const string jsonPathPC = "manifests/songs_dlc_{0}/{0}_{1}.json";
                        const string jsonPathConsole = "manifests/songs_dlc/{0}_{1}.json";
                        packPsarc.AddEntry(String.Format((platform.IsConsole ? jsonPathConsole : jsonPathPC), dlcName, arrangementFileName), manifestStream);

                        // MANIFEST HEADER
                        var attributeHeaderDictionary = new Dictionary<string, AttributesHeader2014> { { "Attributes", new AttributesHeader2014(attribute) } };

                        if (platform.IsConsole)
                        {
                            // One for each arrangements (Xbox360/PS3)
                            manifestHeader = new ManifestHeader2014<AttributesHeader2014>(platform);
                            manifestHeader.Entries.Add(attribute.PersistentID, attributeHeaderDictionary);
                            var manifestHeaderStream = new MemoryStream();
                            manifestHeaderHSONStreamList.Add(manifestHeaderStream);
                            manifestHeader.Serialize(manifestHeaderStream);
                            manifestStream.Seek(0, SeekOrigin.Begin);
                            packPsarc.AddEntry(String.Format("manifests/songs_dlc/{0}_{1}.hson", dlcName, arrangementFileName), manifestHeaderStream);
                        }
                        else
                        {
                            // One for all arrangements (PC/Mac)
                            manifestHeader.Entries.Add(attribute.PersistentID, attributeHeaderDictionary);
                        }
                    }

                    if (!platform.IsConsole)
                    {
                        manifestHeader.Serialize(manifestHeaderHSANStream);
                        manifestHeaderHSANStream.Seek(0, SeekOrigin.Begin);
                        packPsarc.AddEntry(String.Format("manifests/songs_dlc_{0}/songs_dlc_{0}.hsan", dlcName), manifestHeaderHSANStream);
                    }

                    // XML SHOWLIGHTS
                    var shlArr = info.Arrangements.FirstOrDefault(ar => ar.ArrangementType == ArrangementType.ShowLight);
                    if (shlArr != null && shlArr.SongXml.File != null)
                        using (var fs = File.OpenRead(shlArr.SongXml.File))
                            fs.CopyTo(showlightStream);
                    else
                    {
                        var showlight = new Showlights(info);
                        showlight.Serialize(showlightStream);
            #if DEBUG
                        // write to file for debugging
                        string shlFilePath = Path.Combine(Path.GetDirectoryName(info.Arrangements[0].SongXml.File), String.Format("{0}_showlights.xml", "CST"));
                        using (FileStream file = new FileStream(shlFilePath, FileMode.Create, FileAccess.Write))
                            showlightStream.WriteTo(file);
            #endif
                    }

                    if (showlightStream.CanRead)
                        packPsarc.AddEntry(String.Format("songs/arr/{0}_showlights.xml", dlcName), showlightStream);

                    // XBLOCK
                    GameXblock<Entity2014> game = GameXblock<Entity2014>.Generate2014(info, platform);
                    game.SerializeXml(xblockStream);
                    xblockStream.Flush();
                    xblockStream.Seek(0, SeekOrigin.Begin);
                    packPsarc.AddEntry(String.Format("gamexblocks/nsongs/{0}.xblock", dlcName), xblockStream);

                    // WRITE PACKAGE
                    packPsarc.Write(output, !platform.IsConsole);
                    output.Flush();
                    output.Seek(0, SeekOrigin.Begin);
                    output.WriteTmpFile(String.Format("{0}.psarc", dlcName), platform);
                }
            }
            finally
            {
                // Dispose all objects
                if (soundStream != null)
                    soundStream.Dispose();
                if (soundPreviewStream != null)
                    soundPreviewStream.Dispose();
                if (rsenumerableRootStream != null)
                    rsenumerableRootStream.Dispose();
                if (rsenumerableSongStream != null)
                    rsenumerableSongStream.Dispose();
                if (pnum == 0)
                    DeleteTmpFiles(TMPFILES_ART);
                DeleteTmpFiles(TMPFILES_SNG);
            }
        }
        private static void GenerateRS2014InlayPsarc(Stream output, DLCPackageData info, Platform platform)
        {
            dlcName = info.Inlay.DLCSixName;
            // TODO updateProgress remotely from here
            {
                packPsarc = new PSARC.PSARC();

                // Stream objects
                Stream rsenumerableRootStream = null,
                       rsenumerableGuitarStream = null;

                try
                {
                    // ICON/INLAY FILES
                    var ddsfiles = info.ArtFiles;

                    if (ddsfiles == null)
                    {
                        string iconPath;
                        if (File.Exists(info.Inlay.IconPath))
                        {
                            iconPath = info.Inlay.IconPath;
                        }
                        else
                        {
                            using (var iconStream = new MemoryStream(Resources.cgm_default_icon))
                            {
                                iconPath = Path.ChangeExtension(Path.GetTempFileName(), ".png");
                                iconStream.WriteFile(iconPath);
                                TMPFILES_ART.Add(iconPath);
                            }
                        }

                        string inlayPath;
                        if (File.Exists(info.Inlay.InlayPath))
                        {
                            inlayPath = info.Inlay.InlayPath;
                        }
                        else
                        {
                            using (var inlayStream = new MemoryStream(Resources.cgm_default_inlay))
                            {
                                inlayPath = GeneralExtensions.GetTempFileName(".png");
                                inlayStream.WriteFile(inlayPath);
                                TMPFILES_ART.Add(inlayPath);
                            }
                        }

                        ddsfiles = new List<DDSConvertedFile>();
                        ddsfiles.Add(new DDSConvertedFile() { sizeX = 64, sizeY = 64, sourceFile = iconPath, destinationFile = GeneralExtensions.GetTempFileName(".dds") });
                        ddsfiles.Add(new DDSConvertedFile() { sizeX = 128, sizeY = 128, sourceFile = iconPath, destinationFile = GeneralExtensions.GetTempFileName(".dds") });
                        ddsfiles.Add(new DDSConvertedFile() { sizeX = 256, sizeY = 256, sourceFile = iconPath, destinationFile = GeneralExtensions.GetTempFileName(".dds") });
                        ddsfiles.Add(new DDSConvertedFile() { sizeX = 512, sizeY = 512, sourceFile = iconPath, destinationFile = GeneralExtensions.GetTempFileName(".dds") });
                        ddsfiles.Add(new DDSConvertedFile() { sizeX = 1024, sizeY = 512, sourceFile = inlayPath, destinationFile = GeneralExtensions.GetTempFileName(".dds") });

                        // Convert to DDS
                        ToDDS(ddsfiles, DLCPackageType.Inlay);

                        // Save for reuse
                        info.ArtFiles = ddsfiles;
                    }

                    foreach (var dds in info.ArtFiles)
                        if (dds.sizeX == 1024)
                            packPsarc.AddEntry(String.Format("assets/gameplay/inlay/inlay_{0}.dds", dlcName), new FileStream(dds.destinationFile, FileMode.Open, FileAccess.Read, FileShare.Read));
                        else
                            packPsarc.AddEntry(String.Format("gfxassets/rewards/guitar_inlays/reward_inlay_{0}_{1}.dds", dlcName, dds.sizeX), new FileStream(dds.destinationFile, FileMode.Open, FileAccess.Read, FileShare.Read));

                    // FLAT MODEL
                    rsenumerableRootStream = new MemoryStream(Resources.rsenumerable_root);
                    packPsarc.AddEntry("flatmodels/rs/rsenumerable_root.flat", rsenumerableRootStream);
                    rsenumerableGuitarStream = new MemoryStream(Resources.rsenumerable_guitar);
                    packPsarc.AddEntry("flatmodels/rs/rsenumerable_guitars.flat", rsenumerableGuitarStream);

                    using (var toolkitVersionStream = new MemoryStream())
                    using (var appIdStream = new MemoryStream())
                    using (var packageListStream = new MemoryStream())
                    using (var aggregateGraphStream = new MemoryStream())
                    using (var manifestStreamList = new DisposableCollection<Stream>())
                    using (var manifestHeaderStream = new MemoryStream())
                    using (var nifStream = new MemoryStream())
                    using (var xblockStream = new MemoryStream())
                    {
                        // TOOLKIT VERSION
                        GenerateToolkitVersion(toolkitVersionStream);
                        packPsarc.AddEntry("toolkit.version", toolkitVersionStream);

                        // APP ID
                        if (!platform.IsConsole)
                        {
                            GenerateAppId(appIdStream, info.AppId, platform);
                            packPsarc.AddEntry("appid.appid", appIdStream);
                        }

                        if (platform.platform == GamePlatform.XBox360)
                        {
                            var packageListWriter = new StreamWriter(packageListStream);
                            packageListWriter.Write(dlcName);
                            packageListWriter.Flush();
                            packageListStream.Seek(0, SeekOrigin.Begin);
                            const string packageList = "PackageList.txt";
                            packageListStream.WriteTmpFile(packageList, platform);
                        }

                        // AGGREGATE GRAPH
                        var aggregateGraphFileName = String.Format("{0}_aggregategraph.nt", dlcName);
                        var aggregateGraph = new AggregateGraph2014.AggregateGraph2014(info, platform, DLCPackageType.Inlay);
                        aggregateGraph.Serialize(aggregateGraphStream);
                        aggregateGraphStream.Flush();
                        aggregateGraphStream.Seek(0, SeekOrigin.Begin);
                        packPsarc.AddEntry(aggregateGraphFileName, aggregateGraphStream);

                        // MANIFEST
                        var attribute = new InlayAttributes2014(info);
                        var attributeDictionary = new Dictionary<string, InlayAttributes2014> { { "Attributes", attribute } };
                        var manifest = new Manifest2014<InlayAttributes2014>(DLCPackageType.Inlay);
                        manifest.Entries.Add(attribute.PersistentID, attributeDictionary);
                        var manifestStream = new MemoryStream();
                        manifestStreamList.Add(manifestStream);
                        manifest.Serialize(manifestStream);
                        manifestStream.Seek(0, SeekOrigin.Begin);
                        const string jsonPathPC = "manifests/songs_dlc_{0}/dlc_guitar_{0}.json";
                        const string jsonPathConsole = "manifests/songs_dlc/dlc_guitar_{0}.json";
                        packPsarc.AddEntry(String.Format((platform.IsConsole ? jsonPathConsole : jsonPathPC), dlcName), manifestStream);

                        // MANIFEST HEADER
                        var attributeHeaderDictionary = new Dictionary<string, InlayAttributes2014> { { "Attributes", attribute } };
                        var manifestHeader = new ManifestHeader2014<InlayAttributes2014>(platform, DLCPackageType.Inlay);
                        manifestHeader.Entries.Add(attribute.PersistentID, attributeHeaderDictionary);
                        manifestHeader.Serialize(manifestHeaderStream);
                        manifestHeaderStream.Seek(0, SeekOrigin.Begin);
                        const string hsanPathPC = "manifests/songs_dlc_{0}/dlc_{0}.hsan";
                        const string hsonPathConsole = "manifests/songs_dlc/dlc_{0}.hson";
                        packPsarc.AddEntry(String.Format((platform.IsConsole ? hsonPathConsole : hsanPathPC), dlcName), manifestHeaderStream);

                        // XBLOCK
                        GameXblock<Entity2014> game = GameXblock<Entity2014>.Generate2014(info, platform, DLCPackageType.Inlay);
                        game.SerializeXml(xblockStream);
                        xblockStream.Flush();
                        xblockStream.Seek(0, SeekOrigin.Begin);
                        packPsarc.AddEntry(String.Format("gamexblocks/nguitars/guitar_{0}.xblock", dlcName), xblockStream);

                        // INLAY NIF
                        InlayNif nif = new InlayNif(info);
                        nif.Serialize(nifStream);
                        nifStream.Flush();
                        nifStream.Seek(0, SeekOrigin.Begin);
                        packPsarc.AddEntry(String.Format("assets/gameplay/inlay/{0}.nif", dlcName), nifStream);

                        // WRITE PACKAGE
                        packPsarc.Write(output, !platform.IsConsole);
                        output.Flush();
                        output.Seek(0, SeekOrigin.Begin);
                        output.WriteTmpFile(String.Format("{0}.psarc", dlcName), platform);
                    }
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    // Dispose all objects
                    if (rsenumerableRootStream != null)
                        rsenumerableRootStream.Dispose();
                    if (rsenumerableGuitarStream != null)
                        rsenumerableGuitarStream.Dispose();
                    DeleteTmpFiles(TMPFILES_ART);
                }
            }
        }
        public static string DoLikeSongPack(string srcPath, string appId = "248750")
        {
            // create SongPack directory structure
            var dlcName              = Path.GetFileName(srcPath).ToLower();
            var songPackDir          = Path.Combine(Path.GetTempPath(), String.Format("{0}_songpack_p_Pc", dlcName));
            var audioWindowDir       = Path.Combine(songPackDir, "audio", "windows");
            var flatmodelsRsDir      = Path.Combine(songPackDir, "flatmodels", "rs");
            var gamexblocksNsongsDir = Path.Combine(songPackDir, "gamexblocks", "nsongs");
            var gfxassetsAlbumArtDir = Path.Combine(songPackDir, "gfxassets", "album_art");
            var manifestSongsDir     = Path.Combine(songPackDir, "manifests", String.Format("songs_dlc_{0}", dlcName));
            var songsArrDir          = Path.Combine(songPackDir, "songs", "arr");
            var binGenericDir        = Path.Combine(songPackDir, "songs", "bin", "generic");

            if (Directory.Exists(songPackDir))
            {
                DirectoryExtension.SafeDelete(songPackDir);
            }

            Directory.CreateDirectory(songPackDir);
            Directory.CreateDirectory(audioWindowDir);
            Directory.CreateDirectory(flatmodelsRsDir);
            Directory.CreateDirectory(gamexblocksNsongsDir);
            Directory.CreateDirectory(gfxassetsAlbumArtDir);
            Directory.CreateDirectory(manifestSongsDir);
            Directory.CreateDirectory(songsArrDir);
            Directory.CreateDirectory(binGenericDir);

            // populate SongPack temporary directory
            var audioWemFiles = Directory.EnumerateFiles(srcPath, "*.wem", SearchOption.AllDirectories).ToArray();

            foreach (var wem in audioWemFiles)
            {
                File.Copy(wem, Path.Combine(audioWindowDir, Path.GetFileName(wem)));
            }

            var audioBnkFiles = Directory.EnumerateFiles(srcPath, "*.bnk", SearchOption.AllDirectories).ToArray();

            foreach (var bnk in audioBnkFiles)
            {
                File.Copy(bnk, Path.Combine(audioWindowDir, Path.GetFileName(bnk)));
            }

            var xblockFiles = Directory.EnumerateFiles(srcPath, "*.xblock", SearchOption.AllDirectories).ToArray();

            foreach (var xblock in xblockFiles)
            {
                File.Copy(xblock, Path.Combine(gamexblocksNsongsDir, Path.GetFileName(xblock)));
            }

            var albumArtFiles = Directory.EnumerateFiles(srcPath, "*.dds", SearchOption.AllDirectories).ToArray();

            foreach (var albumArt in albumArtFiles)
            {
                File.Copy(albumArt, Path.Combine(gfxassetsAlbumArtDir, Path.GetFileName(albumArt)));
            }

            var jsonFiles = Directory.EnumerateFiles(srcPath, "*.json", SearchOption.AllDirectories).ToArray();

            foreach (var json in jsonFiles)
            {
                File.Copy(json, Path.Combine(manifestSongsDir, Path.GetFileName(json)));
            }

            var hsanFiles = Directory.EnumerateFiles(srcPath, "*.hsan", SearchOption.AllDirectories).ToArray();

            foreach (var hsan in hsanFiles)
            {
                File.Copy(hsan, Path.Combine(manifestSongsDir, Path.GetFileName(hsan)));
            }

            var sngFiles = Directory.EnumerateFiles(srcPath, "*.sng", SearchOption.AllDirectories).ToArray();

            foreach (var sng in sngFiles)
            {
                File.Copy(sng, Path.Combine(binGenericDir, Path.GetFileName(sng)));
            }

            var xmlFiles = Directory.EnumerateFiles(srcPath, "*.xml", SearchOption.AllDirectories).ToArray();

            foreach (var xml in xmlFiles)
            {
                File.Copy(xml, Path.Combine(songsArrDir, Path.GetFileName(xml)));
            }

            // generate new Aggregate Graph
            var aggGraphPack = new AggregateGraph2014();

            aggGraphPack.JsonDB        = new List <GraphItem>();
            aggGraphPack.HsonDB        = new List <GraphItem>(); // used for consoles ONLY
            aggGraphPack.HsanDB        = new GraphItem();
            aggGraphPack.MusicgameSong = new List <GraphItemLLID>();
            aggGraphPack.SongXml       = new List <GraphItemLLID>();
            aggGraphPack.ShowlightXml  = new List <GraphItemLLID>();
            aggGraphPack.ImageArt      = new List <GraphItemLLID>();
            aggGraphPack.Soundbank     = new List <GraphItemLLID>();
            aggGraphPack.GameXblock    = new List <GraphItem>();

            // fix aggregate graph entries, reusing existing Persistent ID
            var currentPlatform     = new Platform(GamePlatform.Pc, GameVersion.RS2014);
            var aggregateGraphFiles = Directory.EnumerateFiles(srcPath, "*.nt", SearchOption.AllDirectories).ToArray();

            foreach (var aggGraph in aggregateGraphFiles)
            {
                var agg = LoadFromFile(aggGraph);

                foreach (var json in agg.JsonDB)
                {
                    json.Canonical        = String.Format(CANONICAL_MANIFEST_PC, dlcName);
                    json.RelPathDirectory = json.Canonical;
                    json.Tag = new List <string>();
                    json.Tag.Add(TagValue.Database.GetDescription());
                    json.Tag.Add(TagValue.JsonDB.GetDescription());
                    json.UUID        = IdGenerator.Guid();
                    json.RelPathFile = String.Format("{0}.json", json.Name);
                }

                aggGraphPack.JsonDB.AddRange(agg.JsonDB);
                aggGraphPack.MusicgameSong.AddRange(agg.MusicgameSong);
                aggGraphPack.SongXml.AddRange(agg.SongXml);
                aggGraphPack.ShowlightXml.AddRange(agg.ShowlightXml);
                aggGraphPack.ImageArt.AddRange(agg.ImageArt);
                aggGraphPack.Soundbank.AddRange(agg.Soundbank);

                aggGraphPack.GameXblock.AddRange(agg.GameXblock);
            }

            // create a single hsanDB entry
            aggGraphPack.HsanDB.Name             = String.Format("songs_dlc_{0}", dlcName);
            aggGraphPack.HsanDB.Canonical        = String.Format(CANONICAL_MANIFEST_PC, dlcName);
            aggGraphPack.HsanDB.RelPathDirectory = aggGraphPack.HsanDB.Canonical;
            aggGraphPack.HsanDB.Tag = new List <string>();
            aggGraphPack.HsanDB.Tag.Add(TagValue.Database.GetDescription());
            aggGraphPack.HsanDB.Tag.Add(TagValue.HsanDB.GetDescription());
            aggGraphPack.HsanDB.UUID        = IdGenerator.Guid();
            aggGraphPack.HsanDB.RelPathFile = String.Format("{0}.hsan", aggGraphPack.HsanDB.Name);

            var aggregateGraphFileName = Path.Combine(songPackDir, String.Format("{0}_aggregategraph.nt", dlcName));

            using (var fs = new FileStream(aggregateGraphFileName, FileMode.Create))
                using (var ms = new MemoryStream())
                {
                    aggGraphPack.Serialize(ms);
                    ms.Flush();
                    ms.Seek(0, SeekOrigin.Begin);
                    ms.CopyTo(fs);
                }

            MergeHsanFiles(songPackDir, dlcName, manifestSongsDir);

            var appIdFile = Path.Combine(songPackDir, "appid.appid");

            File.WriteAllText(appIdFile, appId);

            var toolkitVersionFile = Path.Combine(songPackDir, "toolkit.version");

            using (var fs = new FileStream(toolkitVersionFile, FileMode.Create))
                using (var ms = new MemoryStream())
                {
                    DLCPackageCreator.GenerateToolkitVersion(ms, packageComment: "SongPack Maker v1.1");
                    ms.Flush();
                    ms.Seek(0, SeekOrigin.Begin);
                    ms.CopyTo(fs);
                }

            var rootFlatFile = Path.Combine(flatmodelsRsDir, "rsenumerable_root.flat");

            using (var fs = new FileStream(rootFlatFile, FileMode.Create))
                using (var ms = new MemoryStream(Resources.rsenumerable_root))
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    ms.CopyTo(fs);
                }

            var songFlatFile = Path.Combine(flatmodelsRsDir, "rsenumerable_song.flat");

            using (var fs = new FileStream(songFlatFile, FileMode.Create))
                using (var ms = new MemoryStream(Resources.rsenumerable_song))
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    ms.CopyTo(fs);
                }

            return(songPackDir);
        }
        public static string DoLikeSongPack(string srcPath, string appId = "248750")
        {
            // create SongPack directory structure
            var dlcName = Path.GetFileName(srcPath).ToLower();
            var songPackDir = Path.Combine(Path.GetTempPath(), String.Format("{0}_songpack_p_Pc", dlcName));
            var audioWindowDir = Path.Combine(songPackDir, "audio", "windows");
            var flatmodelsRsDir = Path.Combine(songPackDir, "flatmodels", "rs");
            var gamexblocksNsongsDir = Path.Combine(songPackDir, "gamexblocks", "nsongs");
            var gfxassetsAlbumArtDir = Path.Combine(songPackDir, "gfxassets", "album_art");
            var manifestSongsDir = Path.Combine(songPackDir, "manifests", String.Format("songs_dlc_{0}", dlcName));
            var songsArrDir = Path.Combine(songPackDir, "songs", "arr");
            var binGenericDir = Path.Combine(songPackDir, "songs", "bin", "generic");

            if (Directory.Exists(songPackDir))
                DirectoryExtension.SafeDelete(songPackDir);

            Directory.CreateDirectory(songPackDir);
            Directory.CreateDirectory(audioWindowDir);
            Directory.CreateDirectory(flatmodelsRsDir);
            Directory.CreateDirectory(gamexblocksNsongsDir);
            Directory.CreateDirectory(gfxassetsAlbumArtDir);
            Directory.CreateDirectory(manifestSongsDir);
            Directory.CreateDirectory(songsArrDir);
            Directory.CreateDirectory(binGenericDir);

            // populate SongPack temporary directory
            var audioWemFiles = Directory.EnumerateFiles(srcPath, "*.wem", SearchOption.AllDirectories).ToArray();
            foreach (var wem in audioWemFiles)
                File.Copy(wem, Path.Combine(audioWindowDir, Path.GetFileName(wem)));

            var audioBnkFiles = Directory.EnumerateFiles(srcPath, "*.bnk", SearchOption.AllDirectories).ToArray();
            foreach (var bnk in audioBnkFiles)
                File.Copy(bnk, Path.Combine(audioWindowDir, Path.GetFileName(bnk)));

            var xblockFiles = Directory.EnumerateFiles(srcPath, "*.xblock", SearchOption.AllDirectories).ToArray();
            foreach (var xblock in xblockFiles)
                File.Copy(xblock, Path.Combine(gamexblocksNsongsDir, Path.GetFileName(xblock)));

            var albumArtFiles = Directory.EnumerateFiles(srcPath, "*.dds", SearchOption.AllDirectories).ToArray();
            foreach (var albumArt in albumArtFiles)
                File.Copy(albumArt, Path.Combine(gfxassetsAlbumArtDir, Path.GetFileName(albumArt)));

            var jsonFiles = Directory.EnumerateFiles(srcPath, "*.json", SearchOption.AllDirectories).ToArray();
            foreach (var json in jsonFiles)
                File.Copy(json, Path.Combine(manifestSongsDir, Path.GetFileName(json)));

            var hsanFiles = Directory.EnumerateFiles(srcPath, "*.hsan", SearchOption.AllDirectories).ToArray();
            foreach (var hsan in hsanFiles)
                File.Copy(hsan, Path.Combine(manifestSongsDir, Path.GetFileName(hsan)));

            var sngFiles = Directory.EnumerateFiles(srcPath, "*.sng", SearchOption.AllDirectories).ToArray();
            foreach (var sng in sngFiles)
                File.Copy(sng, Path.Combine(binGenericDir, Path.GetFileName(sng)));

            var xmlFiles = Directory.EnumerateFiles(srcPath, "*.xml", SearchOption.AllDirectories).ToArray();
            foreach (var xml in xmlFiles)
                File.Copy(xml, Path.Combine(songsArrDir, Path.GetFileName(xml)));

            // generate new Aggregate Graph
            var aggGraphPack = new AggregateGraph2014();
            aggGraphPack.JsonDB = new List<GraphItem>();
            aggGraphPack.HsonDB = new List<GraphItem>(); // used for consoles ONLY
            aggGraphPack.HsanDB = new GraphItem();
            aggGraphPack.MusicgameSong = new List<GraphItemLLID>();
            aggGraphPack.SongXml = new List<GraphItemLLID>();
            aggGraphPack.ShowlightXml = new List<GraphItemLLID>();
            aggGraphPack.ImageArt = new List<GraphItemLLID>();
            aggGraphPack.Soundbank = new List<GraphItemLLID>();
            aggGraphPack.GameXblock = new List<GraphItem>();

            // fix aggregate graph entries, reusing existing Persistent ID
            var currentPlatform = new Platform(GamePlatform.Pc, GameVersion.RS2014);
            var aggregateGraphFiles = Directory.EnumerateFiles(srcPath, "*.nt", SearchOption.AllDirectories).ToArray();
            foreach (var aggGraph in aggregateGraphFiles)
            {
                var agg = LoadFromFile(aggGraph);

                foreach (var json in agg.JsonDB)
                {
                    json.Canonical = String.Format(CANONICAL_MANIFEST_PC, dlcName);
                    json.RelPathDirectory = json.Canonical;
                    json.Tag = new List<string>();
                    json.Tag.Add(TagValue.Database.GetDescription());
                    json.Tag.Add(TagValue.JsonDB.GetDescription());
                    json.UUID = IdGenerator.Guid();
                    json.RelPathFile = String.Format("{0}.json", json.Name);
                }

                aggGraphPack.JsonDB.AddRange(agg.JsonDB);
                aggGraphPack.MusicgameSong.AddRange(agg.MusicgameSong);
                aggGraphPack.SongXml.AddRange(agg.SongXml);
                aggGraphPack.ShowlightXml.AddRange(agg.ShowlightXml);
                aggGraphPack.ImageArt.AddRange(agg.ImageArt);
                aggGraphPack.Soundbank.AddRange(agg.Soundbank);

                aggGraphPack.GameXblock.AddRange(agg.GameXblock);
            }

            // create a single hsanDB entry
            aggGraphPack.HsanDB.Name = String.Format("songs_dlc_{0}", dlcName);
            aggGraphPack.HsanDB.Canonical = String.Format(CANONICAL_MANIFEST_PC, dlcName);
            aggGraphPack.HsanDB.RelPathDirectory = aggGraphPack.HsanDB.Canonical;
            aggGraphPack.HsanDB.Tag = new List<string>();
            aggGraphPack.HsanDB.Tag.Add(TagValue.Database.GetDescription());
            aggGraphPack.HsanDB.Tag.Add(TagValue.HsanDB.GetDescription());
            aggGraphPack.HsanDB.UUID = IdGenerator.Guid();
            aggGraphPack.HsanDB.RelPathFile = String.Format("{0}.hsan", aggGraphPack.HsanDB.Name);

            var aggregateGraphFileName = Path.Combine(songPackDir, String.Format("{0}_aggregategraph.nt", dlcName));
            using (var fs = new FileStream(aggregateGraphFileName, FileMode.Create))
            using (var ms = new MemoryStream())
            {
                aggGraphPack.Serialize(ms);
                ms.Flush();
                ms.Seek(0, SeekOrigin.Begin);
                ms.CopyTo(fs);
            }

            MergeHsanFiles(songPackDir, dlcName, manifestSongsDir);

            var appIdFile = Path.Combine(songPackDir, "appid.appid");
            File.WriteAllText(appIdFile, appId);

            var toolkitVersionFile = Path.Combine(songPackDir, "toolkit.version");
            using (var fs = new FileStream(toolkitVersionFile, FileMode.Create))
            using (var ms = new MemoryStream())
            {
                DLCPackageCreator.GenerateToolkitVersion(ms, packageComment: "SongPack Maker v1.1");
                ms.Flush();
                ms.Seek(0, SeekOrigin.Begin);
                ms.CopyTo(fs);
            }

            var rootFlatFile = Path.Combine(flatmodelsRsDir, "rsenumerable_root.flat");
            using (var fs = new FileStream(rootFlatFile, FileMode.Create))
            using (var ms = new MemoryStream(Resources.rsenumerable_root))
            {
                ms.Seek(0, SeekOrigin.Begin);
                ms.CopyTo(fs);
            }

            var songFlatFile = Path.Combine(flatmodelsRsDir, "rsenumerable_song.flat");
            using (var fs = new FileStream(songFlatFile, FileMode.Create))
            using (var ms = new MemoryStream(Resources.rsenumerable_song))
            {
                ms.Seek(0, SeekOrigin.Begin);
                ms.CopyTo(fs);
            }

            return songPackDir;
        }