Beispiel #1
0
 public void UpdateChecks(string c)
 {
     updating = true;
     try
     {
         tJunkLocationsString.Text = c;
         CustomJunkLocationsString = c;
         CustomJunkLocations.Clear();
         string[] v  = c.Split('-');
         int[]    vi = new int[ItemGroupCount];
         if (v.Length != vi.Length)
         {
             ExternalLabel = "Invalid junk locations string";
             return;
         }
         for (int i = 0; i < ItemGroupCount; i++)
         {
             if (v[ItemGroupCount - 1 - i] != "")
             {
                 vi[i] = Convert.ToInt32(v[ItemGroupCount - 1 - i], 16);
             }
         }
         for (int i = 0; i < 32 * ItemGroupCount; i++)
         {
             int j = i / 32;
             int k = i % 32;
             if (((vi[j] >> k) & 1) > 0)
             {
                 if (i >= ItemUtils.AllLocations().Count())
                 {
                     throw new IndexOutOfRangeException();
                 }
                 CustomJunkLocations.Add(_junkLocations[i]);
             }
         }
         foreach (ListViewItem l in lJunkLocations.Items)
         {
             if (CustomJunkLocations.Contains(_junkLocations[l.Index]))
             {
                 l.Checked = true;
             }
             else
             {
                 l.Checked = false;
             }
         }
         ExternalLabel = $"{CustomJunkLocations.Count}/{_junkLocations.Count} locations selected";
     }
     catch
     {
         CustomJunkLocations.Clear();
         ExternalLabel = "Invalid junk locations string";
     }
     finally
     {
         updating = false;
     }
 }
Beispiel #2
0
 public void UpdateChecks(string c)
 {
     updating = true;
     try
     {
         tStartingItemsString.Text = c;
         ItemListString            = c;
         ItemList.Clear();
         string[] v  = c.Split('-');
         int[]    vi = new int[_itemGroupCount];
         if (v.Length != vi.Length)
         {
             ExternalLabel = "Invalid custom starting item string";
             return;
         }
         for (int i = 0; i < _itemGroupCount; i++)
         {
             if (v[_itemGroupCount - 1 - i] != "")
             {
                 vi[i] = Convert.ToInt32(v[_itemGroupCount - 1 - i], 16);
             }
         }
         for (int i = 0; i < 32 * _itemGroupCount; i++)
         {
             int j = i / 32;
             int k = i % 32;
             if (((vi[j] >> k) & 1) > 0)
             {
                 if (i >= ItemUtils.AllLocations().Count())
                 {
                     throw new IndexOutOfRangeException();
                 }
                 ItemList.Add(BaseItemList[i]);
             }
         }
         foreach (ListViewItem l in lStartingItems.Items)
         {
             if (ItemList.Contains((Item)l.Tag))
             {
                 l.Checked = true;
             }
             else
             {
                 l.Checked = false;
             }
         }
         ExternalLabel = $"{ItemList.Count}/{BaseItemList.Count} items randomized";
     }
     catch
     {
         ItemList.Clear();
         ExternalLabel = "Invalid custom starting item string";
     }
     finally
     {
         updating = false;
     }
 }
Beispiel #3
0
 public void UpdateChecks(string c)
 {
     updating = true;
     try
     {
         tSetting.Text = c;
         _settings.CustomItemListString = c;
         _settings.CustomItemList.Clear();
         string[] v  = c.Split('-');
         int[]    vi = new int[13];
         if (v.Length != vi.Length)
         {
             _settings.CustomItemList.Add(-1);
             return;
         }
         for (int i = 0; i < 13; i++)
         {
             if (v[12 - i] != "")
             {
                 vi[i] = Convert.ToInt32(v[12 - i], 16);
             }
         }
         for (int i = 0; i < 32 * 13; i++)
         {
             int j = i / 32;
             int k = i % 32;
             if (((vi[j] >> k) & 1) > 0)
             {
                 if (i >= ItemUtils.AllLocations().Count())
                 {
                     throw new IndexOutOfRangeException();
                 }
                 _settings.CustomItemList.Add(i);
             }
         }
         foreach (ListViewItem l in lItems.Items)
         {
             if (_settings.CustomItemList.Contains(l.Index))
             {
                 l.Checked = true;
             }
             else
             {
                 l.Checked = false;
             }
         }
     }
     catch
     {
         _settings.CustomItemList.Clear();
         _settings.CustomItemList.Add(-1);
     }
     finally
     {
         updating = false;
     }
 }
