private static int HandleArguments(string[] args)
        {
            var    Ops         = new List <Modes>();
            string Filename    = null;
            string SessionName = null;

            if (args.Contains("/?"))
            {
                Help();
                return(RET.HELP);
            }
            for (var i = 0; i < args.Length; i++)
            {
                var arg = args[i];
                Log.Write("{0}: processing argument: {1}", nameof(HandleArguments), arg);
                switch (arg.ToLower())
                {
                case "/verify":
                    Ops.Add(Modes.Verify);
                    break;

                case "/list":
                    Ops.Add(Modes.List);
                    break;

                case "/pack":
                    Ops.Add(Modes.Pack);
                    break;

                case "/render":
                    Ops.Add(Modes.Render);
                    break;

                case "/info":
                    Ops.Add(Modes.Info);
                    break;

                case "/rename":
                    Ops.Add(Modes.RenameSession);
                    if (i < args.Length - 1)
                    {
                        SessionName = args[++i];
                    }
                    else
                    {
                        Log.Write("{0}: /rename requires a new session name", nameof(HandleArguments));
                        Console.WriteLine("/rename requires a new session name");
                        return(RET.ARG);
                    }
                    break;

                default:
                    if (string.IsNullOrEmpty(Filename))
                    {
                        Filename = arg;
                    }
                    else
                    {
                        Log.Write("{0}: unknown argument: {1}", nameof(HandleArguments), arg);
                        Console.WriteLine("Unknown argument: {0}", arg);
                        return(RET.ARG);
                    }
                    break;
                }
            }

            if (Ops.Count == 0 && args.Length < 2)
            {
                return(RET.UI);
            }

            Tools.AllocConsole();

            if (string.IsNullOrEmpty(Filename))
            {
                Log.Write("{0}: No file name argument supplied", nameof(HandleArguments));
                Console.WriteLine("No file name argument supplied");
                return(RET.ARG);
            }

            Ops = Ops.Distinct().ToList();

            var        Changes = false;
            var        IsGz    = false;
            SaveFile   SF      = null;
            FileStream FS      = null;

            try
            {
                FS = File.Open(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Unable to open input file");
                Log.Write("{0}: Unable to open input file", nameof(HandleArguments));
                Log.Write(ex);
                return(RET.IO);
            }
            using (FS)
            {
                IsGz = Tools.IsGzFile(FS);
                try
                {
                    SF = SaveFile.Open(FS);
                    if (SF == null)
                    {
                        throw new InvalidDataException("The file is not a valid satisfactory save game");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Invalid game file");
                    Log.Write("{0}: Invalid game file", nameof(HandleArguments));
                    Log.Write(ex);
                    return(RET.IO);
                }


                if (Ops.Contains(Modes.Verify))
                {
                    Log.Write("{0}: Verifying file", nameof(HandleArguments));
                    //Verify does nothing on its own
                    Check(SF.PlayTime.Ticks >= 0, "Positive play time");
                    Check(Tools.IsMatch(SF.SessionName, @"^[\w\.\- ]{1,31}$"), "Non-Problematic Session Name");
                    Check(SF.LevelType == SaveFile.DEFAULT_LEVEL_TYPE, $"Level type is '{SaveFile.DEFAULT_LEVEL_TYPE}'");
                    Check(SF.SaveDate.ToUniversalTime() < DateTime.UtcNow, "Date in past");
                    foreach (var key in "sessionName Visibility startloc".Split(' '))
                    {
                        Check(SF.Properties.ContainsKey(key), $"Header contains field '{key}'");
                    }
                    //Don't double error with the previous one
                    if (SF.Properties.ContainsKey("sessionName"))
                    {
                        Check(SF.Properties["sessionName"] == SF.SessionName, "Both session names match");
                    }
                    else
                    {
                        Console.WriteLine("[SKIP]: Both session names match");
                    }
                }

                if (Ops.Contains(Modes.List))
                {
                    Log.Write("{0}: Printing item list", nameof(HandleArguments));
                    foreach (var e in SF.Entries.GroupBy(m => m.ObjectData.Name).OrderBy(m => m.Key))
                    {
                        Console.WriteLine("{1}\t{0}", e.Key, e.Count());
                    }
                }

                if (Ops.Contains(Modes.Render))
                {
                    var ImgFile = Path.ChangeExtension(Filename, ".png");
                    Log.Write("{0}: Rendering map as original size to {1}", nameof(HandleArguments), ImgFile);
                    Console.WriteLine("Initializing image...");
                    MapRender.Init(-1, -1);
                    Console.WriteLine("Rendering file...");
                    using (var IMG = MapRender.RenderFile(SF, 8.192))
                    {
                        Console.WriteLine("Saving image...");
                        IMG.Save(ImgFile);
                    }
                }

                if (Ops.Contains(Modes.Info))
                {
                    Log.Write("{0}: Showing game info", nameof(HandleArguments));
                    Console.WriteLine("Save File Size:\t{0}", FS.Position);
                    Console.WriteLine("Build Version:\t{0}", SF.BuildVersion);
                    Console.WriteLine("Save Version:\t{0}", SF.SaveVersion);
                    Console.WriteLine("Header Version:\t{0}", SF.SaveHeaderVersion);
                    Console.WriteLine("Session Name:\t{0}", SF.SessionName);
                    Console.WriteLine("Save Date:\t{0}", SF.SaveDate);
                    Console.WriteLine("Play Time:\t{0}", SF.PlayTime);
                    foreach (var KV in SF.Properties)
                    {
                        Console.WriteLine("{0}:\t{1}", KV.Key, KV.Value);
                    }
                    Console.WriteLine("Object Count:\t{0}", SF.Entries.Count);
                    Console.WriteLine("String List:\t{0}", SF.StringList.Count);
                }

                if (Ops.Contains(Modes.RenameSession))
                {
                    Log.Write("{0}: Renaming session to {1}", nameof(HandleArguments), SessionName);
                    SF.SetSessionName(SessionName);
                    Changes = true;
                }

                if (Ops.Contains(Modes.Pack))
                {
                    string     NewFile;
                    FileStream OUT;
                    FS.Seek(0, SeekOrigin.Begin);
                    if (IsGz)
                    {
                        if (Filename.ToLower().EndsWith(".sav.gz"))
                        {
                            NewFile = Path.ChangeExtension(Filename, null);
                        }
                        else
                        {
                            NewFile = Path.ChangeExtension(Filename, ".sav");
                        }
                    }
                    else
                    {
                        NewFile = Filename + ".gz";
                    }
                    try
                    {
                        OUT = File.Create(NewFile);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Can't create output file");
                        Log.Write("{0}: Can't create {1}", nameof(HandleArguments), NewFile);
                        Log.Write(ex);
                        return(RET.IO);
                    }
                    Log.Write("{0}: {1} file", nameof(HandleArguments), IsGz ? "Compressing" : "Decompressing");
                    using (OUT)
                    {
                        if (IsGz)
                        {
                            Compression.DecompressStream(FS, OUT);
                        }
                        else
                        {
                            Compression.CompressStream(FS, OUT);
                        }
                    }
                    Log.Write("{0}: {1} file OK", nameof(HandleArguments), IsGz ? "Compressing" : "Decompressing");
                }
                if (Changes)
                {
                    Log.Write("{0}: Writing back changes", nameof(HandleArguments));
                    FS.Seek(0, SeekOrigin.Begin);
                    SF.Export(FS);
                    FS.Flush();
                    FS.SetLength(FS.Position);
                }
            }

            return(RET.SUCCESS);
        }
        public frmMain(string InitialFile = null)
        {
            SettingsFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "settings.xml");
            if (File.Exists(SettingsFile))
            {
                try
                {
                    S = Settings.Load(File.ReadAllText(SettingsFile));
                }
                catch (Exception ex)
                {
                    Log.Write(new Exception("Unable to load the settings", ex));
                    Tools.E($"Unable to load your settings. Defaults will be applied. Reason:\r\n{ex.Message}", "Settings Loader");
                    S = new Settings();
                }
            }
            else
            {
                Log.Write("{0}: Creating settings for first run", GetType().Name);
                S = new Settings();
            }

            InitializeComponent();

            MapRender.MapForm = this;

            //Don't block the application startup with the image rendering stuff
            Thread T = new Thread(delegate()
            {
                Log.Write("{0}: Rendering map", GetType().Name);
                MapRender.Init();
                var img = MapRender.GetMap();
                Invoke((MethodInvoker) delegate
                {
                    BackgroundImage = img;
                    if (S.ShowWelcomeMessage)
                    {
                        S.ShowWelcomeMessage = false;
                        Tools.ShowHelp("Welcome");
                    }
                    if (!string.IsNullOrEmpty(InitialFile))
                    {
                        try
                        {
                            OpenFile(InitialFile);
                        }
                        catch (Exception ex)
                        {
                            Log.Write(new Exception("Unable to load file from command line argument", ex));
                            Tools.E($"Unable to open {InitialFile}\r\n{ex.Message}", "File error");
                        }
                    }
                    Log.Write("{0}: Initializer complete", GetType().Name);
                });
            });

            T.Start();

            SFD.InitialDirectory = OFD.InitialDirectory = Program.SaveDirectory;
            Tools.SetupEscHandler(this);
#if DEBUG
            Log.Write("{0}: Enabling debug menu items", GetType().Name);
            //Enable not fully implemented items
            inventoriesToolStripMenuItem.Visible = true;
#endif
        }
        /// <summary>
        /// Form constructor
        /// </summary>
        /// <param name="InitialFile">Optional file to open after startup</param>
        public frmMain(string InitialFile = null)
        {
            RespectManagerSetting = string.IsNullOrEmpty(InitialFile);
            SettingsFile          = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "settings.xml");
            if (File.Exists(SettingsFile))
            {
                try
                {
                    S = Settings.Load(File.ReadAllText(SettingsFile));
                }
                catch (Exception ex)
                {
                    Log.Write(new Exception("Unable to load the settings", ex));
                    Tools.E($"Unable to load your settings. Defaults will be applied. Reason:\r\n{ex.Message}", "Settings Loader");
                    S = new Settings();
                }
            }
            else
            {
                Log.Write("{0}: Creating settings for first run", GetType().Name);
                S = new Settings();
            }
            //Set up feature reporter
            if (!S.DisableUsageReport)
            {
                if (S.ReportId == Guid.Empty || S.UseRandomId)
                {
                    S.ReportId = Guid.NewGuid();
                }
                FeatureReport.Id = S.ReportId;
            }
            else
            {
                //Make sure the Id id is always unset
                FeatureReport.Id = S.ReportId = Guid.Empty;
            }

            InitializeComponent(); //!!!Read+Write form components only after this line!!!

            //Always start from the save file directory
            //We can't set this directly in the properties because the path is dynamic
            OFD.InitialDirectory = Program.SaveDirectory;

            OriginalTitle = Text;

            //Enable the audio extractor only if QuickPlay is present
            if (QuickPlay.HasQuickPlay)
            {
                extractAudioToolStripMenuItem.Enabled = true;
            }

            //Register this as the map rendering form
            MapRender.MapForm = this;

            //Don't block the application startup with the image rendering stuff
            Thread T = new Thread(delegate()
            {
                Log.Write("{0}: Rendering initial map", GetType().Name);
                try
                {
                    MapRender.Init();
                }
                catch (Exception ex)
                {
                    Log.Write("{0}: Rendering initial map failed", GetType().Name);
                    Log.Write(ex);
                    BackgroundImage = new Bitmap(1, 1);
                    DisableImageRendering();
                    return;
                }
                var img = MapRender.GetMap();
                Invoke((MethodInvoker) delegate
                {
                    BackgroundImage = img;
                    //Open initial file if supplied
                    if (!string.IsNullOrEmpty(InitialFile))
                    {
                        try
                        {
                            FeatureReport.Used(FeatureReport.Feature.OpenByCommandLine);
                            OpenFile(InitialFile);
                        }
                        catch (Exception ex)
                        {
                            Log.Write(new Exception("Unable to load file from command line argument", ex));
                            Tools.E($"Unable to open {InitialFile}\r\n{ex.Message}", "File error");
                        }
                    }
                    Log.Write("{0}: Initializer complete", GetType().Name);
                });
            });

            T.Start();

            SFD.InitialDirectory = OFD.InitialDirectory = Program.SaveDirectory;
            Tools.SetupKeyHandlers(this);
            HandleSettingsChange();
#if DEBUG
            Log.Write("{0}: Enabling debug menu items", GetType().Name);
            //Enable not fully implemented items
            inventoriesToolStripMenuItem.Visible = true;
            removeRocksToolStripMenuItem.Visible = true;
#endif
        }