Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/coolgirl-multicart/coolgirl-multirom-builder.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2022-11-09 21:54:53 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2022-11-09 21:54:53 +0300
commit83f20d2d335fde90e2f7b5d12e7e556aa1131e57 (patch)
tree1a2fb212d845c3bfc839c1089f4659afe9d0e2cb
parentcad8bacdb39b2ee4065c542382bfe4ce5d58d825 (diff)
Refactoring
-rw-r--r--tools_sources/CoolgirlCombiner/Config.cs268
-rw-r--r--tools_sources/CoolgirlCombiner/Program.cs315
2 files changed, 332 insertions, 251 deletions
diff --git a/tools_sources/CoolgirlCombiner/Config.cs b/tools_sources/CoolgirlCombiner/Config.cs
new file mode 100644
index 0000000..37638c2
--- /dev/null
+++ b/tools_sources/CoolgirlCombiner/Config.cs
@@ -0,0 +1,268 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace com.clusterrr.Famicom.CoolGirl
+{
+ internal class Config
+ {
+ const string DEFAULT_MAPPERS_FILE = @"coolgirl-mappers.json";
+ const string DEFAULT_FIXES_FILE = @"coolgirl-fixes.json";
+ const string DEFAULT_SYMBOLS_FILE = @"coolgirl-symbols.json";
+ public const string commandPrepare = "prepare";
+ public const string commandCombine = "combine";
+ public const string commandBuild = "build";
+
+ public enum CombinerCommand
+ {
+ Prepare,
+ Combine,
+ Build,
+ }
+
+ public enum CombinerLanguage
+ {
+ English,
+ Russian
+ }
+
+ public CombinerCommand Command { get; private set; } = CombinerCommand.Prepare;
+ public string MappersFile { get; private set; }
+ public string FixesFile { get; private set; }
+ public string SymbolsFile { get; private set; }
+ public string NesAsm { get; private set; } = "nesasm";
+ public string NesAsmArgs { get; private set; } = "";
+ public string SourcesDir { get; private set; } = ".";
+ public string? GamesFile { get; private set; } = null;
+ public string? AsmFile { get; private set; } = null;
+ public string OffsetsFile { get; private set; } = "offsets.json";
+ public string? ReportFile { get; private set; } = null;
+ public string? LoaderFile { get; private set; } = null;
+ public string? UnifFile { get; private set; } = null;
+ public string? Nes20File { get; private set; } = null;
+ public string? BinFile { get; private set; } = null;
+ public CombinerLanguage Language { get; private set; } = CombinerLanguage.English;
+ public List<int> BadSectors { get; private set; } = new();
+ public bool NoSort { get; private set; } = false;
+ public uint MaxRomSizeMB { get; private set; } = 256;
+ public uint MaxChrRamSizeKB { get; private set; } = 256;
+
+ private Config()
+ {
+ MappersFile = Path.Combine(Path.GetDirectoryName(AppContext.BaseDirectory) ?? String.Empty, DEFAULT_MAPPERS_FILE);
+ if (!File.Exists(MappersFile) && !OperatingSystem.IsWindows())
+ MappersFile = Path.Combine("/etc", DEFAULT_MAPPERS_FILE);
+ FixesFile = Path.Combine(Path.GetDirectoryName(AppContext.BaseDirectory) ?? String.Empty, DEFAULT_FIXES_FILE);
+ if (!File.Exists(FixesFile) && !OperatingSystem.IsWindows())
+ FixesFile = Path.Combine("/etc", DEFAULT_FIXES_FILE);
+ SymbolsFile
+ = Path.Combine(Path.GetDirectoryName(AppContext.BaseDirectory) ?? String.Empty, DEFAULT_SYMBOLS_FILE);
+ if (!File.Exists(SymbolsFile) && !OperatingSystem.IsWindows())
+ SymbolsFile = Path.Combine("/etc", DEFAULT_SYMBOLS_FILE);
+ }
+
+ // TODO: Replace magic strings with constants
+ public static Config? Parse(string[] args)
+ {
+ Config config = new Config();
+
+ if (args.Length > 0)
+ {
+ string command = args[0].ToLower();
+ switch (command)
+ {
+ case commandPrepare:
+ config.Command = CombinerCommand.Prepare;
+ break;
+ case commandCombine:
+ config.Command = CombinerCommand.Combine;
+ break;
+ case commandBuild:
+ config.Command = CombinerCommand.Build;
+ break;
+ default:
+ if (!string.IsNullOrEmpty(command))
+ Console.WriteLine("Unknown command: " + command);
+ return null;
+ }
+ }
+ else return null;
+ for (int i = 1; i < args.Length; i++)
+ {
+ string param = args[i];
+ while (param.StartsWith("-")) param = param.Substring(1);
+ string value = i < args.Length - 1 ? args[i + 1] : "";
+ switch (param.ToLower())
+ {
+ case "mappers":
+ config.MappersFile = value;
+ i++;
+ break;
+ case "fixes":
+ config.FixesFile = value;
+ i++;
+ break;
+ case "symbols":
+ config.SymbolsFile = value;
+ i++;
+ break;
+ case "games":
+ config.GamesFile = value;
+ i++;
+ break;
+ case "asm":
+ config.AsmFile = value;
+ i++;
+ break;
+ case "offsets":
+ config.OffsetsFile = value;
+ i++;
+ break;
+ case "report":
+ config.ReportFile = value;
+ i++;
+ break;
+ case "loader":
+ config.LoaderFile = value;
+ i++;
+ break;
+ case "unif":
+ config.UnifFile = value;
+ i++;
+ break;
+ case "nes20":
+ config.Nes20File = value;
+ i++;
+ break;
+ case "bin":
+ config.BinFile = value;
+ i++;
+ break;
+ case "nosort":
+ config.NoSort = true;
+ break;
+ case "maxromsize":
+ config.MaxRomSizeMB = uint.Parse(value);
+ i++;
+ break;
+ case "maxchrsize":
+ config.MaxChrRamSizeKB = uint.Parse(value);
+ i++;
+ break;
+ case "language":
+ switch (value.ToLower())
+ {
+ case "eng":
+ config.Language = CombinerLanguage.English;
+ break;
+ case "rus":
+ config.Language = CombinerLanguage.Russian;
+ break;
+ default:
+ throw new InvalidDataException($"Invalid language: {value}");
+ }
+ i++;
+ break;
+ case "badsectors":
+ foreach (var v in value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
+ config.BadSectors.Add(int.Parse(v));
+ i++;
+ break;
+ case "nesasm":
+ config.NesAsm = value;
+ i++;
+ break;
+ case "nesasm-args":
+ case "nesasmargs":
+ config.NesAsmArgs = value;
+ i++;
+ break;
+ case "sources":
+ config.SourcesDir = value;
+ i++;
+ break;
+ default:
+ Console.WriteLine("Unknown parameter: " + param);
+ return null;
+ }
+ }
+
+ if ((config.GamesFile == null) && ((config.Command == CombinerCommand.Prepare) || (config.Command == CombinerCommand.Build)))
+ {
+ Console.WriteLine("Missing required parameter: --games");
+ return null;
+ }
+ if ((config.AsmFile == null) && (config.Command == CombinerCommand.Prepare))
+ {
+ Console.WriteLine("Missing required parameter: --asm");
+ return null;
+ }
+ if ((config.OffsetsFile == null) && ((config.Command == CombinerCommand.Prepare) || (config.Command == CombinerCommand.Combine)))
+ {
+ Console.WriteLine("Missing required parameter: --offsets");
+ return null;
+ }
+ if ((config.LoaderFile == null) && (config.Command == CombinerCommand.Combine))
+ {
+ Console.WriteLine("Missing required parameter: --loader");
+ return null;
+ }
+ if ((config.UnifFile == null) && (config.Nes20File == null) && (config.BinFile == null)
+ && ((config.Command == CombinerCommand.Combine) || (config.Command == CombinerCommand.Build)))
+ {
+ Console.WriteLine("At least one parameter required: --unif, --nes20 or --bin");
+ return null;
+ }
+
+ if (string.IsNullOrEmpty(config.AsmFile))
+ config.AsmFile = Path.Combine(config.SourcesDir, "games.asm");
+
+ return config;
+ }
+
+ public static void PrintHelp()
+ {
+ var exename = Path.GetFileName(Process.GetCurrentProcess()?.MainModule?.FileName);
+ Console.WriteLine("--- Usage ---");
+ Console.WriteLine("First step:");
+ Console.WriteLine($" {exename} prepare --games <games.txt> --asm <games.asm> --offsets <offsets.json> [--report <report.txt>] [--nosort] [--maxromsize <size_mb>] [--maxchrsize <size_kb>] [--language <eng|rus>] [--badsectors <sectors>]");
+ Console.WriteLine(" {0,-20}{1}", "--games", "- input plain text file with a list of ROM files");
+ Console.WriteLine(" {0,-20}{1}", "--asm", "- output file for the loader");
+ Console.WriteLine(" {0,-20}{1}", "--offsets", "- output file with offsets for every game");
+ Console.WriteLine(" {0,-20}{1}", "--report", "- output report file (human readable)");
+ Console.WriteLine(" {0,-20}{1}", "--nosort", "- disable automatic sort by name");
+ Console.WriteLine(" {0,-20}{1}", "--maxromsize", "- maximum size for final file (in megabytes)");
+ Console.WriteLine(" {0,-20}{1}", "--maxchrsize", "- maximum CHR RAM size (in kilobytes), default is 256");
+ Console.WriteLine(" {0,-20}{1}", "--language", "- language for system messages: \"eng\" or \"rus\"");
+ Console.WriteLine(" {0,-20}{1}", "--badsectors", "- comma-separated list of bad sectors,");
+ Console.WriteLine("Second step:");
+ Console.WriteLine($" {exename} combine --loader <menu.nes> --offsets <offsets.json> [--unif <multirom.unf>] [--nes20 multirom.nes] [--bin <multirom.bin>]");
+ Console.WriteLine(" {0,-20}{1}", "--loader", "- loader (compiled using the asm file generated by the first step)");
+ Console.WriteLine(" {0,-20}{1}", "--offsets", "- input file with offsets for every game (generated by the first step)");
+ Console.WriteLine(" {0,-20}{1}", "--unif", "- output UNIF file");
+ Console.WriteLine(" {0,-20}{1}", "--nes20", "- output NES 2.0 file");
+ Console.WriteLine(" {0,-20}{1}", "--bin", "- output raw binary file");
+ Console.WriteLine("All at once:");
+ Console.WriteLine($" {exename} build --games <games.txt> --asm <games.asm> [--nesasm <nesasm>] [--nesasm-args <args>] [--sources <path>] [--report <report.txt>] [--nosort] [--maxromsize <size_mb>] [--maxchrsize <size_kb>] [--language <language>] [--badsectors <sectors>] [--unif <multirom.unf>] [--nes20 <multirom.nes>] [--bin <multirom.bin>]");
+ Console.WriteLine(" {0,-20}{1}", "--games", "- input plain text file with list of ROM files");
+ Console.WriteLine(" {0,-20}{1}", "--asm", "- output file for the loader");
+ Console.WriteLine(" {0,-20}{1}", "--nesasm", "- path to the nesasm compiler executable");
+ Console.WriteLine(" {0,-20}{1}", "--nesasm-args", "- additional command-line arguments for nesasm");
+ Console.WriteLine(" {0,-20}{1}", "--sources", "- directory with loader source files, default is current directory");
+ Console.WriteLine(" {0,-20}{1}", "--report", "- output report file (human readable)");
+ Console.WriteLine(" {0,-20}{1}", "--nosort", "- disable automatic sort by name");
+ Console.WriteLine(" {0,-20}{1}", "--maxromsize", "- maximum size for final file (in megabytes)");
+ Console.WriteLine(" {0,-20}{1}", "--maxchrsize", "- maximum CHR RAM size (in kilobytes), default is 256");
+ Console.WriteLine(" {0,-20}{1}", "--language", "- language for system messages: \"eng\" or \"rus\", default is \"eng\"");
+ Console.WriteLine(" {0,-20}{1}", "--badsectors", "- comma-separated list of bad sectors,");
+ Console.WriteLine(" {0,-20}{1}", "--unif", "- output UNIF file");
+ Console.WriteLine(" {0,-20}{1}", "--nes20", "- output NES 2.0 file");
+ Console.WriteLine(" {0,-20}{1}", "--bin", "- output raw binary file");
+ }
+ }
+}
diff --git a/tools_sources/CoolgirlCombiner/Program.cs b/tools_sources/CoolgirlCombiner/Program.cs
index ac07d55..4ea7ce0 100644
--- a/tools_sources/CoolgirlCombiner/Program.cs
+++ b/tools_sources/CoolgirlCombiner/Program.cs
@@ -17,9 +17,6 @@ namespace com.clusterrr.Famicom.CoolGirl
{
public const string REPO_PATH = "https://github.com/ClusterM/coolgirl-multirom-builder";
public static DateTime BUILD_TIME = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(long.Parse(Properties.Resources.buildtime.Trim()));
- const string DEFAULT_MAPPERS_FILE = @"coolgirl-mappers.json";
- const string DEFAULT_FIXES_FILE = @"coolgirl-fixes.json";
- const string DEFAULT_SYMBOLS_FILE = @"coolgirl-symbols.json";
static int Main(string[] args)
{
@@ -33,38 +30,14 @@ namespace com.clusterrr.Famicom.CoolGirl
Console.WriteLine(" (c) Alexey 'Cluster' Avdyukhin / https://clusterrr.com / clusterrr@clusterrr.com");
Console.WriteLine("");
- bool needShowHelp = false;
-
- const string commandPrepare = "prepare";
- const string commandCombine = "combine";
- const string commandBuild = "build";
-
- string? command = null;
- string optionMappersFile = Path.Combine(Path.GetDirectoryName(AppContext.BaseDirectory) ?? String.Empty, DEFAULT_MAPPERS_FILE);
- if (!File.Exists(optionMappersFile) && !OperatingSystem.IsWindows())
- optionMappersFile = Path.Combine("/etc", DEFAULT_MAPPERS_FILE);
- string optionFixesFile = Path.Combine(Path.GetDirectoryName(AppContext.BaseDirectory) ?? String.Empty, DEFAULT_FIXES_FILE);
- if (!File.Exists(optionFixesFile) && !OperatingSystem.IsWindows())
- optionFixesFile = Path.Combine("/etc", DEFAULT_FIXES_FILE);
- string optionSymbolsFile = Path.Combine(Path.GetDirectoryName(AppContext.BaseDirectory) ?? String.Empty, DEFAULT_SYMBOLS_FILE);
- if (!File.Exists(optionSymbolsFile) && !OperatingSystem.IsWindows())
- optionSymbolsFile = Path.Combine("/etc", DEFAULT_SYMBOLS_FILE);
- string optionNesAsm = "nesasm";
- string optionNesAsmArgs = "";
- string optionSourcesDir = ".";
- string? optionGamesFile = null;
- string optionAsmFile = "games.asm";
- string optionOffsetsFile = "offsets.json";
- string? optionReportFile = null;
- string? optionLoaderFile = null;
- string? optionUnifFile = null;
- string? optionNes20File = null;
- string? optionBinFile = null;
- string optionLanguage = "eng";
- var badSectors = new List<int>();
- bool optionNoSort = false;
- uint optionMaxRomSize = 256;
- uint optionMaxChrRamSize = 256;
+ var config = Config.Parse(args);
+
+ if (config == null)
+ {
+ Config.PrintHelp();
+ return 1;
+ }
+
var jsonOptions = new JsonSerializerOptions()
{
WriteIndented = true,
@@ -72,181 +45,13 @@ namespace com.clusterrr.Famicom.CoolGirl
Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) }
};
- if (args.Length > 0) command = args[0].ToLower();
- if ((command != commandPrepare) && (command != commandCombine) && (command != commandBuild))
- {
- if (!string.IsNullOrEmpty(command))
- Console.WriteLine("Unknown command: " + command);
- needShowHelp = true;
- }
- for (int i = 1; i < args.Length; i++)
- {
- string param = args[i];
- while (param.StartsWith("-")) param = param.Substring(1);
- string value = i < args.Length - 1 ? args[i + 1] : "";
- switch (param.ToLower())
- {
- case "mappers":
- optionMappersFile = value;
- i++;
- break;
- case "fixes":
- optionFixesFile = value;
- i++;
- break;
- case "symbols":
- optionSymbolsFile = value;
- i++;
- break;
- case "games":
- optionGamesFile = value;
- i++;
- break;
- case "asm":
- optionAsmFile = value;
- i++;
- break;
- case "offsets":
- optionOffsetsFile = value;
- i++;
- break;
- case "report":
- optionReportFile = value;
- i++;
- break;
- case "loader":
- optionLoaderFile = value;
- i++;
- break;
- case "unif":
- optionUnifFile = value;
- i++;
- break;
- case "nes20":
- optionNes20File = value;
- i++;
- break;
- case "bin":
- optionBinFile = value;
- i++;
- break;
- case "nosort":
- optionNoSort = true;
- break;
- case "maxromsize":
- optionMaxRomSize = uint.Parse(value);
- i++;
- break;
- case "maxchrsize":
- optionMaxChrRamSize = uint.Parse(value);
- i++;
- break;
- case "language":
- switch (value.ToLower())
- {
- case "eng":
- case "rus":
- optionLanguage = value.ToLower();
- break;
- default:
- throw new Exception($"Invalid language: {value}");
- }
- i++;
- break;
- case "badsectors":
- foreach (var v in value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
- badSectors.Add(int.Parse(v));
- i++;
- break;
- case "nesasm":
- optionNesAsm = value;
- i++;
- break;
- case "nesasm-args":
- case "nesasmargs":
- optionNesAsmArgs = value;
- i++;
- break;
- case "sources":
- optionSourcesDir = value;
- i++;
- break;
- default:
- Console.WriteLine("Unknown parameter: " + param);
- needShowHelp = true;
- break;
- }
- }
-
- if ((optionGamesFile == null) && ((command == commandPrepare) || (command == commandBuild)))
- {
- Console.WriteLine("Missing required parameter: --games");
- needShowHelp = true;
- }
- if ((optionOffsetsFile == null) && (command == commandPrepare))
- {
- Console.WriteLine("Missing required parameter: --offsets");
- needShowHelp = true;
- }
- if ((optionLoaderFile == null) && (command == commandCombine))
- {
- Console.WriteLine("Missing required parameter: --loader");
- needShowHelp = true;
- }
- if ((optionUnifFile == null) && (optionNes20File == null) && (optionBinFile == null) && ((command == commandCombine) || (command == commandBuild)))
- {
- Console.WriteLine("At least one parameter required: --unif, --nes20 or --bin");
- needShowHelp = true;
- }
-
- if (needShowHelp)
- {
- var exename = Path.GetFileName(Process.GetCurrentProcess()?.MainModule?.FileName);
- Console.WriteLine("--- Usage ---");
- Console.WriteLine("First step:");
- Console.WriteLine($" {exename} prepare --games <games.txt> --asm <games.asm> --offsets <offsets.json> [--report <report.txt>] [--nosort] [--maxromsize <size_mb>] [--maxchrsize <size_kb>] [--language <eng|rus>] [--badsectors <sectors>]");
- Console.WriteLine(" {0,-20}{1}", "--games", "- input plain text file with a list of ROM files");
- Console.WriteLine(" {0,-20}{1}", "--asm", "- output file for the loader");
- Console.WriteLine(" {0,-20}{1}", "--offsets", "- output file with offsets for every game");
- Console.WriteLine(" {0,-20}{1}", "--report", "- output report file (human readable)");
- Console.WriteLine(" {0,-20}{1}", "--nosort", "- disable automatic sort by name");
- Console.WriteLine(" {0,-20}{1}", "--maxromsize", "- maximum size for final file (in megabytes)");
- Console.WriteLine(" {0,-20}{1}", "--maxchrsize", "- maximum CHR RAM size (in kilobytes), default is 256");
- Console.WriteLine(" {0,-20}{1}", "--language", "- language for system messages: \"eng\" or \"rus\"");
- Console.WriteLine(" {0,-20}{1}", "--badsectors", "- comma-separated list of bad sectors,");
- Console.WriteLine("Second step:");
- Console.WriteLine($" {exename} combine --loader <menu.nes> --offsets <offsets.json> [--unif <multirom.unf>] [--nes20 multirom.nes] [--bin <multirom.bin>]");
- Console.WriteLine(" {0,-20}{1}", "--loader", "- loader (compiled using the asm file generated by the first step)");
- Console.WriteLine(" {0,-20}{1}", "--offsets", "- input file with offsets for every game (generated by the first step)");
- Console.WriteLine(" {0,-20}{1}", "--unif", "- output UNIF file");
- Console.WriteLine(" {0,-20}{1}", "--nes20", "- output NES 2.0 file");
- Console.WriteLine(" {0,-20}{1}", "--bin", "- output raw binary file");
- Console.WriteLine("All at once:");
- Console.WriteLine($" {exename} build --games <games.txt> --asm <games.asm> [--nesasm <nesasm>] [--nesasm-args <args>] [--sources <path>] [--report <report.txt>] [--nosort] [--maxromsize <size_mb>] [--maxchrsize <size_kb>] [--language <language>] [--badsectors <sectors>] [--unif <multirom.unf>] [--nes20 <multirom.nes>] [--bin <multirom.bin>]");
- Console.WriteLine(" {0,-20}{1}", "--games", "- input plain text file with list of ROM files");
- Console.WriteLine(" {0,-20}{1}", "--asm", "- output file for the loader");
- Console.WriteLine(" {0,-20}{1}", "--nesasm", "- path to the nesasm compiler executable");
- Console.WriteLine(" {0,-20}{1}", "--nesasm-args", "- additional command-line arguments for nesasm");
- Console.WriteLine(" {0,-20}{1}", "--sources", "- directory with loader source files, default is current directory");
- Console.WriteLine(" {0,-20}{1}", "--report", "- output report file (human readable)");
- Console.WriteLine(" {0,-20}{1}", "--nosort", "- disable automatic sort by name");
- Console.WriteLine(" {0,-20}{1}", "--maxromsize", "- maximum size for final file (in megabytes)");
- Console.WriteLine(" {0,-20}{1}", "--maxchrsize", "- maximum CHR RAM size (in kilobytes), default is 256");
- Console.WriteLine(" {0,-20}{1}", "--language", "- language for system messages: \"eng\" or \"rus\", default is \"eng\"");
- Console.WriteLine(" {0,-20}{1}", "--badsectors", "- comma-separated list of bad sectors,");
- Console.WriteLine(" {0,-20}{1}", "--unif", "- output UNIF file");
- Console.WriteLine(" {0,-20}{1}", "--nes20", "- output NES 2.0 file");
- Console.WriteLine(" {0,-20}{1}", "--bin", "- output raw binary file");
- return 1;
- }
-
// Reserved for loader
byte?[] result = Enumerable.Repeat(byte.MaxValue, 128 * 1024).Select(b => (byte?)b).ToArray();
- if ((command == commandPrepare) || (command == commandBuild))
+ if ((config.Command == Config.CombinerCommand.Prepare) || (config.Command == Config.CombinerCommand.Build))
{
// Loading mappers file
- var mappersJson = File.ReadAllText(optionMappersFile);
+ var mappersJson = File.ReadAllText(config.MappersFile);
var mappers = JsonSerializer.Deserialize<Dictionary<string, Mapper>>(mappersJson, jsonOptions);
if (mappers == null) throw new InvalidDataException("Can't read mappers file");
// Add padding zeros
@@ -265,9 +70,9 @@ namespace com.clusterrr.Famicom.CoolGirl
// Loading fixes file
Dictionary<string, GameFix>? fixes;
- if (File.Exists(optionFixesFile))
+ if (File.Exists(config.FixesFile))
{
- var fixesJson = File.ReadAllText(optionFixesFile);
+ var fixesJson = File.ReadAllText(config.FixesFile);
var fixesStr = JsonSerializer.Deserialize<Dictionary<string, GameFix>>(fixesJson, jsonOptions);
if (fixesStr == null) throw new InvalidDataException("Can't read fixes file");
// Convert string CRC32 to uint
@@ -285,18 +90,18 @@ namespace com.clusterrr.Famicom.CoolGirl
}
// Loading symbols table
- var symbolsJson = File.ReadAllText(optionSymbolsFile);
+ var symbolsJson = File.ReadAllText(config.SymbolsFile);
var symbols = JsonSerializer.Deserialize<Dictionary<char, byte>>(symbolsJson, jsonOptions);
if (symbols == null) throw new InvalidDataException("Can't load symbols file");
// Loading games list
- var lines = File.ReadAllLines(optionGamesFile!);
+ var lines = File.ReadAllLines(config.GamesFile!);
var regs = new Dictionary<string, List<String>>();
var games = new List<Game>();
var report = new List<String>();
// Bad sectors :(
- foreach (var bad in badSectors)
+ foreach (var bad in config.BadSectors)
{
for (int a = bad * 4 * 0x8000; a < bad * 4 * 0x8000 + 128 * 1024; a++)
{
@@ -306,6 +111,7 @@ namespace com.clusterrr.Famicom.CoolGirl
}
}
+ bool nosort = config.NoSort;
// Building list of ROMs
foreach (var line in lines)
{
@@ -315,7 +121,7 @@ namespace com.clusterrr.Famicom.CoolGirl
if (line.Trim().StartsWith(";")) continue;
if (line.Trim().ToUpper() == "!NOSORT")
{
- optionNoSort = true;
+ nosort = true;
continue;
}
var cols = line.Split(new char[] { '|' }, 2, StringSplitOptions.RemoveEmptyEntries);
@@ -344,7 +150,7 @@ namespace com.clusterrr.Famicom.CoolGirl
// Sorting
IEnumerable<Game> sortedGames;
- if (optionNoSort)
+ if (nosort)
{
sortedGames =
Enumerable.Concat(
@@ -383,7 +189,7 @@ namespace com.clusterrr.Famicom.CoolGirl
{
Console.Write($"Fitting PRG of {Path.GetFileName(game.FileName)} ({game.PRG.Length / 1024}KB)... ");
bool fitted = false;
- for (int pos = 0; pos < optionMaxRomSize * 1024 * 1024; pos += game.PRG.Length)
+ for (int pos = 0; pos < config.MaxRomSizeMB * 1024 * 1024; pos += game.PRG.Length)
{
if (WillFit(result, pos, game.PRG))
{
@@ -409,7 +215,7 @@ namespace com.clusterrr.Famicom.CoolGirl
{
Console.Write($"Fitting CHR of {Path.GetFileName(game.FileName)} ({game.CHR.Length / 1024}KB)... ");
bool fitted = false;
- for (int pos = 0; pos < optionMaxRomSize * 1024 * 1024; pos += 0x2000)
+ for (int pos = 0; pos < config.MaxRomSizeMB * 1024 * 1024; pos += 0x2000)
{
if (WillFit(result, pos, game.CHR))
{
@@ -478,8 +284,8 @@ namespace com.clusterrr.Famicom.CoolGirl
Console.WriteLine($"Battery-backed games: {saveId}");
// Write report file if need
- if (optionReportFile != null)
- File.WriteAllLines(optionReportFile, report.ToArray());
+ if (config.ReportFile != null)
+ File.WriteAllLines(config.ReportFile, report.ToArray());
if (games.Count - hiddenCount == 0)
throw new InvalidOperationException("Games list is empty");
@@ -503,7 +309,7 @@ namespace com.clusterrr.Famicom.CoolGirl
// Error collection
var problems = new List<Exception>();
- if (usedSpace > optionMaxRomSize * 1024 * 1024)
+ if (usedSpace > config.MaxRomSizeMB * 1024 * 1024)
problems.Add(new OutOfMemoryException($"ROM is too big: {Math.Round(usedSpace / 1024.0 / 1024.0, 3)}MB"));
if (games.Count > 256 * 6)
problems.Add(new InvalidDataException($"Too many ROMs: {games.Count} (maximum {256 * 6})"));
@@ -523,14 +329,14 @@ namespace com.clusterrr.Famicom.CoolGirl
}
}
else mapperInfo = new Mapper();
- if (game.CHR.Length > optionMaxChrRamSize * 1024)
+ if (game.CHR.Length > config.MaxChrRamSizeKB * 1024)
{
problems.Add(new Exception($"CHR size is too big in \"{Path.GetFileName(game.FileName)}\""));
continue;
}
- if ((game.Mirroring == MirroringType.FourScreenVram) && (game.CHR.Length > optionMaxChrRamSize * 1024 - 0x1000))
+ if ((game.Mirroring == MirroringType.FourScreenVram) && (game.CHR.Length > config.MaxChrRamSizeKB * 1024 - 0x1000))
{
- problems.Add(new Exception($"Four-screen mode and such big CHR ({optionMaxChrRamSize}KB) is not supported for \"{Path.GetFileName(game.FileName)}\""));
+ problems.Add(new Exception($"Four-screen mode and such big CHR ({config.MaxChrRamSizeKB}KB) is not supported for \"{Path.GetFileName(game.FileName)}\""));
continue;
}
if (game.Trained)
@@ -585,7 +391,7 @@ namespace com.clusterrr.Famicom.CoolGirl
// if CHR RAM banking is supported by mapper
// set the maximum size
if (mapperInfo.ChrRamBanking)
- chrBankingSize = (int)optionMaxChrRamSize * 1024;
+ chrBankingSize = (int)config.MaxChrRamSizeKB * 1024;
else // else banking is disabled
chrBankingSize = 0x2000;
}
@@ -700,6 +506,7 @@ namespace com.clusterrr.Famicom.CoolGirl
}
// Some strings
+ // TODO: replace magic strings with constants
asmResult.AppendLine();
asmResult.AppendLine();
asmResult.AppendLine("; Some strings");
@@ -707,7 +514,7 @@ namespace com.clusterrr.Famicom.CoolGirl
asmResult.AppendLine(" .org $C800");
asmResult.AppendLine();
asmResult.AppendLine("string_file:");
- asmResult.Append(BytesToAsm(StringToTiles("FILE: " + Path.GetFileName(optionGamesFile), symbols)));
+ asmResult.Append(BytesToAsm(StringToTiles("FILE: " + Path.GetFileName(config.GamesFile), symbols)));
asmResult.AppendLine("string_build_date:");
asmResult.Append(BytesToAsm(StringToTiles("BUILD DATE: " + DateTime.Now.ToString("yyyy-MM-dd"), symbols)));
asmResult.AppendLine("string_build_time:");
@@ -754,16 +561,22 @@ namespace com.clusterrr.Famicom.CoolGirl
asmResult.Append(BytesToAsm(StringToTiles("NOT AVAILABLE", symbols)));
asmResult.AppendLine("string_commit:");
asmResult.Append(BytesToAsm(StringToTiles("COMMIT: " + Properties.Resources.gitCommit, symbols)));
- asmResult.AppendLine("string_saving:");
- if (optionLanguage == "rus")
- asmResult.Append(BytesToAsm(StringToTiles(" СОХРАНЯЕМСЯ... НЕ ВЫКЛЮЧАЙ! ", symbols)));
- else
- asmResult.Append(BytesToAsm(StringToTiles(" SAVING... DON'T TURN OFF! ", symbols)));
- asmResult.AppendLine("string_incompatible_console:");
- if (optionLanguage == "rus")
- asmResult.Append(BytesToAsm(StringToTiles(" ИЗВИНИТЕ, ДАННАЯ ИГРА НЕСОВМЕСТИМА С ЭТОЙ КОНСОЛЬЮ НАЖМИТЕ ЛЮБУЮ КНОПКУ ", symbols)));
- else
- asmResult.Append(BytesToAsm(StringToTiles(" SORRY, THIS GAME IS NOT COMPATIBLE WITH THIS CONSOLE PRESS ANY BUTTON ", symbols)));
+ switch (config.Language)
+ {
+ case Config.CombinerLanguage.English:
+ asmResult.AppendLine("string_saving:");
+ asmResult.Append(BytesToAsm(StringToTiles(" SAVING... DON'T TURN OFF! ", symbols)));
+ asmResult.AppendLine("string_incompatible_console:");
+ asmResult.Append(BytesToAsm(StringToTiles(" SORRY, THIS GAME IS NOT COMPATIBLE WITH THIS CONSOLE PRESS ANY BUTTON ", symbols)));
+ break;
+ case Config.CombinerLanguage.Russian:
+ asmResult.AppendLine("string_saving:");
+ asmResult.Append(BytesToAsm(StringToTiles(" СОХРАНЯЕМСЯ... НЕ ВЫКЛЮЧАЙ! ", symbols)));
+ asmResult.AppendLine("string_incompatible_console:");
+ asmResult.Append(BytesToAsm(StringToTiles(" ИЗВИНИТЕ, ДАННАЯ ИГРА НЕСОВМЕСТИМА С ЭТОЙ КОНСОЛЬЮ НАЖМИТЕ ЛЮБУЮ КНОПКУ ", symbols)));
+ break;
+ }
+
asmResult.AppendLine("string_prg_ram_test:");
asmResult.Append(BytesToAsm(StringToTiles("PRG RAM TEST:", symbols)));
asmResult.AppendLine("string_chr_ram_test:");
@@ -777,27 +590,27 @@ namespace com.clusterrr.Famicom.CoolGirl
asmResult.AppendLine("string_error:");
asmResult.Append(BytesToAsm(StringToTiles("ERROR", symbols)));
- File.WriteAllText(optionAsmFile, asmResult.ToString());
+ File.WriteAllText(config.AsmFile!, asmResult.ToString());
- if (command == commandPrepare)
+ if (config.Command == Config.CombinerCommand.Prepare)
{
var offsets = new Offsets();
offsets.Size = romSize;
offsets.RomCount = gameCount;
- offsets.GamesFile = Path.GetFileName(optionGamesFile);
+ offsets.GamesFile = Path.GetFileName(config.GamesFile);
offsets.Games = sortedGames.Where(g => !g.IsSeparator).ToArray();
- File.WriteAllText(optionOffsetsFile!, JsonSerializer.Serialize(offsets, jsonOptions));
+ File.WriteAllText(config.OffsetsFile!, JsonSerializer.Serialize(offsets, jsonOptions));
}
- if (command == commandBuild)
+ if (config.Command == Config.CombinerCommand.Build)
{
Console.Write("Compiling using nesasm... ");
Array.Resize(ref result, (int)romSize);
var process = new Process();
var cp866 = CodePagesEncodingProvider.Instance.GetEncoding(866) ?? Encoding.ASCII;
- process.StartInfo.FileName = optionNesAsm;
- process.StartInfo.Arguments = $"\"menu.asm\" -r -o - -C \"GAMES_DB={optionAsmFile}\" " + optionNesAsmArgs;
- process.StartInfo.WorkingDirectory = optionSourcesDir;
+ process.StartInfo.FileName = config.NesAsm;
+ process.StartInfo.Arguments = $"\"menu.asm\" -r -o - -C \"GAMES_DB={config.AsmFile}\" " + config.NesAsmArgs;
+ process.StartInfo.WorkingDirectory = config.SourcesDir;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
@@ -837,9 +650,9 @@ namespace com.clusterrr.Famicom.CoolGirl
Console.WriteLine("OK");
}
}
- if (command == commandCombine) // Combine
+ if (config.Command == Config.CombinerCommand.Combine) // Combine
{
- var offsetsJson = File.ReadAllText(optionOffsetsFile!);
+ var offsetsJson = File.ReadAllText(config.OffsetsFile);
var offsets = JsonSerializer.Deserialize<Offsets>(offsetsJson, jsonOptions);
if (offsets == null) throw new InvalidDataException("Can't load offsets file");
result = new byte?[offsets.Size];
@@ -848,7 +661,7 @@ namespace com.clusterrr.Famicom.CoolGirl
result[i] = 0xFF;
Console.Write("Loading loader... ");
- var loaderFile = new NesFile(optionLoaderFile!);
+ var loaderFile = new NesFile(config.LoaderFile!);
var loader = loaderFile.PRG.ToArray();
for (int i = 0; i < loader.Length; i++)
result[i] = loader[i];
@@ -890,9 +703,9 @@ namespace com.clusterrr.Famicom.CoolGirl
}
}
- if ((command == commandCombine) || (command == commandBuild)) // Combine or build
+ if ((config.Command == Config.CombinerCommand.Combine) || (config.Command == Config.CombinerCommand.Build)) // Combine or build
{
- if (!string.IsNullOrEmpty(optionUnifFile))
+ if (!string.IsNullOrEmpty(config.UnifFile))
{
Console.Write("Saving UNIF file... ");
var u = new UnifFile();
@@ -901,10 +714,10 @@ namespace com.clusterrr.Famicom.CoolGirl
u.Mirroring = MirroringType.MapperControlled;
u.PRG0 = result.Select(b => b ?? byte.MaxValue).ToArray();
u.Battery = true;
- u.Save(optionUnifFile);
+ u.Save(config.UnifFile);
Console.WriteLine("OK");
}
- if (!string.IsNullOrEmpty(optionNes20File))
+ if (!string.IsNullOrEmpty(config.Nes20File))
{
Console.Write("Saving NES file... ");
var nes = new NesFile();
@@ -913,15 +726,15 @@ namespace com.clusterrr.Famicom.CoolGirl
nes.CHR = Array.Empty<byte>();
nes.Mapper = 342;
nes.PrgNvRamSize = 32 * 1024;
- nes.ChrRamSize = optionMaxChrRamSize * 1024;
+ nes.ChrRamSize = config.MaxChrRamSizeKB * 1024;
nes.Battery = true;
- nes.Save(optionNes20File);
+ nes.Save(config.Nes20File);
Console.WriteLine("OK");
}
- if (!string.IsNullOrEmpty(optionBinFile))
+ if (!string.IsNullOrEmpty(config.BinFile))
{
Console.Write("Saving BIN file... ");
- File.WriteAllBytes(optionBinFile, result.Select(b => b ?? byte.MaxValue).ToArray());
+ File.WriteAllBytes(config.BinFile, result.Select(b => b ?? byte.MaxValue).ToArray());
Console.WriteLine("OK");
}
}