Beispiel #4
0
 private void UpdateCustomItemAmountLabel()
 {
     if (_settings.CustomItemList.Contains(-1))
     {
         lCustomItemAmount.Text = "Invalid custom item string";
     }
     else
     {
         lCustomItemAmount.Text = $"{_settings.CustomItemList.Count}/{ItemUtils.AllLocations().Count()} items randomized";
     }
 }
Beispiel #5
0
        private void bAddLevel_Click(object sender, EventArgs e)
        {
            var form = new ItemSelectorForm(ItemUtils.AllLocations(), Enumerable.Empty <Item>());

            form.ShowDialog();

            if (form.DialogResult == DialogResult.OK && form.ReturnItems.Count > 0)
            {
                Result.Add(form.ReturnItems);

                tHintPriorities.SuspendLayout();
                AddItems(form.ReturnItems, false);
                tHintPriorities.ResumeLayout();
            }
        }
Beispiel #6
0
        public JunkLocationEditForm()
        {
            InitializeComponent();

            _junkLocations = ItemUtils.AllLocations().ToList();

            PrintToListView();

            if (CustomJunkLocations != null)
            {
                UpdateString(CustomJunkLocations);
                ExternalLabel = $"{CustomJunkLocations.Count}/{_junkLocations.Count} items selected";
            }
            else
            {
                tJunkLocationsString.Text = "--";
            }
        }
Beispiel #7
0
        private static List <int> ConvertIntString(string c)
        {
            var result = new List <int>();

            if (string.IsNullOrWhiteSpace(c))
            {
                return(result);
            }
            try
            {
                result.Clear();
                string[] v  = c.Split('-');
                int[]    vi = new int[13];
                if (v.Length != vi.Length)
                {
                    return(null);
                }
                for (int i = 0; i < 13; i++)
                {
                    if (v[12 - i] != "")
                    {
                        vi[i] = Convert.ToInt32(v[12 - i], 16);
                    }
                }
                for (int i = 0; i < 32 * 13; i++)
                {
                    int j = i / 32;
                    int k = i % 32;
                    if (((vi[j] >> k) & 1) > 0)
                    {
                        if (i >= ItemUtils.AllLocations().Count())
                        {
                            throw new IndexOutOfRangeException();
                        }
                        result.Add(i);
                    }
                }
            }
            catch
            {
                return(null);
            }
            return(result);
        }
Beispiel #8
0
        public JunkLocationEditForm()
        {
            InitializeComponent();

            _junkLocations = ItemUtils.AllLocations().ToList();

            foreach (var item in _junkLocations)
            {
                lJunkLocations.Items.Add(item.Location());
            }

            if (CustomJunkLocations != null)
            {
                UpdateString(CustomJunkLocations);
                ExternalLabel = $"{CustomJunkLocations.Count}/{_junkLocations.Count} items selected";
            }
            else
            {
                tJunkLocationsString.Text = "--";
            }
        }
Beispiel #9
0
        private void editButton_Click(object sender, EventArgs e)
        {
            var control = (Control)sender;
            var index   = tHintPriorities.GetRow(control);

            var form = new ItemSelectorForm(ItemUtils.AllLocations(), Result[index]);

            form.ShowDialog();

            if (form.DialogResult == DialogResult.OK)
            {
                if (form.ReturnItems.Count > 0)
                {
                    Result[index] = form.ReturnItems;
                    var label = (Label)tHintPriorities.GetControlFromPosition(3, index);
                    label.Text = string.Join(", ", Result[index].Select(item => item.Location()));
                }
                else
                {
                    DeleteRow(index);
                }
            }
        }
