mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
Split Headerer back out
This is in anticipation of making it a fully independent program. Currently, the only links to the rest of SabreTools are a few usability libraries that are mostly unnecessary. The main logic now lives as a separate library in SabreTools.Skippers.
This commit is contained in:
2
.github/workflows/build_and_publish.yml
vendored
2
.github/workflows/build_and_publish.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
project: [RombaSharp, SabreTools]
|
||||
project: [Headerer, RombaSharp, SabreTools]
|
||||
runtime: [win-x86, win-x64, win-arm64, linux-x64, linux-arm64, osx-x64]
|
||||
framework: [net8.0] #[net20, net35, net40, net452, net472, net48, netcoreapp3.1, net5.0, net6.0, net7.0, net8.0]
|
||||
|
||||
|
||||
195
Headerer/Features/BaseFeature.cs
Normal file
195
Headerer/Features/BaseFeature.cs
Normal file
@@ -0,0 +1,195 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using SabreTools.Core;
|
||||
using SabreTools.Core.Tools;
|
||||
using SabreTools.Help;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.Logging;
|
||||
|
||||
namespace Headerer.Features
|
||||
{
|
||||
internal class BaseFeature : TopLevel
|
||||
{
|
||||
#region Logging
|
||||
|
||||
/// <summary>
|
||||
/// Logging object
|
||||
/// </summary>
|
||||
protected Logger logger = new();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
|
||||
public static string HeadererFileName = Path.Combine(PathTool.GetRuntimeDirectory(), "Headerer.sqlite");
|
||||
public static string HeadererConnectionString = $"Data Source={HeadererFileName};";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Features
|
||||
|
||||
#region Flag features
|
||||
|
||||
internal const string NoStoreHeaderValue = "no-store-header";
|
||||
internal static Feature NoStoreHeaderFlag
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Feature(
|
||||
NoStoreHeaderValue,
|
||||
new List<string>() { "-nsh", "--no-store-header" },
|
||||
"Don't store the extracted header",
|
||||
ParameterType.Flag,
|
||||
longDescription: "By default, all headers that are removed from files are backed up in the database. This flag allows users to skip that step entirely, avoiding caching the headers at all.");
|
||||
}
|
||||
}
|
||||
|
||||
internal const string ScriptValue = "script";
|
||||
internal static Feature ScriptFlag
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Feature(
|
||||
ScriptValue,
|
||||
new List<string>() { "-sc", "--script" },
|
||||
"Enable script mode (no clear screen)",
|
||||
ParameterType.Flag,
|
||||
"For times when SabreTools is being used in a scripted environment, the user may not want the screen to be cleared every time that it is called. This flag allows the user to skip clearing the screen on run just like if the console was being redirected.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Int32 features
|
||||
|
||||
internal const string ThreadsInt32Value = "threads";
|
||||
internal static Feature ThreadsInt32Input
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Feature(
|
||||
ThreadsInt32Value,
|
||||
new List<string>() { "-mt", "--threads" },
|
||||
"Amount of threads to use (default = # cores)",
|
||||
ParameterType.Int32,
|
||||
longDescription: "Optionally, set the number of threads to use for the multithreaded operations. The default is the number of available machine threads; -1 means unlimited threads created.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region String features
|
||||
|
||||
internal const string LogLevelStringValue = "log-level";
|
||||
internal static Feature LogLevelStringInput
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Feature(
|
||||
LogLevelStringValue,
|
||||
new List<string>() { "-ll", "--log-level" },
|
||||
"Set the lowest log level for output",
|
||||
ParameterType.String,
|
||||
longDescription: @"Set the lowest log level for output.
|
||||
Possible values are: Verbose, User, Warning, Error");
|
||||
}
|
||||
}
|
||||
|
||||
internal const string OutputDirStringValue = "output-dir";
|
||||
internal static Feature OutputDirStringInput
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Feature(
|
||||
OutputDirStringValue,
|
||||
new List<string>() { "-out", "--output-dir" },
|
||||
"Set output directory",
|
||||
ParameterType.String,
|
||||
longDescription: "This sets an output folder to be used when the files are created. If a path is not defined, the runtime directory is used instead.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// Lowest log level for output
|
||||
/// </summary>
|
||||
public LogLevel LogLevel { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Output directory
|
||||
/// </summary>
|
||||
protected string? OutputDir { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines if scripting mode is enabled
|
||||
/// </summary>
|
||||
public bool ScriptMode { get; protected set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Add Feature Groups
|
||||
|
||||
/// <summary>
|
||||
/// Add common features
|
||||
/// </summary>
|
||||
protected void AddCommonFeatures()
|
||||
{
|
||||
AddFeature(ScriptFlag);
|
||||
AddFeature(LogLevelStringInput);
|
||||
AddFeature(ThreadsInt32Input);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override bool ProcessFeatures(Dictionary<string, Feature?> features)
|
||||
{
|
||||
// Generic feature flags
|
||||
LogLevel = GetString(features, LogLevelStringValue).AsLogLevel();
|
||||
OutputDir = GetString(features, OutputDirStringValue)?.Trim('"');
|
||||
ScriptMode = GetBoolean(features, ScriptValue);
|
||||
|
||||
// Set threading flag, if necessary
|
||||
if (features.ContainsKey(ThreadsInt32Value))
|
||||
Globals.MaxThreads = GetInt32(features, ThreadsInt32Value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region Protected Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Ensure that the database exists and has the proper schema
|
||||
/// </summary>
|
||||
protected static void EnsureDatabase()
|
||||
{
|
||||
// Make sure the file exists
|
||||
if (!File.Exists(HeadererFileName))
|
||||
File.Create(HeadererFileName);
|
||||
|
||||
// Open the database connection
|
||||
SqliteConnection dbc = new(HeadererConnectionString);
|
||||
dbc.Open();
|
||||
|
||||
// Make sure the database has the correct schema
|
||||
string query = @"
|
||||
CREATE TABLE IF NOT EXISTS data (
|
||||
'sha1' TEXT NOT NULL,
|
||||
'header' TEXT NOT NULL,
|
||||
'type' TEXT NOT NULL,
|
||||
PRIMARY KEY (sha1, header, type)
|
||||
)";
|
||||
SqliteCommand slc = new(query, dbc);
|
||||
slc.ExecuteNonQuery();
|
||||
slc.Dispose();
|
||||
dbc.Dispose();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
35
Headerer/Features/DisplayHelp.cs
Normal file
35
Headerer/Features/DisplayHelp.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using SabreTools.Help;
|
||||
|
||||
namespace Headerer.Features
|
||||
{
|
||||
internal class DisplayHelp : BaseFeature
|
||||
{
|
||||
public const string Value = "Help";
|
||||
|
||||
public DisplayHelp()
|
||||
{
|
||||
Name = Value;
|
||||
Flags.AddRange(["?", "h", "help"]);
|
||||
Description = "Show this help";
|
||||
_featureType = ParameterType.Flag;
|
||||
LongDescription = "Built-in to most of the programs is a basic help text.";
|
||||
}
|
||||
|
||||
public override bool ProcessArgs(string[] args, FeatureSet help)
|
||||
{
|
||||
// If we had something else after help
|
||||
if (args.Length > 1)
|
||||
{
|
||||
help.OutputIndividualFeature(args[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, show generic help
|
||||
else
|
||||
{
|
||||
help.OutputGenericHelp();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
Headerer/Features/DisplayHelpDetailed.cs
Normal file
35
Headerer/Features/DisplayHelpDetailed.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using SabreTools.Help;
|
||||
|
||||
namespace Headerer.Features
|
||||
{
|
||||
internal class DisplayHelpDetailed : BaseFeature
|
||||
{
|
||||
public const string Value = "Help (Detailed)";
|
||||
|
||||
public DisplayHelpDetailed()
|
||||
{
|
||||
Name = Value;
|
||||
Flags.AddRange(["??", "hd", "help-detailed"]);
|
||||
Description = "Show this detailed help";
|
||||
_featureType = ParameterType.Flag;
|
||||
LongDescription = "Display a detailed help text to the screen.";
|
||||
}
|
||||
|
||||
public override bool ProcessArgs(string[] args, FeatureSet help)
|
||||
{
|
||||
// If we had something else after help
|
||||
if (args.Length > 1)
|
||||
{
|
||||
help.OutputIndividualFeature(args[1], includeLongDescription: true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, show generic help
|
||||
else
|
||||
{
|
||||
help.OutputAllHelp();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ using SabreTools.Help;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.Skippers;
|
||||
|
||||
namespace SabreTools.Features
|
||||
namespace Headerer.Features
|
||||
{
|
||||
internal class Extract : BaseFeature
|
||||
{
|
||||
@@ -7,7 +7,7 @@ using SabreTools.Hashing;
|
||||
using SabreTools.Help;
|
||||
using SabreTools.IO;
|
||||
|
||||
namespace SabreTools.Features
|
||||
namespace Headerer.Features
|
||||
{
|
||||
internal class Restore : BaseFeature
|
||||
{
|
||||
33
Headerer/Features/Version.cs
Normal file
33
Headerer/Features/Version.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
using SabreTools.Core;
|
||||
using SabreTools.Help;
|
||||
|
||||
namespace Headerer.Features
|
||||
{
|
||||
internal class Version : BaseFeature
|
||||
{
|
||||
public const string Value = "Version";
|
||||
|
||||
public Version()
|
||||
{
|
||||
Name = Value;
|
||||
Flags.AddRange(["v", "version"]);
|
||||
Description = "Prints version";
|
||||
_featureType = ParameterType.Flag;
|
||||
LongDescription = "Prints current program version.";
|
||||
|
||||
// Common Features
|
||||
AddCommonFeatures();
|
||||
}
|
||||
|
||||
public override bool ProcessFeatures(Dictionary<string, Feature?> features)
|
||||
{
|
||||
// If the base fails, just fail out
|
||||
if (!base.ProcessFeatures(features))
|
||||
return false;
|
||||
|
||||
logger.User($"Headerer version: {Globals.Version}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
53
Headerer/Headerer.csproj
Normal file
53
Headerer/Headerer.csproj
Normal file
@@ -0,0 +1,53 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>1.1.2</Version>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
<Copyright>Copyright (c)2016-2024 Matt Nadareski</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/SabreTools/SabreTools</RepositoryUrl>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Support All Frameworks -->
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net4`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.10" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SabreTools.FileTypes\SabreTools.FileTypes.csproj" />
|
||||
<ProjectReference Include="..\SabreTools.Help\SabreTools.Help.csproj" />
|
||||
<ProjectReference Include="..\SabreTools.Logging\SabreTools.Logging.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
187
Headerer/Program.cs
Normal file
187
Headerer/Program.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Headerer.Features;
|
||||
using SabreTools.Core;
|
||||
using SabreTools.Help;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.Logging;
|
||||
|
||||
namespace Headerer
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
#region Static Variables
|
||||
|
||||
/// <summary>
|
||||
/// Help object that determines available functionality
|
||||
/// </summary>
|
||||
private static FeatureSet? _help;
|
||||
|
||||
/// <summary>
|
||||
/// Logging object
|
||||
/// </summary>
|
||||
private static readonly Logger logger = new();
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Entry point for the SabreTools application
|
||||
/// </summary>
|
||||
/// <param name="args">String array representing command line parameters</param>
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
// Perform initial setup and verification
|
||||
LoggerImpl.SetFilename(Path.Combine(PathTool.GetRuntimeDirectory(), "logs", "headerer.log"), true);
|
||||
LoggerImpl.AppendPrefix = true;
|
||||
LoggerImpl.LowestLogLevel = LogLevel.VERBOSE;
|
||||
LoggerImpl.ThrowOnError = false;
|
||||
LoggerImpl.Start();
|
||||
|
||||
// Create a new Help object for this program
|
||||
_help = RetrieveHelp();
|
||||
|
||||
// Credits take precidence over all
|
||||
if (new List<string>(args).Contains("--credits"))
|
||||
{
|
||||
FeatureSet.OutputCredits();
|
||||
LoggerImpl.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
// If there's no arguments, show help
|
||||
if (args.Length == 0)
|
||||
{
|
||||
_help.OutputGenericHelp();
|
||||
LoggerImpl.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the first argument as a feature flag
|
||||
string featureName = args[0];
|
||||
|
||||
// TODO: Remove this block once trimming is no longer needed
|
||||
// TODO: Update wiki documentation ONLY after this reaches stable
|
||||
// TODO: Re-evaluate feature flags with this change in mind
|
||||
featureName = featureName.TrimStart('-');
|
||||
if (args[0].StartsWith("-"))
|
||||
logger.User($"Feature flags no longer require leading '-' characters");
|
||||
|
||||
// Verify that the flag is valid
|
||||
if (!_help.TopLevelFlag(featureName))
|
||||
{
|
||||
logger.User($"'{featureName}' is not valid feature flag");
|
||||
_help.OutputIndividualFeature(featureName);
|
||||
LoggerImpl.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the proper name for the feature
|
||||
featureName = _help.GetFeatureName(featureName);
|
||||
|
||||
// Get the associated feature
|
||||
BaseFeature feature = (_help[featureName] as BaseFeature)!;
|
||||
|
||||
// If we had the help feature first
|
||||
if (featureName == DisplayHelp.Value || featureName == DisplayHelpDetailed.Value)
|
||||
{
|
||||
feature.ProcessArgs(args, _help);
|
||||
LoggerImpl.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
// Now verify that all other flags are valid
|
||||
if (!feature.ProcessArgs(args, _help))
|
||||
{
|
||||
LoggerImpl.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the new log level based on settings
|
||||
LoggerImpl.LowestLogLevel = feature.LogLevel;
|
||||
|
||||
// If output is being redirected or we are in script mode, don't allow clear screens
|
||||
if (!Console.IsOutputRedirected && feature.ScriptMode)
|
||||
{
|
||||
Console.Clear();
|
||||
Globals.SetConsoleHeader("Headerer");
|
||||
}
|
||||
|
||||
// Now process the current feature
|
||||
Dictionary<string, Feature?> features = _help.GetEnabledFeatures();
|
||||
bool success = false;
|
||||
switch (featureName)
|
||||
{
|
||||
// No-op as these should be caught
|
||||
case DisplayHelp.Value:
|
||||
case DisplayHelpDetailed.Value:
|
||||
break;
|
||||
|
||||
// Require input verification
|
||||
case Extract.Value:
|
||||
case Restore.Value:
|
||||
VerifyInputs(feature.Inputs, feature);
|
||||
success = feature.ProcessFeatures(features);
|
||||
break;
|
||||
|
||||
// If nothing is set, show the help
|
||||
default:
|
||||
_help.OutputGenericHelp();
|
||||
break;
|
||||
}
|
||||
|
||||
// If the feature failed, output help
|
||||
if (!success)
|
||||
{
|
||||
logger.Error("An error occurred during processing!");
|
||||
_help.OutputIndividualFeature(featureName);
|
||||
}
|
||||
|
||||
LoggerImpl.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a Help object for this program
|
||||
/// </summary>
|
||||
/// <returns>Populated Help object</returns>
|
||||
private static FeatureSet RetrieveHelp()
|
||||
{
|
||||
// Create and add the header to the Help object
|
||||
string barrier = "-----------------------------------------";
|
||||
List<string> helpHeader =
|
||||
[
|
||||
"Headerer - Remove, store, and restore copier headers",
|
||||
barrier,
|
||||
"Usage: Headerer [option] [flags] [filename|dirname] ...",
|
||||
string.Empty
|
||||
];
|
||||
|
||||
// Create the base help object with header
|
||||
var help = new FeatureSet(helpHeader);
|
||||
|
||||
// Add all of the features
|
||||
help.Add(new DisplayHelp());
|
||||
help.Add(new DisplayHelpDetailed());
|
||||
help.Add(new Extract());
|
||||
help.Add(new Restore());
|
||||
|
||||
return help;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify that there are inputs, show help otherwise
|
||||
/// </summary>
|
||||
/// <param name="inputs">List of inputs</param>
|
||||
/// <param name="feature">Name of the current feature</param>
|
||||
private static void VerifyInputs(List<string> inputs, BaseFeature feature)
|
||||
{
|
||||
if (inputs.Count == 0)
|
||||
{
|
||||
logger.Error("This feature requires at least one input");
|
||||
_help?.OutputIndividualFeature(feature.Name);
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
24
README.MD
24
README.MD
@@ -39,17 +39,6 @@ As the core of the SabreTools suite, the C# libraries provide nearly all of the
|
||||
* Includes the total uncompressed size of all items
|
||||
* Optionally includes statistics on individual DATs in a folder
|
||||
* Reports can be output in standard text, CSV, and/or HTML formats
|
||||
* **Extract and Restore Copier Headers** - Extract and store or restore from DB copier headers
|
||||
* Supports copier headers from the following systems:
|
||||
* Atari 7800
|
||||
* Atari Lynx
|
||||
* Commodore 64 PSID music
|
||||
* NEC PC-Engine / TurboGrafx 16
|
||||
* Nintendo Famicom Disk System
|
||||
* Nintendo Entertainment System / Famicom
|
||||
* Super Nintendo Entertainment System / Super Famicom
|
||||
* Super Nintendo Entertainment System / Super Famicom SPC music
|
||||
* Stores the header information linked to unheadered hash
|
||||
* **Rebuild From DAT** - Act as a simple rebuilder for files
|
||||
* Two options for rebuild origin: standard folder and Romba depot
|
||||
* Multiple output formats: unarchived, TAR, TorrentZip, 7zip, TorrentGZ
|
||||
@@ -66,6 +55,19 @@ As the core of the SabreTools suite, the C# libraries provide nearly all of the
|
||||
|
||||
This tool has a comprehensive list of command line parameters that can be used to do the above and much more.
|
||||
|
||||
### Headerer
|
||||
|
||||
A small tool that allows users to extract, store, and remove copier headers for a variety of systems. Optionally, the stored headers can be replaced on the original files using a separate command. Each of the headers are stored in a Sqlite database file that links each header to the unheadered hash of the original file. The following copier header types are supported:
|
||||
|
||||
* Atari 7800
|
||||
* Atari Lynx
|
||||
* Commodore 64 PSID music
|
||||
* NEC PC-Engine / TurboGrafx 16
|
||||
* Nintendo Famicom Disk System
|
||||
* Nintendo Entertainment System / Famicom
|
||||
* Super Nintendo Entertainment System / Super Famicom
|
||||
* Super Nintendo Entertainment System / Super Famicom SPC music
|
||||
|
||||
### RombaSharp
|
||||
|
||||
An in-progress tool that will try to act as a C# port of the Go-based [Romba](https://github.com/uwedeportivo/romba/) program. All features that are not already a part of SabreTools will be attempted to be added to this program. It is NOT ready for use yet. For any inquiries into the full features of this tool, please contact the project.
|
||||
|
||||
@@ -34,6 +34,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SabreTools.Reports", "Sabre
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SabreTools.Test", "SabreTools.Test\SabreTools.Test.csproj", "{5B4E67D5-F4DA-4750-8FE2-04D08E343791}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Headerer", "Headerer\Headerer.csproj", "{6629F05A-6696-4FCA-9614-83791725E499}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -138,6 +140,14 @@ Global
|
||||
{5B4E67D5-F4DA-4750-8FE2-04D08E343791}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5B4E67D5-F4DA-4750-8FE2-04D08E343791}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{5B4E67D5-F4DA-4750-8FE2-04D08E343791}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6629F05A-6696-4FCA-9614-83791725E499}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6629F05A-6696-4FCA-9614-83791725E499}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6629F05A-6696-4FCA-9614-83791725E499}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6629F05A-6696-4FCA-9614-83791725E499}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{6629F05A-6696-4FCA-9614-83791725E499}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6629F05A-6696-4FCA-9614-83791725E499}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6629F05A-6696-4FCA-9614-83791725E499}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6629F05A-6696-4FCA-9614-83791725E499}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using SabreTools.Core;
|
||||
using SabreTools.Core.Filter;
|
||||
using SabreTools.Core.Tools;
|
||||
@@ -724,20 +723,6 @@ namespace SabreTools.Features
|
||||
}
|
||||
}
|
||||
|
||||
internal const string NoStoreHeaderValue = "no-store-header";
|
||||
internal static Feature NoStoreHeaderFlag
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Feature(
|
||||
NoStoreHeaderValue,
|
||||
new List<string>() { "-nsh", "--no-store-header" },
|
||||
"Don't store the extracted header",
|
||||
ParameterType.Flag,
|
||||
longDescription: "By default, all headers that are removed from files are backed up in the database. This flag allows users to skip that step entirely, avoiding caching the headers at all.");
|
||||
}
|
||||
}
|
||||
|
||||
internal const string OneGamePerRegionValue = "one-game-per-region";
|
||||
internal static Feature OneGamePerRegionFlag
|
||||
{
|
||||
@@ -2293,33 +2278,6 @@ Some special strings that can be used:
|
||||
|
||||
#region Protected Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Ensure that the database exists and has the proper schema
|
||||
/// </summary>
|
||||
protected static void EnsureDatabase()
|
||||
{
|
||||
// Make sure the file exists
|
||||
if (!File.Exists(HeadererFileName))
|
||||
File.Create(HeadererFileName);
|
||||
|
||||
// Open the database connection
|
||||
SqliteConnection dbc = new(HeadererConnectionString);
|
||||
dbc.Open();
|
||||
|
||||
// Make sure the database has the correct schema
|
||||
string query = @"
|
||||
CREATE TABLE IF NOT EXISTS data (
|
||||
'sha1' TEXT NOT NULL,
|
||||
'header' TEXT NOT NULL,
|
||||
'type' TEXT NOT NULL,
|
||||
PRIMARY KEY (sha1, header, type)
|
||||
)";
|
||||
SqliteCommand slc = new(query, dbc);
|
||||
slc.ExecuteNonQuery();
|
||||
slc.Dispose();
|
||||
dbc.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get DatFormat value from input string
|
||||
/// </summary>
|
||||
|
||||
@@ -120,8 +120,6 @@ namespace SabreTools
|
||||
// Require input verification
|
||||
case Batch.Value:
|
||||
case DatFromDir.Value:
|
||||
case Extract.Value:
|
||||
case Restore.Value:
|
||||
case Split.Value:
|
||||
case Stats.Value:
|
||||
case Update.Value:
|
||||
@@ -176,8 +174,6 @@ namespace SabreTools
|
||||
help.Add(new DisplayHelpDetailed());
|
||||
help.Add(new Batch());
|
||||
help.Add(new DatFromDir());
|
||||
help.Add(new Extract());
|
||||
help.Add(new Restore());
|
||||
help.Add(new Sort());
|
||||
help.Add(new Split());
|
||||
help.Add(new Stats());
|
||||
|
||||
@@ -35,10 +35,6 @@
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.10" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SabreTools.DatFiles\SabreTools.DatFiles.csproj" />
|
||||
<ProjectReference Include="..\SabreTools.DatTools\SabreTools.DatTools.csproj" />
|
||||
|
||||
@@ -64,6 +64,45 @@ if [ $NO_BUILD = false ]; then
|
||||
echo "Restoring Nuget packages"
|
||||
dotnet restore
|
||||
|
||||
# Build Headerer
|
||||
for FRAMEWORK in "${FRAMEWORKS[@]}"; do
|
||||
for RUNTIME in "${RUNTIMES[@]}"; do
|
||||
# Output the current build
|
||||
echo "===== Build Headerer - $FRAMEWORK, $RUNTIME ====="
|
||||
|
||||
# If we have an invalid combination of framework and runtime
|
||||
if [[ ! $(echo ${VALID_CROSS_PLATFORM_FRAMEWORKS[@]} | fgrep -w $FRAMEWORK) ]]; then
|
||||
if [[ $(echo ${VALID_CROSS_PLATFORM_RUNTIMES[@]} | fgrep -w $RUNTIME) ]]; then
|
||||
echo "Skipped due to invalid combination"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
# If we have Apple silicon but an unsupported framework
|
||||
if [[ ! $(echo ${VALID_APPLE_FRAMEWORKS[@]} | fgrep -w $FRAMEWORK) ]]; then
|
||||
if [ $RUNTIME = "osx-arm64" ]; then
|
||||
echo "Skipped due to no Apple Silicon support"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
# Only .NET 5 and above can publish to a single file
|
||||
if [[ $(echo ${SINGLE_FILE_CAPABLE[@]} | fgrep -w $FRAMEWORK) ]]; then
|
||||
# Only include Debug if building all
|
||||
if [ $USE_ALL = true ]; then
|
||||
dotnet publish Headerer/Headerer.csproj -f $FRAMEWORK -r $RUNTIME -c Debug --self-contained true --version-suffix $COMMIT -p:PublishSingleFile=true
|
||||
fi
|
||||
dotnet publish Headerer/Headerer.csproj -f $FRAMEWORK -r $RUNTIME -c Release --self-contained true --version-suffix $COMMIT -p:PublishSingleFile=true -p:DebugType=None -p:DebugSymbols=false
|
||||
else
|
||||
# Only include Debug if building all
|
||||
if [ $USE_ALL = true ]; then
|
||||
dotnet publish Headerer/Headerer.csproj -f $FRAMEWORK -r $RUNTIME -c Debug --self-contained true --version-suffix $COMMIT
|
||||
fi
|
||||
dotnet publish Headerer/Headerer.csproj -f $FRAMEWORK -r $RUNTIME -c Release --self-contained true --version-suffix $COMMIT -p:DebugType=None -p:DebugSymbols=false
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# Build RombaSharp
|
||||
for FRAMEWORK in "${FRAMEWORKS[@]}"; do
|
||||
for RUNTIME in "${RUNTIMES[@]}"; do
|
||||
@@ -103,7 +142,7 @@ if [ $NO_BUILD = false ]; then
|
||||
done
|
||||
done
|
||||
|
||||
# Build RombaSharp
|
||||
# Build SabreTools
|
||||
for FRAMEWORK in "${FRAMEWORKS[@]}"; do
|
||||
for RUNTIME in "${RUNTIMES[@]}"; do
|
||||
# Output the current build
|
||||
@@ -145,6 +184,38 @@ fi
|
||||
|
||||
# Only create archives if requested
|
||||
if [ $NO_ARCHIVE = false ]; then
|
||||
# Create Headerer archives
|
||||
for FRAMEWORK in "${FRAMEWORKS[@]}"; do
|
||||
for RUNTIME in "${RUNTIMES[@]}"; do
|
||||
# Output the current build
|
||||
echo "===== Archive Headerer - $FRAMEWORK, $RUNTIME ====="
|
||||
|
||||
# If we have an invalid combination of framework and runtime
|
||||
if [[ ! $(echo ${VALID_CROSS_PLATFORM_FRAMEWORKS[@]} | fgrep -w $FRAMEWORK) ]]; then
|
||||
if [[ $(echo ${VALID_CROSS_PLATFORM_RUNTIMES[@]} | fgrep -w $RUNTIME) ]]; then
|
||||
echo "Skipped due to invalid combination"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
# If we have Apple silicon but an unsupported framework
|
||||
if [[ ! $(echo ${VALID_APPLE_FRAMEWORKS[@]} | fgrep -w $FRAMEWORK) ]]; then
|
||||
if [ $RUNTIME = "osx-arm64" ]; then
|
||||
echo "Skipped due to no Apple Silicon support"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
# Only include Debug if building all
|
||||
if [ $USE_ALL = true ]; then
|
||||
cd $BUILD_FOLDER/Headerer/bin/Debug/${FRAMEWORK}/${RUNTIME}/publish/
|
||||
zip -r $BUILD_FOLDER/Headerer_${FRAMEWORK}_${RUNTIME}_debug.zip .
|
||||
fi
|
||||
cd $BUILD_FOLDER/Headerer/bin/Release/${FRAMEWORK}/${RUNTIME}/publish/
|
||||
zip -r $BUILD_FOLDER/Headerer_${FRAMEWORK}_${RUNTIME}_release.zip .
|
||||
done
|
||||
done
|
||||
|
||||
# Create RombaSharp archives
|
||||
for FRAMEWORK in "${FRAMEWORKS[@]}"; do
|
||||
for RUNTIME in "${RUNTIMES[@]}"; do
|
||||
|
||||
@@ -55,6 +55,42 @@ if (!$NO_BUILD.IsPresent) {
|
||||
Write-Host "Restoring Nuget packages"
|
||||
dotnet restore
|
||||
|
||||
# Build Headerer
|
||||
foreach ($FRAMEWORK in $FRAMEWORKS) {
|
||||
foreach ($RUNTIME in $RUNTIMES) {
|
||||
# Output the current build
|
||||
Write-Host "===== Build Headerer - $FRAMEWORK, $RUNTIME ====="
|
||||
|
||||
# If we have an invalid combination of framework and runtime
|
||||
if ($VALID_CROSS_PLATFORM_FRAMEWORKS -notcontains $FRAMEWORK -and $VALID_CROSS_PLATFORM_RUNTIMES -contains $RUNTIME) {
|
||||
Write-Host "Skipped due to invalid combination"
|
||||
continue
|
||||
}
|
||||
|
||||
# If we have Apple silicon but an unsupported framework
|
||||
if ($VALID_APPLE_FRAMEWORKS -notcontains $FRAMEWORK -and $RUNTIME -eq 'osx-arm64') {
|
||||
Write-Host "Skipped due to no Apple Silicon support"
|
||||
continue
|
||||
}
|
||||
|
||||
# Only .NET 5 and above can publish to a single file
|
||||
if ($SINGLE_FILE_CAPABLE -contains $FRAMEWORK) {
|
||||
# Only include Debug if building all
|
||||
if ($USE_ALL.IsPresent) {
|
||||
dotnet publish Headerer\Headerer.csproj -f $FRAMEWORK -r $RUNTIME -c Debug --self-contained true --version-suffix $COMMIT -p:PublishSingleFile=true
|
||||
}
|
||||
dotnet publish Headerer\Headerer.csproj -f $FRAMEWORK -r $RUNTIME -c Release --self-contained true --version-suffix $COMMIT -p:PublishSingleFile=true -p:DebugType=None -p:DebugSymbols=false
|
||||
}
|
||||
else {
|
||||
# Only include Debug if building all
|
||||
if ($USE_ALL.IsPresent) {
|
||||
dotnet publish Headerer\Headerer.csproj -f $FRAMEWORK -r $RUNTIME -c Debug --self-contained true --version-suffix $COMMIT
|
||||
}
|
||||
dotnet publish Headerer\Headerer.csproj -f $FRAMEWORK -r $RUNTIME -c Release --self-contained true --version-suffix $COMMIT -p:DebugType=None -p:DebugSymbols=false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Build RombaSharp
|
||||
foreach ($FRAMEWORK in $FRAMEWORKS) {
|
||||
foreach ($RUNTIME in $RUNTIMES) {
|
||||
@@ -130,6 +166,35 @@ if (!$NO_BUILD.IsPresent) {
|
||||
|
||||
# Only create archives if requested
|
||||
if (!$NO_ARCHIVE.IsPresent) {
|
||||
# Create Headerer archives
|
||||
foreach ($FRAMEWORK in $FRAMEWORKS) {
|
||||
foreach ($RUNTIME in $RUNTIMES) {
|
||||
# Output the current build
|
||||
Write-Host "===== Archive Headerer - $FRAMEWORK, $RUNTIME ====="
|
||||
|
||||
# If we have an invalid combination of framework and runtime
|
||||
if ($VALID_CROSS_PLATFORM_FRAMEWORKS -notcontains $FRAMEWORK -and $VALID_CROSS_PLATFORM_RUNTIMES -contains $RUNTIME) {
|
||||
Write-Host "Skipped due to invalid combination"
|
||||
continue
|
||||
}
|
||||
|
||||
# If we have Apple silicon but an unsupported framework
|
||||
if ($VALID_APPLE_FRAMEWORKS -notcontains $FRAMEWORK -and $RUNTIME -eq 'osx-arm64') {
|
||||
Write-Host "Skipped due to no Apple Silicon support"
|
||||
continue
|
||||
}
|
||||
|
||||
# Only include Debug if building all
|
||||
if ($USE_ALL.IsPresent) {
|
||||
Set-Location -Path $BUILD_FOLDER\Headerer\bin\Debug\${FRAMEWORK}\${RUNTIME}\publish\
|
||||
7z a -tzip $BUILD_FOLDER\Headerer_${FRAMEWORK}_${RUNTIME}_debug.zip *
|
||||
}
|
||||
|
||||
Set-Location -Path $BUILD_FOLDER\Headerer\bin\Release\${FRAMEWORK}\${RUNTIME}\publish\
|
||||
7z a -tzip $BUILD_FOLDER\Headerer_${FRAMEWORK}_${RUNTIME}_release.zip *
|
||||
}
|
||||
}
|
||||
|
||||
# Create RombaSharp archives
|
||||
foreach ($FRAMEWORK in $FRAMEWORKS) {
|
||||
foreach ($RUNTIME in $RUNTIMES) {
|
||||
|
||||
Reference in New Issue
Block a user