public static string SaveTrack(Track trk, string savename)
        {
            var dir = TrackIO.GetTrackDirectory(trk);

            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            var filename = dir + savename + ".trk";

            using (var file = File.Create(filename))
            {
                var bw = new BinaryWriter(file);
                bw.Write(new byte[] { (byte)'T', (byte)'R', (byte)'K', 0xF2 });
                bw.Write((byte)1);
                string featurestring = "";
                var    lines         = trk.GetLines();
                var    featurelist   = TrackIO.GetTrackFeatures(trk);
                featurelist.TryGetValue(TrackFeatures.songinfo, out bool songinfo);
                featurelist.TryGetValue(TrackFeatures.redmultiplier, out bool redmultiplier);
                featurelist.TryGetValue(TrackFeatures.zerostart, out bool zerostart);
                featurelist.TryGetValue(TrackFeatures.scenerywidth, out bool scenerywidth);
                featurelist.TryGetValue(TrackFeatures.six_one, out bool six_one);
                featurelist.TryGetValue(TrackFeatures.ignorable_trigger, out bool ignorable_trigger);
                foreach (var feature in featurelist)
                {
                    if (feature.Value)
                    {
                        featurestring += feature.Key + ";";
                    }
                }
                WriteString(bw, featurestring);
                if (songinfo)
                {
                    // unfotrunately this relies on .net to save and parse in
                    // its own way, and we're kind of stuck with it instead of
                    // the right way to write strings
                    bw.Write(trk.Song.ToString());
                }
                bw.Write(trk.StartOffset.X);
                bw.Write(trk.StartOffset.Y);
                bw.Write(lines.Length);
                foreach (var line in lines)
                {
                    byte type = (byte)line.Type;
                    if (line is StandardLine l)
                    {
                        if (l.inv)
                        {
                            type |= 1 << 7;
                        }
                        var ext = (byte)l.Extension;
                        type |= (byte)((ext & 0x03) << 5); //bits: 2
                        bw.Write(type);
                        if (redmultiplier)
                        {
                            if (line is RedLine red)
                            {
                                bw.Write((byte)red.Multiplier);
                            }
                        }
                        if (ignorable_trigger)
                        {
                            if (l.Trigger != null)
                            {
                                if (l.Trigger.ZoomTrigger) // check other triggers here for at least one
                                {
                                    bw.Write(l.Trigger.ZoomTrigger);
                                    if (l.Trigger.ZoomTrigger)
                                    {
                                        bw.Write(l.Trigger.ZoomTarget);
                                        bw.Write((short)l.Trigger.ZoomFrames);
                                    }
                                }
                                else
                                {
                                    bw.Write(false);
                                }
                            }
                            else
                            {
                                bw.Write(false);//zoomtrigger=false
                            }
                        }
                        bw.Write(l.ID);
                        if (l.Extension != StandardLine.Ext.None)
                        {
                            // this was extension writing
                            // but we no longer support this.
                            bw.Write(-1);
                            bw.Write(-1);
                        }
                    }
                    else
                    {
                        bw.Write(type);
                        if (scenerywidth)
                        {
                            if (line is SceneryLine scenery)
                            {
                                byte b = (byte)(Math.Round(scenery.Width, 1) * 10);
                                bw.Write(b);
                            }
                        }
                    }

                    bw.Write(line.Position.X);
                    bw.Write(line.Position.Y);
                    bw.Write(line.Position2.X);
                    bw.Write(line.Position2.Y);
                }
                bw.Write(new byte[] { (byte)'M', (byte)'E', (byte)'T', (byte)'A' });
                List <string> metadata = new List <string>();
                metadata.Add("STARTZOOM=" + trk.StartZoom.ToString(Program.Culture));

                bw.Write((short)metadata.Count);
                foreach (var str in metadata)
                {
                    WriteString(bw, str);
                }
            }
            return(filename);
        }
        public static string SaveTrack(Track trk, string savename)
        {
            var dir = TrackIO.GetTrackDirectory(trk);

            if (trk.Name.Equals("<untitled>"))
            {
                dir = Utils.Constants.TracksDirectory + "Unnamed Track" + Path.DirectorySeparatorChar;
            }
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            var filename = dir + savename + ".trk";

            using (var file = File.Create(filename))
            {
                var bw = new BinaryWriter(file);
                bw.Write(new byte[] { (byte)'T', (byte)'R', (byte)'K', 0xF2 }); //TRK
                bw.Write((byte)1);
                string featurestring = "";
                var    lines         = trk.GetLines();
                var    featurelist   = TrackIO.GetTrackFeatures(trk);
                featurelist.TryGetValue(TrackFeatures.songinfo, out bool songinfo);
                featurelist.TryGetValue(TrackFeatures.redmultiplier, out bool redmultiplier);
                featurelist.TryGetValue(TrackFeatures.zerostart, out bool zerostart);
                featurelist.TryGetValue(TrackFeatures.scenerywidth, out bool scenerywidth);
                featurelist.TryGetValue(TrackFeatures.six_one, out bool six_one);
                featurelist.TryGetValue(TrackFeatures.ignorable_trigger, out bool ignorable_trigger);
                featurelist.TryGetValue(TrackFeatures.remount, out bool remount);
                featurelist.TryGetValue(TrackFeatures.frictionless, out bool frictionless);
                foreach (var feature in featurelist)
                {
                    if (feature.Value)
                    {
                        featurestring += feature.Key + ";";
                    }
                }
                WriteString(bw, featurestring);
                if (songinfo)
                {
                    // unfotrunately this relies on .net to save and parse in
                    // its own way, and we're kind of stuck with it instead of
                    // the right way to write strings
                    bw.Write(trk.Song.ToString());
                }
                bw.Write(trk.StartOffset.X);
                bw.Write(trk.StartOffset.Y);
                bw.Write(lines.Length);
                foreach (var line in lines)
                {
                    byte type = (byte)line.Type;
                    if (line is StandardLine l)
                    {
                        if (l.inv)
                        {
                            type |= 1 << 7;
                        }
                        var ext = (byte)l.Extension;
                        type |= (byte)((ext & 0x03) << 5); //bits: 2
                        bw.Write(type);
                        if (redmultiplier)
                        {
                            if (line is RedLine red)
                            {
                                bw.Write((byte)red.Multiplier);
                            }
                        }
                        if (ignorable_trigger)
                        {
                            if (l.Trigger != null)
                            {
                                if (l.Trigger.ZoomTrigger) // check other triggers here for at least one
                                {
                                    bw.Write(l.Trigger.ZoomTrigger);
                                    if (l.Trigger.ZoomTrigger)
                                    {
                                        bw.Write(l.Trigger.ZoomTarget);
                                        bw.Write((short)l.Trigger.ZoomFrames);
                                    }
                                }
                                else
                                {
                                    bw.Write(false);
                                }
                            }
                            else
                            {
                                bw.Write(false);//zoomtrigger=false
                            }
                        }
                        bw.Write(l.ID);
                        if (l.Extension != StandardLine.Ext.None)
                        {
                            // this was extension writing
                            // but we no longer support this.
                            bw.Write(-1);
                            bw.Write(-1);
                        }
                    }
                    else
                    {
                        bw.Write(type);
                        if (scenerywidth)
                        {
                            if (line is SceneryLine scenery)
                            {
                                byte b = (byte)(Math.Round(scenery.Width, 1) * 10);
                                bw.Write(b);
                            }
                        }
                    }

                    bw.Write(line.Position.X);
                    bw.Write(line.Position.Y);
                    bw.Write(line.Position2.X);
                    bw.Write(line.Position2.Y);
                }
                bw.Write(new byte[] { (byte)'M', (byte)'E', (byte)'T', (byte)'A' });
                List <string> metadata = new List <string>();
                metadata.Add(TrackMetadata.startzoom + "=" + trk.StartZoom.ToString(Program.Culture));

                //Only add if the values are different from default
                if (trk.YGravity != 1)
                {
                    metadata.Add(TrackMetadata.ygravity + "=" + trk.YGravity.ToString(Program.Culture));
                }
                if (trk.XGravity != 0)
                {
                    metadata.Add(TrackMetadata.xgravity + "=" + trk.XGravity.ToString(Program.Culture));
                }
                if (trk.GravityWellSize != 10)
                {
                    metadata.Add(TrackMetadata.gravitywellsize + "=" + trk.GravityWellSize.ToString(Program.Culture));
                }

                if (trk.BGColorR != Color.FromArgb(Utils.Constants.ColorOffwhite.ToArgb()).R)
                {
                    metadata.Add(TrackMetadata.bgcolorR + "=" + trk.BGColorR.ToString(Program.Culture));
                }
                if (trk.BGColorG != Color.FromArgb(Utils.Constants.ColorOffwhite.ToArgb()).G)
                {
                    metadata.Add(TrackMetadata.bgcolorG + "=" + trk.BGColorG.ToString(Program.Culture));
                }
                if (trk.BGColorB != Color.FromArgb(Utils.Constants.ColorOffwhite.ToArgb()).B)
                {
                    metadata.Add(TrackMetadata.bgcolorB + "=" + trk.BGColorB.ToString(Program.Culture));
                }

                if (trk.LineColorR != Settings.Lines.DefaultLine.R)
                {
                    metadata.Add(TrackMetadata.linecolorR + "=" + trk.LineColorR.ToString(Program.Culture));
                }
                if (trk.LineColorG != Settings.Lines.DefaultLine.G)
                {
                    metadata.Add(TrackMetadata.linecolorG + "=" + trk.LineColorG.ToString(Program.Culture));
                }
                if (trk.LineColorB != Settings.Lines.DefaultLine.B)
                {
                    metadata.Add(TrackMetadata.linecolorB + "=" + trk.LineColorB.ToString(Program.Culture));
                }

                StringBuilder triggerstring = new StringBuilder();
                for (int i = 0; i < trk.Triggers.Count; i++)
                {
                    GameTrigger t = trk.Triggers[i];
                    if (i != 0)
                    {
                        triggerstring.Append("&");
                    }
                    switch (t.TriggerType)
                    {
                    case TriggerType.Zoom:
                        triggerstring.Append((int)TriggerType.Zoom);
                        triggerstring.Append(":");
                        triggerstring.Append(t.ZoomTarget.ToString(Program.Culture));
                        triggerstring.Append(":");
                        break;

                    case TriggerType.BGChange:
                        triggerstring.Append((int)TriggerType.BGChange);
                        triggerstring.Append(":");
                        triggerstring.Append(t.backgroundRed.ToString(Program.Culture));
                        triggerstring.Append(":");
                        triggerstring.Append(t.backgroundGreen.ToString(Program.Culture));
                        triggerstring.Append(":");
                        triggerstring.Append(t.backgroundBlue.ToString(Program.Culture));
                        triggerstring.Append(":");
                        break;

                    case TriggerType.LineColor:
                        triggerstring.Append((int)TriggerType.LineColor);
                        triggerstring.Append(":");
                        triggerstring.Append(t.lineRed.ToString(Program.Culture));
                        triggerstring.Append(":");
                        triggerstring.Append(t.lineGreen.ToString(Program.Culture));
                        triggerstring.Append(":");
                        triggerstring.Append(t.lineBlue.ToString(Program.Culture));
                        triggerstring.Append(":");
                        break;
                    }
                    triggerstring.Append(t.Start.ToString(Program.Culture));
                    triggerstring.Append(":");
                    triggerstring.Append(t.End.ToString(Program.Culture));
                }
                if (trk.Triggers.Count > 0) //If here are not trigger don't add triggers entry
                {
                    metadata.Add(TrackMetadata.triggers + "=" + triggerstring.ToString());
                }
                bw.Write((short)metadata.Count);
                foreach (var str in metadata)
                {
                    WriteString(bw, str);
                }
            }
            return(filename);
        }