Beispiel #10
0
        static int Main(string[] args)
        {
            Dictionary <string, List <string> > argsDictionary;

            if (args.Length == 1 && File.Exists(args[0]) && Path.GetExtension(args[0]) == ".mmr")
            {
                argsDictionary = new Dictionary <string, List <string> >
                {
                    { "-inputpatch", args.ToList() }
                };
            }
            else
            {
                argsDictionary = DictionaryHelper.FromProgramArguments(args);
            }
            if (argsDictionary.ContainsKey("-help"))
            {
                Console.WriteLine("All arguments are optional.");
                var helpTexts = new Dictionary <string, string>
                {
                    { "-help", "See this help text." },
                    { "-settings <path>", "Path to a settings JSON file. Only the GameplaySettings will be loaded. Other settings will be loaded from your default settings.json file." },
                    { "-outputpatch", "Output a .mmr patch file." },
                    { "-inputpatch <path>", "Path to a .mmr patch file to apply." },
                    { "-spoiler", "Output a .txt spoiler log." },
                    { "-html", "Output a .html item tracker." },
                    { "-rom", "Output a .z64 ROM file." },
                    { "-seed", "Set the seed for the randomizer." },
                    { "-output <path>", "Path to output the output ROM. Other outputs will be based on the filename in this path. If omitted, will output to \"output/{timestamp}.z64\"" },
                    { "-input <path>", "Path to the input Majora's Mask (U) ROM. If omitted, will try to use \"input.z64\"." },
                    { "-save", "Save the settings to the default settings.json file." },
                };
                foreach (var kvp in helpTexts)
                {
                    Console.WriteLine("{0, -17} {1}", kvp.Key, kvp.Value);
                }
                Console.WriteLine("settings.json details:");
                Console.WriteLine(GetSettingPath(cfg => cfg.GameplaySettings) + ":");
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.LogicMode));
                Console.WriteLine(GetArrayValueDescription(nameof(GameplaySettings.ItemCategoriesRandomized), Enum.GetValues <ItemCategory>().Where(c => c > 0).Select(c => c.ToString())));
                Console.WriteLine(GetArrayValueDescription(nameof(GameplaySettings.LocationCategoriesRandomized), Enum.GetValues <LocationCategory>().Where(c => c > 0).Select(c => c.ToString())));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.DamageMode));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.DamageEffect));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.MovementMode));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.FloorType));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.ClockSpeed));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.BlastMaskCooldown));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.GossipHintStyle));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.SmallKeyMode));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.BossKeyMode));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.StrayFairyMode));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.PriceMode));
                Console.WriteLine(GetSettingDescription(nameof(GameplaySettings.EnabledTricks), "Array of trick IDs."));
                Console.WriteLine(GetSettingPath(cfg => cfg.GameplaySettings.ShortenCutsceneSettings) + ":");
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.ShortenCutsceneSettings.General));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.ShortenCutsceneSettings.BossIntros));
                Console.WriteLine(GetSettingPath(cfg => cfg.CosmeticSettings) + ":");
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.CosmeticSettings.TatlColorSchema));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.CosmeticSettings.Music));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.CosmeticSettings.DisableCombatMusic));
                Console.WriteLine(GetArrayValueDescription(nameof(CosmeticSettings.Instruments), Enum.GetNames <Instrument>()));
                Console.WriteLine(GetArrayValueDescription(nameof(CosmeticSettings.HeartsSelection), ColorSelectionManager.Hearts.GetItems().Select(csi => csi.Name)));
                Console.WriteLine(GetArrayValueDescription(nameof(CosmeticSettings.MagicSelection), ColorSelectionManager.MagicMeter.GetItems().Select(csi => csi.Name)));
                Console.WriteLine(GetSettingPath(cfg => cfg.CosmeticSettings.DPad.Pad) + ":");
                Console.WriteLine(GetEnumArraySettingDescription(cfg => cfg.CosmeticSettings.DPad.Pad.Values) + " Array length of 4.");
                return(0);
            }
            var configuration = LoadSettings();

            if (configuration == null)
            {
                Console.WriteLine("Default settings file not found. Generating...");
                configuration = new Configuration
                {
                    CosmeticSettings = new CosmeticSettings(),
                    GameplaySettings = new GameplaySettings
                    {
                        ShortenCutsceneSettings = new ShortenCutsceneSettings(),
                    },
                    OutputSettings = new OutputSettings()
                    {
                        InputROMFilename = "input.z64",
                    },
                };
                SaveSettings(configuration);
                Console.WriteLine($"Generated {Path.ChangeExtension(DEFAULT_SETTINGS_FILENAME, SETTINGS_EXTENSION)}. Edit it to set your settings.");
            }
            var settingsPath = argsDictionary.GetValueOrDefault("-settings")?.FirstOrDefault();

            if (settingsPath != null)
            {
                var loadedConfiguration = LoadSettings(settingsPath);
                if (loadedConfiguration == null)
                {
                    Console.WriteLine($"File not found \"{settingsPath}\".");
                    return(-1);
                }
                if (loadedConfiguration.GameplaySettings == null)
                {
                    Console.WriteLine($"Error loading GameplaySettings from \"{settingsPath}\".");
                    return(-1);
                }
                configuration.GameplaySettings = loadedConfiguration.GameplaySettings;
                Console.WriteLine($"Loaded GameplaySettings from \"{settingsPath}\".");
            }

            if (configuration.GameplaySettings.ItemCategoriesRandomized != null || configuration.GameplaySettings.LocationCategoriesRandomized != null)
            {
                var items = new List <Item>();
                if (configuration.GameplaySettings.ItemCategoriesRandomized != null)
                {
                    items.AddRange(ItemUtils.ItemsByItemCategory().Where(kvp => configuration.GameplaySettings.ItemCategoriesRandomized.Contains(kvp.Key)).SelectMany(kvp => kvp.Value));
                    configuration.GameplaySettings.ItemCategoriesRandomized = null;
                }
                if (configuration.GameplaySettings.LocationCategoriesRandomized != null)
                {
                    items.AddRange(ItemUtils.ItemsByLocationCategory().Where(kvp => configuration.GameplaySettings.LocationCategoriesRandomized.Contains(kvp.Key)).SelectMany(kvp => kvp.Value));
                    configuration.GameplaySettings.LocationCategoriesRandomized = null;
                }
                configuration.GameplaySettings.CustomItemList.Clear();
                foreach (var item in items)
                {
                    configuration.GameplaySettings.CustomItemList.Add(item);
                }
            }
            else
            {
                configuration.GameplaySettings.CustomItemList = ConvertItemString(ItemUtils.AllLocations().ToList(), configuration.GameplaySettings.CustomItemListString).ToHashSet();
            }

            configuration.GameplaySettings.CustomStartingItemList = ConvertItemString(ItemUtils.StartingItems().Where(item => !item.Name().Contains("Heart")).ToList(), configuration.GameplaySettings.CustomStartingItemListString);
            configuration.GameplaySettings.CustomJunkLocations    = ConvertItemString(ItemUtils.AllLocations().ToList(), configuration.GameplaySettings.CustomJunkLocationsString);

            configuration.OutputSettings.InputPatchFilename  = argsDictionary.GetValueOrDefault("-inputpatch")?.SingleOrDefault();
            configuration.OutputSettings.GeneratePatch      |= argsDictionary.ContainsKey("-outputpatch");
            configuration.OutputSettings.GenerateSpoilerLog |= argsDictionary.ContainsKey("-spoiler");
            configuration.OutputSettings.GenerateHTMLLog    |= argsDictionary.ContainsKey("-html");
            configuration.OutputSettings.GenerateROM        |= argsDictionary.ContainsKey("-rom");

            int seed;

            if (argsDictionary.ContainsKey("-seed"))
            {
                seed = int.Parse(argsDictionary["-seed"][0]);
            }
            else
            {
                seed = new Random().Next();
            }


            var outputArg = argsDictionary.GetValueOrDefault("-output");

            if (outputArg != null)
            {
                if (outputArg.Count > 1)
                {
                    throw new ArgumentException("Invalid argument.", "-output");
                }
                configuration.OutputSettings.OutputROMFilename = outputArg.SingleOrDefault();
            }
            else if (!string.IsNullOrWhiteSpace(configuration.OutputSettings.InputPatchFilename))
            {
                configuration.OutputSettings.OutputROMFilename = Path.ChangeExtension(configuration.OutputSettings.InputPatchFilename, "z64");
            }
            configuration.OutputSettings.OutputROMFilename ??= "output/";
            if (!Path.IsPathRooted(configuration.OutputSettings.OutputROMFilename))
            {
                configuration.OutputSettings.OutputROMFilename = Path.Combine(Directory.GetCurrentDirectory(), configuration.OutputSettings.OutputROMFilename);
            }
            var directory = Path.GetDirectoryName(configuration.OutputSettings.OutputROMFilename);
            var filename  = Path.GetFileName(configuration.OutputSettings.OutputROMFilename);

            if (!Directory.Exists(directory))
            {
                Console.WriteLine($"Directory not found '{directory}'");
                return(-1);
            }
            if (string.IsNullOrWhiteSpace(filename))
            {
                filename = FileUtils.MakeFilenameValid($"MMR-{typeof(Randomizer.Randomizer).Assembly.GetName().Version}-{DateTime.UtcNow:o}") + ".z64";
            }
            else if (Path.GetExtension(filename) != ".z64")
            {
                filename = Path.ChangeExtension(filename, "z64");
            }
            configuration.OutputSettings.OutputROMFilename = Path.Combine(directory, filename);

            var inputArg = argsDictionary.GetValueOrDefault("-input");

            if (inputArg != null)
            {
                if (inputArg.Count > 1)
                {
                    throw new ArgumentException("Invalid argument.", "-input");
                }
                configuration.OutputSettings.InputROMFilename = inputArg.SingleOrDefault();
            }
            configuration.OutputSettings.InputROMFilename ??= "input.z64";

            if (argsDictionary.ContainsKey("-save"))
            {
                SaveSettings(configuration);
            }

            var validationResult = configuration.GameplaySettings.Validate() ?? configuration.OutputSettings.Validate();

            if (validationResult != null)
            {
                Console.WriteLine(validationResult);
                return(-1);
            }

            try
            {
                string result;
                using (var progressBar = new ProgressBar())
                {
                    //var progressReporter = new TextWriterProgressReporter(Console.Out);
                    var progressReporter = new ProgressBarProgressReporter(progressBar);
                    result = ConfigurationProcessor.Process(configuration, seed, progressReporter);
                }
                if (result != null)
                {
                    Console.Error.WriteLine(result);
                }
                else
                {
                    Console.WriteLine("Generation complete!");
                }
                return(result == null ? 0 : -1);
            }
            catch (Exception e)
            {
                Console.Error.Write(e.Message);
                Console.Error.Write(e.StackTrace);
                return(-1);
            }
        }
Beispiel #11
0
        static int Main(string[] args)
        {
            var argsDictionary = DictionaryHelper.FromProgramArguments(args);
            var settings       = new GameplaySettings();
            var outputSettings = new OutputSettings();

            settings.Update("fz1mr--16psr-lc-f");
            settings.CustomItemListString         = "81-80000000----3fff-ffffffff-ffffffff-fe000000-6619ff-7fffffff-f378ffff-ffffffff";
            settings.CustomItemList               = ConvertIntString(settings.CustomItemListString);
            settings.CustomStartingItemListString = "-3fc04000-";
            settings.CustomStartingItemList       = ConvertItemString(ItemUtils.StartingItems().Where(item => !item.Name().Contains("Heart")).ToList(), settings.CustomStartingItemListString);
            settings.CustomJunkLocationsString    = "----------200000--f000";
            settings.CustomJunkLocations          = ConvertItemString(ItemUtils.AllLocations().ToList(), settings.CustomJunkLocationsString);

            outputSettings.GeneratePatch      = argsDictionary.ContainsKey("-patch");
            outputSettings.GenerateSpoilerLog = argsDictionary.ContainsKey("-spoiler");
            outputSettings.GenerateHTMLLog    = argsDictionary.ContainsKey("-html");
            outputSettings.GenerateROM        = argsDictionary.ContainsKey("-rom");

            int seed;

            if (argsDictionary.ContainsKey("-seed"))
            {
                seed = int.Parse(argsDictionary["-seed"][0]);
            }
            else
            {
                seed = new Random().Next();
            }

            var outputArg = argsDictionary.GetValueOrDefault("-output");

            if (outputArg != null)
            {
                if (outputArg.Count > 1)
                {
                    throw new ArgumentException("Invalid argument.", "-output");
                }
                outputSettings.OutputROMFilename = outputArg.SingleOrDefault();
            }
            outputSettings.OutputROMFilename ??= Path.Combine("output", FileUtils.MakeFilenameValid(DateTime.UtcNow.ToString("o")));

            var inputArg = argsDictionary.GetValueOrDefault("-input");

            if (inputArg != null)
            {
                if (inputArg.Count > 1)
                {
                    throw new ArgumentException("Invalid argument.", "-input");
                }
                outputSettings.InputROMFilename = inputArg.SingleOrDefault();
            }
            outputSettings.InputROMFilename ??= "input.z64";

            var validationResult = settings.Validate();

            if (validationResult != null)
            {
                Console.WriteLine(validationResult);
                return(-1);
            }

            try
            {
                string result;
                using (var progressBar = new ProgressBar())
                {
                    //var progressReporter = new TextWriterProgressReporter(Console.Out);
                    var progressReporter = new ProgressBarProgressReporter(progressBar);
                    result = ConfigurationProcessor.Process(new Configuration
                    {
                        GameplaySettings = settings,
                        OutputSettings   = outputSettings,
                    }, seed, progressReporter);
                }
                if (result != null)
                {
                    Console.Error.WriteLine(result);
                }
                else
                {
                    Console.WriteLine("Generation complete!");
                }
                return(result == null ? 0 : -1);
            }
            catch (Exception e)
            {
                Console.Error.Write(e.Message);
                Console.Error.Write(e.StackTrace);
                return(-1);
            }
        }
Beispiel #12
0
        static int Main(string[] args)
        {
            var argsDictionary = DictionaryHelper.FromProgramArguments(args);

            if (argsDictionary.ContainsKey("-help"))
            {
                Console.WriteLine("All arguments are optional.");
                var helpTexts = new Dictionary <string, string>
                {
                    { "-help", "See this help text." },
                    { "-settings <path>", "Path to a settings JSON file. Only the GameplaySettings will be loaded. Other settings will be loaded from your default settings.json file." },
                    { "-patch", "Output a .mmr patch file." },
                    { "-spoiler", "Output a .txt spoiler log." },
                    { "-html", "Output a .html item tracker." },
                    { "-rom", "Output a .z64 ROM file." },
                    { "-seed", "Set the seed for the randomizer." },
                    { "-output <path>", "Path to output the output ROM. Other outputs will be based on the filename in this path. If omitted, will output to \"output/{timestamp}.z64\"" },
                    { "-input <path>", "Path to the input Majora's Mask (U) ROM. If omitted, will try to use \"input.z64\"." },
                    { "-save", "Save the settings to the default settings.json file." },
                };
                foreach (var kvp in helpTexts)
                {
                    Console.WriteLine("{0, -17} {1}", kvp.Key, kvp.Value);
                }
                Console.WriteLine("settings.json details:");
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.LogicMode));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.DamageMode));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.DamageEffect));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.MovementMode));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.FloorType));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.ClockSpeed));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.BlastMaskCooldown));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.GameplaySettings.GossipHintStyle));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.CosmeticSettings.TatlColorSchema));
                Console.WriteLine(GetEnumSettingDescription(cfg => cfg.CosmeticSettings.Music));
                Console.WriteLine(GetEnumArraySettingDescription(cfg => cfg.CosmeticSettings.DPad.Pad.Values) + " Array length of 4.");
                Console.WriteLine(GetArrayValueDescription(nameof(CosmeticSettings.HeartsSelection), ColorSelectionManager.Hearts.GetItems().Select(csi => csi.Name)));
                Console.WriteLine(GetArrayValueDescription(nameof(CosmeticSettings.MagicSelection), ColorSelectionManager.MagicMeter.GetItems().Select(csi => csi.Name)));
                Console.WriteLine(GetSettingDescription(nameof(GameplaySettings.EnabledTricks), "Array of trick IDs."));
                return(0);
            }
            var configuration = LoadSettings();

            if (configuration == null)
            {
                Console.WriteLine("Default settings file not found. Generating...");
                configuration = new Configuration
                {
                    CosmeticSettings = new CosmeticSettings(),
                    GameplaySettings = new GameplaySettings(),
                    OutputSettings   = new OutputSettings()
                    {
                        InputROMFilename = "input.z64",
                    },
                };
                SaveSettings(configuration);
                Console.WriteLine($"Generated {Path.ChangeExtension(DEFAULT_SETTINGS_FILENAME, SETTINGS_EXTENSION)}. Edit it to set your settings.");
            }
            var settingsPath = argsDictionary.GetValueOrDefault("-settings")?.FirstOrDefault();

            if (settingsPath != null)
            {
                var loadedConfiguration = LoadSettings(settingsPath);
                if (loadedConfiguration == null)
                {
                    Console.WriteLine($"File not found \"{settingsPath}\".");
                    return(-1);
                }
                if (loadedConfiguration.GameplaySettings == null)
                {
                    Console.WriteLine($"Error loading GameplaySettings from \"{settingsPath}\".");
                    return(-1);
                }
                configuration.GameplaySettings = loadedConfiguration.GameplaySettings;
                Console.WriteLine($"Loaded GameplaySettings from \"{settingsPath}\".");
            }

            configuration.GameplaySettings.CustomItemList         = ConvertIntString(configuration.GameplaySettings.CustomItemListString);
            configuration.GameplaySettings.CustomStartingItemList = ConvertItemString(ItemUtils.StartingItems().Where(item => !item.Name().Contains("Heart")).ToList(), configuration.GameplaySettings.CustomStartingItemListString);
            configuration.GameplaySettings.CustomJunkLocations    = ConvertItemString(ItemUtils.AllLocations().ToList(), configuration.GameplaySettings.CustomJunkLocationsString);

            configuration.OutputSettings.GeneratePatch      |= argsDictionary.ContainsKey("-patch");
            configuration.OutputSettings.GenerateSpoilerLog |= argsDictionary.ContainsKey("-spoiler");
            configuration.OutputSettings.GenerateHTMLLog    |= argsDictionary.ContainsKey("-html");
            configuration.OutputSettings.GenerateROM        |= argsDictionary.ContainsKey("-rom");

            int seed;

            if (argsDictionary.ContainsKey("-seed"))
            {
                seed = int.Parse(argsDictionary["-seed"][0]);
            }
            else
            {
                seed = new Random().Next();
            }

            var outputArg = argsDictionary.GetValueOrDefault("-output");

            if (outputArg != null)
            {
                if (outputArg.Count > 1)
                {
                    throw new ArgumentException("Invalid argument.", "-output");
                }
                configuration.OutputSettings.OutputROMFilename = outputArg.SingleOrDefault();
            }
            configuration.OutputSettings.OutputROMFilename ??= Path.Combine("output", FileUtils.MakeFilenameValid(DateTime.UtcNow.ToString("o")));
            if (Path.GetExtension(configuration.OutputSettings.OutputROMFilename) != ".z64")
            {
                configuration.OutputSettings.OutputROMFilename += ".z64";
            }

            var inputArg = argsDictionary.GetValueOrDefault("-input");

            if (inputArg != null)
            {
                if (inputArg.Count > 1)
                {
                    throw new ArgumentException("Invalid argument.", "-input");
                }
                configuration.OutputSettings.InputROMFilename = inputArg.SingleOrDefault();
            }
            configuration.OutputSettings.InputROMFilename ??= "input.z64";

            if (argsDictionary.ContainsKey("-save"))
            {
                SaveSettings(configuration);
            }

            var validationResult = configuration.GameplaySettings.Validate() ?? configuration.OutputSettings.Validate();

            if (validationResult != null)
            {
                Console.WriteLine(validationResult);
                return(-1);
            }

            try
            {
                string result;
                using (var progressBar = new ProgressBar())
                {
                    //var progressReporter = new TextWriterProgressReporter(Console.Out);
                    var progressReporter = new ProgressBarProgressReporter(progressBar);
                    result = ConfigurationProcessor.Process(configuration, seed, progressReporter);
                }
                if (result != null)
                {
                    Console.Error.WriteLine(result);
                }
                else
                {
                    Console.WriteLine("Generation complete!");
                }
                return(result == null ? 0 : -1);
            }
            catch (Exception e)
            {
                Console.Error.Write(e.Message);
                Console.Error.Write(e.StackTrace);
                return(-1);
            }
        }