Merge pull request #1 from gaseous-project/develop

First API Service
This commit is contained in:
Michael Green
2023-03-07 11:01:05 +11:00
committed by GitHub
34 changed files with 2357 additions and 193 deletions

11
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "nuget" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"

0
.gitmodules vendored Normal file
View File

35
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,35 @@
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/gaseous-server/bin/Debug/net7.0/gaseous-server.dll",
"args": [],
"cwd": "${workspaceFolder}/gaseous-server",
"stopAtEntry": false,
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
}

41
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,41 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/gaseous-server/gaseous-server.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/gaseous-server/gaseous-server.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"--project",
"${workspaceFolder}/gaseous-server/gaseous-server.csproj"
],
"problemMatcher": "$msCompile"
}
]
}

View File

@@ -1,9 +1,21 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 25.0.1704.4
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gaseous-identifier", "gaseous-identifier\gaseous-identifier.csproj", "{F5C42134-5372-430A-A9AE-1871981850DB}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gaseous-identifier-testapp", "gaseous-identifier\gaseous-identifier-testapp.csproj", "{F5C42134-5372-430A-A9AE-1871981850DB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gaseous-signature-parser", "gaseous-signature-parser\gaseous-signature-parser.csproj", "{DAEBBB82-5051-43FD-A406-F9D64A38F468}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gaseous-romsignatureobject", "gaseous-romsignatureobject\gaseous-romsignatureobject.csproj", "{9DCD243D-37CE-4562-8411-B5242B687D4F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gaseous-signature-ingestor", "gaseous-signature-ingestor\gaseous-signature-ingestor.csproj", "{86DF6E45-2C2B-4C30-AEC1-E7EF8C5CEA7D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gaseous-tools", "gaseous-tools\gaseous-tools.csproj", "{08FE408A-5EC1-4110-ABD8-D19A1155B8CE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gaseous-server", "gaseous-server\gaseous-server.csproj", "{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{B07A4655-A003-416B-A790-ADAA5B548E1A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -15,6 +27,38 @@ Global
{F5C42134-5372-430A-A9AE-1871981850DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5C42134-5372-430A-A9AE-1871981850DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5C42134-5372-430A-A9AE-1871981850DB}.Release|Any CPU.Build.0 = Release|Any CPU
{08699C93-15CD-4E39-9053-D3C8056CE938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{08699C93-15CD-4E39-9053-D3C8056CE938}.Debug|Any CPU.Build.0 = Debug|Any CPU
{08699C93-15CD-4E39-9053-D3C8056CE938}.Release|Any CPU.ActiveCfg = Release|Any CPU
{08699C93-15CD-4E39-9053-D3C8056CE938}.Release|Any CPU.Build.0 = Release|Any CPU
{DAEBBB82-5051-43FD-A406-F9D64A38F468}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DAEBBB82-5051-43FD-A406-F9D64A38F468}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DAEBBB82-5051-43FD-A406-F9D64A38F468}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DAEBBB82-5051-43FD-A406-F9D64A38F468}.Release|Any CPU.Build.0 = Release|Any CPU
{FFCEC386-033F-4772-A45B-D33579F2E5EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FFCEC386-033F-4772-A45B-D33579F2E5EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FFCEC386-033F-4772-A45B-D33579F2E5EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FFCEC386-033F-4772-A45B-D33579F2E5EE}.Release|Any CPU.Build.0 = Release|Any CPU
{9DCD243D-37CE-4562-8411-B5242B687D4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9DCD243D-37CE-4562-8411-B5242B687D4F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9DCD243D-37CE-4562-8411-B5242B687D4F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9DCD243D-37CE-4562-8411-B5242B687D4F}.Release|Any CPU.Build.0 = Release|Any CPU
{86DF6E45-2C2B-4C30-AEC1-E7EF8C5CEA7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{86DF6E45-2C2B-4C30-AEC1-E7EF8C5CEA7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{86DF6E45-2C2B-4C30-AEC1-E7EF8C5CEA7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{86DF6E45-2C2B-4C30-AEC1-E7EF8C5CEA7D}.Release|Any CPU.Build.0 = Release|Any CPU
{08FE408A-5EC1-4110-ABD8-D19A1155B8CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{08FE408A-5EC1-4110-ABD8-D19A1155B8CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{08FE408A-5EC1-4110-ABD8-D19A1155B8CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{08FE408A-5EC1-4110-ABD8-D19A1155B8CE}.Release|Any CPU.Build.0 = Release|Any CPU
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Release|Any CPU.Build.0 = Release|Any CPU
{B07A4655-A003-416B-A790-ADAA5B548E1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B07A4655-A003-416B-A790-ADAA5B548E1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B07A4655-A003-416B-A790-ADAA5B548E1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B07A4655-A003-416B-A790-ADAA5B548E1A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -3,6 +3,9 @@ using System.Security.Cryptography;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using Newtonsoft.Json;
using gaseous_romsignatureobject;
using gaseous_signature_parser.parsers;
string[] commandLineArgs = Environment.GetCommandLineArgs();
@@ -49,9 +52,10 @@ foreach (string commandLineArg in commandLineArgs)
scanPath = Path.GetFullPath(scanPath);
Console.WriteLine("ROM search path: " + scanPath);
System.Collections.ArrayList TOSEC = new System.Collections.ArrayList();
List<gaseous_identifier.classes.tosecXML> tosecLists = new List<gaseous_identifier.classes.tosecXML>();
UInt32 GameCounter = 0;
List<RomSignatureObject> romSignatures = new List<RomSignatureObject>();
System.Collections.ArrayList availablePlatforms = new System.Collections.ArrayList();
// load TOSEC XML files
if (tosecXML != null && tosecXML.Length > 0)
{
tosecXML = Path.GetFullPath(tosecXML);
@@ -59,146 +63,43 @@ if (tosecXML != null && tosecXML.Length > 0)
Console.WriteLine("TOSEC XML search path: " + tosecXML);
string[] tosecPathContents = Directory.GetFiles(tosecXML);
foreach (string tosecXMLFile in tosecPathContents)
int lastCLILineLength = 0;
for (UInt16 i = 0; i < tosecPathContents.Length; ++i)
{
XmlDocument tosecXmlDoc = new XmlDocument();
tosecXmlDoc.Load(tosecXMLFile);
string tosecXMLFile = tosecPathContents[i];
gaseous_identifier.classes.tosecXML tosecObject = new gaseous_identifier.classes.tosecXML();
TosecParser tosecParser = new TosecParser();
RomSignatureObject tosecObject = tosecParser.Parse(tosecXMLFile);
// get header
XmlNode xmlHeader = tosecXmlDoc.DocumentElement.SelectSingleNode("/datafile/header");
foreach (XmlNode childNode in xmlHeader.ChildNodes)
string statusOutput = i + " / " + tosecPathContents.Length + " : " + Path.GetFileName(tosecXMLFile);
Console.Write("\r " + statusOutput.PadRight(lastCLILineLength, ' ') + "\r");
lastCLILineLength = statusOutput.Length;
foreach (RomSignatureObject.Game gameRom in tosecObject.Games)
{
switch (childNode.Name.ToLower())
if (!availablePlatforms.Contains(gameRom.System))
{
case "name":
tosecObject.Name = childNode.InnerText;
break;
case "description":
tosecObject.Description = childNode.InnerText;
break;
case "category":
tosecObject.Category = childNode.InnerText;
break;
case "version":
tosecObject.Version = childNode.InnerText;
break;
case "author":
tosecObject.Author = childNode.InnerText;
break;
case "email":
tosecObject.Email = childNode.InnerText;
break;
case "homepage":
tosecObject.Homepage = childNode.InnerText;
break;
case "url":
try
{
tosecObject.Url = new Uri(childNode.InnerText);
} catch
{
tosecObject.Url = null;
}
break;
availablePlatforms.Add(gameRom.System);
}
}
// get games
tosecObject.Games = new List<gaseous_identifier.classes.tosecXML.Game>();
XmlNodeList xmlGames = tosecXmlDoc.DocumentElement.SelectNodes("/datafile/game");
foreach (XmlNode xmlGame in xmlGames)
{
gaseous_identifier.classes.tosecXML.Game gameObject = new gaseous_identifier.classes.tosecXML.Game();
// parse game name
string gameName = xmlGame.Attributes["name"].Value;
string[] gameNameTokens = gameName.Split("(");
// game title should be first item
gameObject.Name = gameNameTokens[0].Trim();
// game year should be second item
if (gameNameTokens.Length == 2)
{
gameObject.Year = gameNameTokens[1].Replace(")", "").Trim();
} else
{
gameObject.Year = "";
}
// game publisher should be third item
if (gameNameTokens.Length == 3)
{
gameObject.Publisher = gameNameTokens[2].Replace(")", "").Trim();
} else
{
gameObject.Publisher = "";
}
gameObject.Roms = new List<gaseous_identifier.classes.tosecXML.Game.Rom>();
// get the roms
foreach (XmlNode xmlGameDetail in xmlGame.ChildNodes)
{
switch (xmlGameDetail.Name.ToLower())
{
case "description":
gameObject.Description = xmlGameDetail.InnerText;
break;
case "rom":
gaseous_identifier.classes.tosecXML.Game.Rom romObject = new gaseous_identifier.classes.tosecXML.Game.Rom();
romObject.Name = xmlGameDetail.Attributes["name"]?.Value;
romObject.Size = UInt64.Parse(xmlGameDetail.Attributes["size"]?.Value);
romObject.Crc = xmlGameDetail.Attributes["crc"]?.Value;
romObject.Md5 = xmlGameDetail.Attributes["md5"]?.Value;
romObject.Sha1 = xmlGameDetail.Attributes["sha1"]?.Value;
gameObject.Roms.Add(romObject);
break;
}
}
// search for existing gameObject to update
bool existingGameFound = false;
foreach (gaseous_identifier.classes.tosecXML.Game existingGame in tosecObject.Games)
{
if (existingGame.Name == gameObject.Name && existingGame.Year == gameObject.Year && existingGame.Publisher == gameObject.Publisher)
{
existingGame.Roms.AddRange(gameObject.Roms);
existingGameFound = true;
break;
}
}
if (existingGameFound == false)
{
tosecObject.Games.Add(gameObject);
GameCounter += 1;
}
}
Console.Write(".");
tosecLists.Add(tosecObject);
romSignatures.Add(tosecObject);
}
Console.WriteLine("");
} else
{
Console.WriteLine("TOSEC is disabled, title matching will be by file name only.");
Console.WriteLine("TOSEC is disabled.");
}
Console.WriteLine(tosecLists.Count + " TOSEC files loaded - " + GameCounter + " games cataloged");
Console.WriteLine(romSignatures.Count + " TOSEC files loaded");
if (tosecLists.Count > 0)
// Summarise signatures
if (availablePlatforms.Count > 0)
{
Console.WriteLine("TOSEC lists available:");
foreach (gaseous_identifier.classes.tosecXML tosecList in tosecLists)
availablePlatforms.Sort();
Console.WriteLine("Platforms loaded:");
foreach (string platform in availablePlatforms)
{
Console.WriteLine(" * " + tosecList.Name);
Console.WriteLine(" * " + platform);
}
}
@@ -216,20 +117,43 @@ foreach (string romFile in romPathContents)
var sha1 = SHA1.Create();
byte[] sha1HashByte = sha1.ComputeHash(stream);
string sha1Hash = BitConverter.ToString(md5HashByte).Replace("-", "").ToLowerInvariant();
string sha1Hash = BitConverter.ToString(sha1HashByte).Replace("-", "").ToLowerInvariant();
bool gameFound = false;
foreach (gaseous_identifier.classes.tosecXML tosecList in tosecLists)
foreach (RomSignatureObject tosecList in romSignatures)
{
foreach (gaseous_identifier.classes.tosecXML.Game gameObject in tosecList.Games)
foreach (RomSignatureObject.Game gameObject in tosecList.Games)
{
foreach (gaseous_identifier.classes.tosecXML.Game.Rom romObject in gameObject.Roms)
foreach (RomSignatureObject.Game.Rom romObject in gameObject.Roms)
{
if (md5Hash == romObject.Md5)
if (romObject.Md5 != null)
{
if (md5Hash == romObject.Md5.ToLowerInvariant())
{
// match
gameFound = true;
}
}
if (romObject.Sha1 != null)
{
if (md5Hash == romObject.Sha1.ToLowerInvariant())
{
// match
gameFound = true;
}
}
if (gameFound == true)
{
// match
gameFound = true;
Console.WriteLine(romObject.Name);
RomSignatureObject.Game gameSignature = gameObject;
gameSignature.Roms.Clear();
gameSignature.Roms.Add(romObject);
var jsonSerializerSettings = new JsonSerializerSettings();
jsonSerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
jsonSerializerSettings.NullValueHandling = NullValueHandling.Ignore;
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(gameSignature, Newtonsoft.Json.Formatting.Indented, jsonSerializerSettings));
break;
}
}
@@ -241,4 +165,19 @@ foreach (string romFile in romPathContents)
{
Console.WriteLine("File not found in TOSEC library");
}
}
string SearchTitle = "California Games";
foreach (RomSignatureObject romSignatureObject in romSignatures)
{
foreach (RomSignatureObject.Game gameObject in romSignatureObject.Games)
{
if (gameObject.Name == SearchTitle)
{
var jsonSerializerSettings = new JsonSerializerSettings();
jsonSerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
jsonSerializerSettings.NullValueHandling = NullValueHandling.Ignore;
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(gameObject, Newtonsoft.Json.Formatting.Indented, jsonSerializerSettings));
}
}
}

View File

@@ -1,55 +0,0 @@
using System;
using System.Collections.Generic;
namespace gaseous_identifier.classes
{
public class tosecXML
{
public string Name { get; set; }
public string Description { get; set; }
public string Category { get; set; }
public string Version { get; set; }
public string Author { get; set; }
public string Email { get; set; }
public string Homepage { get; set; }
public Uri? Url { get; set; }
public List<Game> Games { get; set; }
public class Game
{
public string Name { get; set; }
public string Description { get; set; }
public string Year { get; set; }
public string Publisher { get; set; }
public List<Rom> Roms { get; set; }
public class Rom
{
public string Name { get; set; }
public UInt64 Size { get; set; }
public string Crc { get; set; }
public string Md5 { get; set; }
public string Sha1 { get; set; }
public string flags { get; set; }
public RomTypes RomType { get; set; }
public UInt16 DiskNumber { get; set; }
public string DiskSide { get; set; }
public enum RomTypes
{
Cartridge = 0,
Cassette = 1,
Floppy = 2,
CD = 3,
DVD = 4,
Unknown = 100
}
}
}
}
}

View File

@@ -9,9 +9,13 @@
</PropertyGroup>
<ItemGroup>
<None Remove="classes\" />
<None Remove="Newtonsoft.Json" />
</ItemGroup>
<ItemGroup>
<Folder Include="classes\" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\gaseous-romsignatureobject\gaseous-romsignatureobject.csproj" />
<ProjectReference Include="..\gaseous-signature-parser\gaseous-signature-parser.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
namespace gaseous_romsignatureobject
{
/// <summary>
/// Object returned by all signature engines containing metadata about the ROM's in the data files
///
/// This class was based on the TOSEC dataset, so may need to be expanded as new signature engines are added
/// </summary>
public class RomSignatureObject
{
public string? Name { get; set; }
public string? Description { get; set; }
public string? Category { get; set; }
public string? Version { get; set; }
public string? Author { get; set; }
public string? Email { get; set; }
public string? Homepage { get; set; }
public Uri? Url { get; set; }
public string? SourceType { get; set; }
public string SourceMd5 { get; set; } = "";
public string SourceSHA1 { get; set; } = "";
public List<Game> Games { get; set; } = new List<Game>();
public class Game
{
public string? Name { get; set; }
public string? Description { get; set; }
public string? Year { get; set; }
public string? Publisher { get; set; }
public DemoTypes Demo { get; set; }
public string? System { get; set; }
public string? SystemVariant { get; set; }
public string? Video { get; set; }
public string? Country { get; set; }
public string? Language { get; set; }
public string? Copyright { get; set; }
public List<Rom> Roms { get; set; } = new List<Rom>();
public int RomCount
{
get
{
return Roms.Count();
}
}
public enum DemoTypes
{
NotDemo = 0,
demo = 1,
demo_kiosk = 2,
demo_playable = 3,
demo_rolling = 4,
demo_slideshow = 5
}
public class Rom
{
public string? Name { get; set; }
public UInt64? Size { get; set; }
public string? Crc { get; set; }
public string? Md5 { get; set; }
public string? Sha1 { get; set; }
public string? DevelopmentStatus { get; set; }
public List<string> flags { get; set; } = new List<string>();
public RomTypes RomType { get; set; }
public string? RomTypeMedia { get; set; }
public string? MediaLabel { get; set; }
public enum RomTypes
{
/// <summary>
/// Media type is unknown
/// </summary>
Unknown = 0,
/// <summary>
/// Optical media
/// </summary>
Disc = 1,
/// <summary>
/// Magnetic media
/// </summary>
Disk = 2,
/// <summary>
/// Individual files
/// </summary>
File = 3,
/// <summary>
/// Individual pars
/// </summary>
Part = 4,
/// <summary>
/// Tape base media
/// </summary>
Tape = 5,
/// <summary>
/// Side of the media
/// </summary>
Side = 6
}
}
}
}
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>gaseous_romsignatureobject</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<WarningLevel>4</WarningLevel>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
using gaseous_tools;
using Microsoft.AspNetCore.Mvc;
// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace gaseous_server.Controllers
{
[ApiController]
[Route("api/[controller]/[action]")]
public class SignaturesController : ControllerBase
{
/// <summary>
/// Get the current signature counts from the database
/// </summary>
/// <returns>Number of sources, publishers, games, and rom signatures in the database</returns>
[HttpGet]
public Models.Signatures_Status Status()
{
return new Models.Signatures_Status();
}
[HttpGet]
[Route("api/[controller]/[action]")]
public List<Models.Signatures_Games> GetSignature(string md5 = "", string sha1 = "")
{
if (md5.Length > 0)
{
return _GetSignature("signatures_roms.md5 = @searchstring", md5);
} else
{
return _GetSignature("signatures_roms.sha1 = @searchstring", sha1);
}
}
private List<Models.Signatures_Games> _GetSignature(string sqlWhere, string searchString)
{
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "SELECT \n view_signatures_games.*,\n signatures_roms.id AS romid,\n signatures_roms.name AS romname,\n signatures_roms.size,\n signatures_roms.crc,\n signatures_roms.md5,\n signatures_roms.sha1,\n signatures_roms.developmentstatus,\n signatures_roms.flags,\n signatures_roms.romtype,\n signatures_roms.romtypemedia,\n signatures_roms.medialabel\nFROM\n signatures_roms\n INNER JOIN\n view_signatures_games ON signatures_roms.gameid = view_signatures_games.id WHERE " + sqlWhere;
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("searchString", searchString);
DataTable sigDb = db.ExecuteCMD(sql, dbDict);
List<Models.Signatures_Games> GamesList = new List<Models.Signatures_Games>();
foreach (DataRow sigDbRow in sigDb.Rows)
{
Models.Signatures_Games gameItem = new Models.Signatures_Games
{
Game = new Models.Signatures_Games.GameItem
{
Id = (Int32)sigDbRow["id"],
Name = (string)sigDbRow["name"],
Description = (string)sigDbRow["description"],
Year = (string)sigDbRow["year"],
Publisher = (string)sigDbRow["publisher"],
Demo = (Models.Signatures_Games.GameItem.DemoTypes)(int)sigDbRow["demo"],
System = (string)sigDbRow["platform"],
SystemVariant = (string)sigDbRow["systemvariant"],
Video = (string)sigDbRow["video"],
Country = (string)sigDbRow["country"],
Language = (string)sigDbRow["language"],
Copyright = (string)sigDbRow["copyright"]
},
Rom = new Models.Signatures_Games.RomItem
{
Id = (Int32)sigDbRow["romid"],
Name = (string)sigDbRow["romname"],
Size = (Int64)sigDbRow["size"],
Crc = (string)sigDbRow["crc"],
Md5 = (string)sigDbRow["md5"],
Sha1 = (string)sigDbRow["sha1"],
DevelopmentStatus = (string)sigDbRow["developmentstatus"],
flags = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>>((string)sigDbRow["flags"]),
RomType = (Models.Signatures_Games.RomItem.RomTypes)(int)sigDbRow["romtype"],
RomTypeMedia = (string)sigDbRow["romtypemedia"],
MediaLabel = (string)sigDbRow["medialabel"]
}
};
GamesList.Add(gameItem);
}
return GamesList;
}
}
}

View File

@@ -0,0 +1,98 @@
using System;
using static gaseous_romsignatureobject.RomSignatureObject.Game;
namespace gaseous_server.Models
{
public class Signatures_Games
{
public Signatures_Games()
{
}
public GameItem? Game { get; set; }
public RomItem? Rom { get; set; }
public class GameItem
{
public Int32? Id { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public string? Year { get; set; }
public string? Publisher { get; set; }
public DemoTypes Demo { get; set; }
public string? System { get; set; }
public string? SystemVariant { get; set; }
public string? Video { get; set; }
public string? Country { get; set; }
public string? Language { get; set; }
public string? Copyright { get; set; }
public enum DemoTypes
{
NotDemo = 0,
demo = 1,
demo_kiosk = 2,
demo_playable = 3,
demo_rolling = 4,
demo_slideshow = 5
}
}
public class RomItem
{
public Int32? Id { get; set; }
public string? Name { get; set; }
public Int64? Size { get; set; }
public string? Crc { get; set; }
public string? Md5 { get; set; }
public string? Sha1 { get; set; }
public string? DevelopmentStatus { get; set; }
public List<string> flags { get; set; } = new List<string>();
public RomTypes RomType { get; set; }
public string? RomTypeMedia { get; set; }
public string? MediaLabel { get; set; }
public enum RomTypes
{
/// <summary>
/// Media type is unknown
/// </summary>
Unknown = 0,
/// <summary>
/// Optical media
/// </summary>
Disc = 1,
/// <summary>
/// Magnetic media
/// </summary>
Disk = 2,
/// <summary>
/// Individual files
/// </summary>
File = 3,
/// <summary>
/// Individual pars
/// </summary>
Part = 4,
/// <summary>
/// Tape base media
/// </summary>
Tape = 5,
/// <summary>
/// Side of the media
/// </summary>
Side = 6
}
}
}
}

View File

@@ -0,0 +1,63 @@
using System;
using System.Data;
using gaseous_tools;
namespace gaseous_server.Models
{
public class Signatures_Status
{
private Int64 _SourceCount = 0;
private Int64 _PlatformCount = 0;
private Int64 _GameCount = 0;
private Int64 _RomCount = 0;
public Signatures_Status()
{
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "select (select count(*) from signatures_sources) as SourceCount, (select count(*) from signatures_platforms) as PlatformCount, (select count(*) from signatures_games) as GameCount, (select count(*) from signatures_roms) as RomCount;";
DataTable sigDb = db.ExecuteCMD(sql);
if (sigDb.Rows.Count > 0)
{
_SourceCount = (Int64)sigDb.Rows[0]["SourceCount"];
_PlatformCount = (Int64)sigDb.Rows[0]["PlatformCount"];
_GameCount = (Int64)sigDb.Rows[0]["GameCount"];
_RomCount = (Int64)sigDb.Rows[0]["RomCount"];
}
}
public Int64 Sources
{
get
{
return _SourceCount;
}
}
public Int64 Platforms
{
get
{
return _PlatformCount;
}
}
public Int64 Games
{
get
{
return _GameCount;
}
}
public Int64 Roms
{
get
{
return _RomCount;
}
}
}
}

38
gaseous-server/Program.cs Normal file
View File

@@ -0,0 +1,38 @@
using System.Text.Json.Serialization;
using gaseous_tools;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers().AddJsonOptions(x =>
{
// serialize enums as strings in api responses (e.g. Role)
x.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
// set up db
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
db.InitDB();
// start the app
app.Run();

View File

@@ -0,0 +1,41 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:38715",
"sslPort": 44314
}
},
"profiles": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5198",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true
},
"https": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7282;http://localhost:5198",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>gaseous_server</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition=" '$(RunConfiguration)' == 'https' " />
<PropertyGroup Condition=" '$(RunConfiguration)' == 'http' " />
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\gaseous-tools\gaseous-tools.csproj">
<GlobalPropertiesToRemove></GlobalPropertiesToRemove>
</ProjectReference>
<ProjectReference Include="..\gaseous-romsignatureobject\gaseous-romsignatureobject.csproj">
<GlobalPropertiesToRemove></GlobalPropertiesToRemove>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Remove="Controllers\" />
<None Remove="Models\" />
<None Remove="Models\Signatures.Status" />
</ItemGroup>
<ItemGroup>
<Folder Include="Controllers\" />
<Folder Include="Models\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,284 @@
using System;
using System.IO;
using MySql.Data.MySqlClient;
using gaseous_romsignatureobject;
using gaseous_signature_parser.parsers;
using gaseous_tools;
using MySqlX.XDevAPI;
// process command line
string[] commandLineArgs = Environment.GetCommandLineArgs();
string tosecXML = "";
bool showGames = false;
string inArgument = "";
foreach (string commandLineArg in commandLineArgs)
{
if (commandLineArg != commandLineArgs[0])
{
if (inArgument == "")
{
switch (commandLineArg.ToLower())
{
case "-tosecpath":
inArgument = commandLineArg.ToLower();
break;
case "-showgames":
showGames = true;
break;
default:
break;
}
}
else
{
switch (inArgument)
{
case "-tosecpath":
tosecXML = commandLineArg;
break;
default:
break;
}
inArgument = "";
}
}
}
// check if Config.ConfigurationPath is valid and create it if not
if (!Directory.Exists(Config.ConfigurationPath))
{
Directory.CreateDirectory(Config.ConfigurationPath);
}
// connect to database
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
// initialise the db
db.InitDB();
// process provided files
Console.WriteLine("Processing input files:");
if (Directory.Exists(tosecXML))
{
Console.WriteLine("Processing TOSEC data files", ConsoleColor.Green);
Console.WriteLine("");
Console.WriteLine("");
tosecXML = Path.GetFullPath(tosecXML);
string[] tosecPathContents = Directory.GetFiles(tosecXML);
int lineFileNameLength = 0;
int lineGameNameLength = 0;
string sql = "";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
System.Data.DataTable sigDB;
for (UInt16 i = 0; i < tosecPathContents.Length; ++i)
{
string tosecXMLFile = tosecPathContents[i];
string statusOutput = (i + 1).ToString().PadLeft(7, ' ') + " / " + tosecPathContents.Length.ToString().PadLeft(7, ' ') + " : " + Path.GetFileName(tosecXMLFile);
Console.SetCursorPosition(0, Console.CursorTop - 2);
Console.WriteLine("\r " + statusOutput.PadRight(lineFileNameLength, ' ') + "\r");
lineFileNameLength = statusOutput.Length;
// check tosec file md5
Console.WriteLine(" ==> Checking input file ");
Common.hashObject hashObject = new Common.hashObject(tosecXMLFile);
sql = "SELECT * FROM signatures_sources WHERE sourcemd5=@sourcemd5";
dbDict = new Dictionary<string, object>();
dbDict.Add("sourcemd5", hashObject.md5hash);
sigDB = db.ExecuteCMD(sql, dbDict);
if (sigDB.Rows.Count == 0)
{
// start parsing file
Console.SetCursorPosition(0, Console.CursorTop - 1);
Console.WriteLine(" ==> Parsing file ");
TosecParser tosecParser = new TosecParser();
RomSignatureObject tosecObject = tosecParser.Parse(tosecXMLFile);
// store in database
// store source object
bool processGames = false;
if (tosecObject.SourceMd5 != null)
{
Console.SetCursorPosition(0, Console.CursorTop - 1);
Console.WriteLine(" ==> Storing file in database ");
sql = "SELECT * FROM signatures_sources WHERE sourcemd5=@sourcemd5";
dbDict = new Dictionary<string, object>();
dbDict.Add("name", Common.ReturnValueIfNull(tosecObject.Name, ""));
dbDict.Add("description", Common.ReturnValueIfNull(tosecObject.Description, ""));
dbDict.Add("category", Common.ReturnValueIfNull(tosecObject.Category, ""));
dbDict.Add("version", Common.ReturnValueIfNull(tosecObject.Version, ""));
dbDict.Add("author", Common.ReturnValueIfNull(tosecObject.Author, ""));
dbDict.Add("email", Common.ReturnValueIfNull(tosecObject.Email, ""));
dbDict.Add("homepage", Common.ReturnValueIfNull(tosecObject.Homepage, ""));
dbDict.Add("uri", Common.ReturnValueIfNull(tosecObject.Url, ""));
dbDict.Add("sourcetype", Common.ReturnValueIfNull(tosecObject.SourceType, ""));
dbDict.Add("sourcemd5", tosecObject.SourceMd5);
dbDict.Add("sourcesha1", tosecObject.SourceSHA1);
sigDB = db.ExecuteCMD(sql, dbDict);
if (sigDB.Rows.Count == 0)
{
// entry not present, insert it
sql = "INSERT INTO signatures_sources (name, description, category, version, author, email, homepage, url, sourcetype, sourcemd5, sourcesha1) VALUES (@name, @description, @category, @version, @author, @email, @homepage, @uri, @sourcetype, @sourcemd5, @sourcesha1)";
db.ExecuteCMD(sql, dbDict);
processGames = true;
}
if (processGames == true)
{
for (int x = 0; x < tosecObject.Games.Count; ++x)
{
RomSignatureObject.Game gameObject = tosecObject.Games[x];
// update display
if (showGames == true)
{
Console.SetCursorPosition(0, Console.CursorTop - 1);
string statusGameOutput = " ==> " + (x + 1).ToString().PadLeft(7, ' ') + " / " + tosecObject.Games.Count.ToString().PadLeft(7, ' ') + " : " + gameObject.Name;
Console.WriteLine("\r " + statusGameOutput.PadRight(lineGameNameLength, ' ') + "\r");
lineGameNameLength = statusGameOutput.Length;
}
// set up game dictionary
dbDict = new Dictionary<string, object>();
dbDict.Add("name", Common.ReturnValueIfNull(gameObject.Name, ""));
dbDict.Add("description", Common.ReturnValueIfNull(gameObject.Description, ""));
dbDict.Add("year", Common.ReturnValueIfNull(gameObject.Year, ""));
dbDict.Add("publisher", Common.ReturnValueIfNull(gameObject.Publisher, ""));
dbDict.Add("demo", (int)gameObject.Demo);
dbDict.Add("system", Common.ReturnValueIfNull(gameObject.System, ""));
dbDict.Add("platform", Common.ReturnValueIfNull(gameObject.System, ""));
dbDict.Add("systemvariant", Common.ReturnValueIfNull(gameObject.SystemVariant, ""));
dbDict.Add("video", Common.ReturnValueIfNull(gameObject.Video, ""));
dbDict.Add("country", Common.ReturnValueIfNull(gameObject.Country, ""));
dbDict.Add("language", Common.ReturnValueIfNull(gameObject.Language, ""));
dbDict.Add("copyright", Common.ReturnValueIfNull(gameObject.Copyright, ""));
// store platform
int gameSystem = 0;
if (gameObject.System != null)
{
sql = "SELECT id FROM signatures_platforms WHERE platform=@platform";
sigDB = db.ExecuteCMD(sql, dbDict);
if (sigDB.Rows.Count == 0)
{
// entry not present, insert it
sql = "INSERT INTO signatures_platforms (platform) VALUES (@platform); SELECT LAST_INSERT_ID()";
sigDB = db.ExecuteCMD(sql, dbDict);
gameSystem = (int)sigDB.Rows[0][0];
}
else
{
gameSystem = (int)sigDB.Rows[0][0];
}
}
dbDict.Add("systemid", gameSystem);
// store publisher
int gamePublisher = 0;
if (gameObject.Publisher != null)
{
sql = "SELECT * FROM signatures_publishers WHERE publisher=@publisher";
sigDB = db.ExecuteCMD(sql, dbDict);
if (sigDB.Rows.Count == 0)
{
// entry not present, insert it
sql = "INSERT INTO signatures_publishers (publisher) VALUES (@publisher); SELECT LAST_INSERT_ID()";
sigDB = db.ExecuteCMD(sql, dbDict);
gamePublisher = (int)sigDB.Rows[0][0];
}
else
{
gamePublisher = (int)sigDB.Rows[0][0];
}
}
dbDict.Add("publisherid", gamePublisher);
// store game
int gameId = 0;
sql = "SELECT * FROM signatures_games WHERE name=@name AND year=@year AND publisherid=@publisher AND systemid=@systemid AND country=@country AND language=@language";
sigDB = db.ExecuteCMD(sql, dbDict);
if (sigDB.Rows.Count == 0)
{
// entry not present, insert it
sql = "INSERT INTO signatures_games " +
"(name, description, year, publisherid, demo, systemid, systemvariant, video, country, language, copyright) VALUES " +
"(@name, @description, @year, @publisherid, @demo, @systemid, @systemvariant, @video, @country, @language, @copyright); SELECT LAST_INSERT_ID()";
sigDB = db.ExecuteCMD(sql, dbDict);
gameId = (int)sigDB.Rows[0][0];
}
else
{
gameId = (int)sigDB.Rows[0][0];
}
// store rom
foreach (RomSignatureObject.Game.Rom romObject in gameObject.Roms)
{
if (romObject.Md5 != null)
{
int romId = 0;
sql = "SELECT * FROM signatures_roms WHERE gameid=@gameid AND md5=@md5";
dbDict = new Dictionary<string, object>();
dbDict.Add("gameid", gameId);
dbDict.Add("name", Common.ReturnValueIfNull(romObject.Name, ""));
dbDict.Add("size", Common.ReturnValueIfNull(romObject.Size, ""));
dbDict.Add("crc", Common.ReturnValueIfNull(romObject.Crc, ""));
dbDict.Add("md5", romObject.Md5);
dbDict.Add("sha1", Common.ReturnValueIfNull(romObject.Sha1, ""));
dbDict.Add("developmentstatus", Common.ReturnValueIfNull(romObject.DevelopmentStatus, ""));
if (romObject.flags != null)
{
if (romObject.flags.Count > 0)
{
dbDict.Add("flags", Newtonsoft.Json.JsonConvert.SerializeObject(romObject.flags));
}
else
{
dbDict.Add("flags", "[ ]");
}
}
else
{
dbDict.Add("flags", "[ ]");
}
dbDict.Add("romtype", (int)romObject.RomType);
dbDict.Add("romtypemedia", Common.ReturnValueIfNull(romObject.RomTypeMedia, ""));
dbDict.Add("medialabel", Common.ReturnValueIfNull(romObject.MediaLabel, ""));
sigDB = db.ExecuteCMD(sql, dbDict);
if (sigDB.Rows.Count == 0)
{
// entry not present, insert it
sql = "INSERT INTO signatures_roms (gameid, name, size, crc, md5, sha1, developmentstatus, flags, romtype, romtypemedia, medialabel) VALUES (@gameid, @name, @size, @crc, @md5, @sha1, @developmentstatus, @flags, @romtype, @romtypemedia, @medialabel); SELECT LAST_INSERT_ID()";
sigDB = db.ExecuteCMD(sql, dbDict);
romId = (int)sigDB.Rows[0][0];
}
else
{
romId = (int)sigDB.Rows[0][0];
}
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>gaseous_signature_ingestor</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\gaseous-romsignatureobject\gaseous-romsignatureobject.csproj" />
<ProjectReference Include="..\gaseous-signature-parser\gaseous-signature-parser.csproj" />
<ProjectReference Include="..\gaseous-tools\gaseous-tools.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MySql.Data" Version="8.0.32" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,525 @@
using System;
using System.Xml;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
using gaseous_romsignatureobject;
namespace gaseous_signature_parser.parsers
{
public class TosecParser
{
public RomSignatureObject Parse(string XMLFile)
{
// load resources
var assembly = Assembly.GetExecutingAssembly();
// load systems list
List<string> TOSECSystems = new List<string>();
var resourceName = "gaseous_signature_parser.Support.Parsers.TOSEC.Systems.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
TOSECSystems = reader.ReadToEnd().Split(Environment.NewLine).ToList<string>();
}
// load video list
List<string> TOSECVideo = new List<string>();
resourceName = "gaseous_signature_parser.Support.Parsers.TOSEC.Video.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
TOSECVideo = reader.ReadToEnd().Split(Environment.NewLine).ToList<string>();
}
// load country list
Dictionary<string, string> TOSECCountry = new Dictionary<string, string>();
resourceName = "gaseous_signature_parser.Support.Parsers.TOSEC.Country.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
do
{
string[] line = reader.ReadLine().Split(",");
TOSECCountry.Add(line[0], line[1]);
} while (reader.EndOfStream == false);
}
// load language list
Dictionary<string, string> TOSECLanguage = new Dictionary<string, string>();
resourceName = "gaseous_signature_parser.Support.Parsers.TOSEC.Language.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
do
{
string[] line = reader.ReadLine().Split(",");
TOSECLanguage.Add(line[0], line[1]);
} while (reader.EndOfStream == false);
}
// load copyright list
Dictionary<string, string> TOSECCopyright = new Dictionary<string, string>();
resourceName = "gaseous_signature_parser.Support.Parsers.TOSEC.Copyright.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
do
{
string[] line = reader.ReadLine().Split(",");
TOSECCopyright.Add(line[0], line[1]);
} while (reader.EndOfStream == false);
}
// load development status list
Dictionary<string, string> TOSECDevelopment = new Dictionary<string, string>();
resourceName = "gaseous_signature_parser.Support.Parsers.TOSEC.DevelopmentStatus.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
do
{
string[] line = reader.ReadLine().Split(",");
TOSECDevelopment.Add(line[0], line[1]);
} while (reader.EndOfStream == false);
}
// get hashes of TOSEC file
var xmlStream = File.OpenRead(XMLFile);
var md5 = MD5.Create();
byte[] md5HashByte = md5.ComputeHash(xmlStream);
string md5Hash = BitConverter.ToString(md5HashByte).Replace("-", "").ToLowerInvariant();
var sha1 = SHA1.Create();
byte[] sha1HashByte = sha1.ComputeHash(xmlStream);
string sha1Hash = BitConverter.ToString(sha1HashByte).Replace("-", "").ToLowerInvariant();
// load TOSEC file
XmlDocument tosecXmlDoc = new XmlDocument();
tosecXmlDoc.Load(XMLFile);
RomSignatureObject tosecObject = new RomSignatureObject();
// get header
XmlNode xmlHeader = tosecXmlDoc.DocumentElement.SelectSingleNode("/datafile/header");
tosecObject.SourceType = "TOSEC";
tosecObject.SourceMd5 = md5Hash;
tosecObject.SourceSHA1 = sha1Hash;
foreach (XmlNode childNode in xmlHeader.ChildNodes)
{
switch (childNode.Name.ToLower())
{
case "name":
tosecObject.Name = childNode.InnerText;
break;
case "description":
tosecObject.Description = childNode.InnerText;
break;
case "category":
tosecObject.Category = childNode.InnerText;
break;
case "version":
tosecObject.Version = childNode.InnerText;
break;
case "author":
tosecObject.Author = childNode.InnerText;
break;
case "email":
tosecObject.Email = childNode.InnerText;
break;
case "homepage":
tosecObject.Homepage = childNode.InnerText;
break;
case "url":
try
{
tosecObject.Url = new Uri(childNode.InnerText);
}
catch
{
tosecObject.Url = null;
}
break;
}
}
// get games
tosecObject.Games = new List<RomSignatureObject.Game>();
XmlNodeList xmlGames = tosecXmlDoc.DocumentElement.SelectNodes("/datafile/game");
foreach (XmlNode xmlGame in xmlGames)
{
RomSignatureObject.Game gameObject = new RomSignatureObject.Game();
// parse game name
string[] gameNameTitleParts = xmlGame.Attributes["name"].Value.Split("[");
string gameName = gameNameTitleParts[0];
// before split, save and remove the demo tag if present
if (gameName.Contains("(demo) ", StringComparison.CurrentCulture))
{
gameObject.Demo = RomSignatureObject.Game.DemoTypes.demo;
gameName = gameName.Replace("(demo) ", "");
}
else if (gameName.Contains("(demo-kiosk) ", StringComparison.CurrentCulture))
{
gameObject.Demo = RomSignatureObject.Game.DemoTypes.demo_kiosk;
gameName = gameName.Replace("(demo-kiosk) ", "");
}
else if (gameName.Contains("(demo-playable) ", StringComparison.CurrentCulture))
{
gameObject.Demo = RomSignatureObject.Game.DemoTypes.demo_playable;
gameName = gameName.Replace("(demo-playable) ", "");
}
else if (gameName.Contains("(demo-rolling) ", StringComparison.CurrentCulture))
{
gameObject.Demo = RomSignatureObject.Game.DemoTypes.demo_rolling;
gameName = gameName.Replace("(demo-rolling) ", "");
}
else if (gameName.Contains("(demo-slideshow) ", StringComparison.CurrentCulture))
{
gameObject.Demo = RomSignatureObject.Game.DemoTypes.demo_slideshow;
gameName = gameName.Replace("(demo-slideshow) ", "");
}
else
{
gameObject.Demo = RomSignatureObject.Game.DemoTypes.NotDemo;
}
string[] gameNameTokens = gameName.Split("(");
// game title should be first item
gameObject.Name = gameNameTokens[0].Trim();
// game year should be second item
if (gameNameTokens.Length >= 2)
{
bool dateFound = false;
// verify the value
string dateToken = gameNameTokens[1].Replace(")", "");
if (dateToken.Length >= 4)
{
// test for possible year values
// first up - centuries
if (dateToken == "19xx" || dateToken == "20xx")
{
// date is a century
gameObject.Year = dateToken;
dateFound = true;
} else
{
// check for decades
for (UInt16 i = 0; i < 10; i++)
{
if (dateToken == "19" + i + "x" || dateToken == "20" + i + "x")
{
// date is a decade
gameObject.Year = dateToken;
dateFound = true;
break;
}
}
if (dateFound == false)
{
// check if the year is a four digit number
DateTime dateTime = new DateTime();
if (DateTime.TryParse(string.Format("1/1/{0}", dateToken), out dateTime))
{
// is a valid year!
gameObject.Year = dateToken;
dateFound = true;
}
// if we still haven't found a valid date, check if the whole string is a valid date object
if (dateFound == false)
{
if (DateTime.TryParse(dateToken, out dateTime))
{
// is a valid year!
gameObject.Year = dateToken;
dateFound = true;
}
}
// if we still haven't found a valid date, check if the whole string is a valid date object, but with x's
// example: 19xx-12-2x
if (dateFound == false)
{
if (DateTime.TryParse(dateToken.Replace("x", "0"), out dateTime))
{
// is a valid year!
gameObject.Year = dateToken;
dateFound = true;
}
}
// if we still haven't found a valid date, perhaps it a year and month?
// example: 19xx-12
if (dateFound == false)
{
if (DateTime.TryParse(dateToken.Replace("x", "0") + "-01", out dateTime))
{
// is a valid year!
gameObject.Year = dateToken;
dateFound = true;
}
}
}
}
}
}
else
{
gameObject.Year = "";
}
// game publisher should be third item
if (gameNameTokens.Length >= 3)
{
gameObject.Publisher = gameNameTokens[2].Replace(")", "").Trim();
}
else
{
gameObject.Publisher = "";
}
// process remaining tokens
// set default values
gameObject.System = tosecObject.Name.Split(" - ")[0];
// process title values
UInt16 StartToken = 0;
foreach (string rawToken in gameNameTokens)
{
if (StartToken > 2)
{
string[] tokenSplit = rawToken.Split("[");
// replace the extra closing bracket
string token = tokenSplit[0].Replace(")", "").Trim();
// perform tests on the token to see what it is
// exclude strings that start with [ in this part
if (!(token.StartsWith("[") && token.EndsWith("]")))
{
// check for systems
if (TOSECSystems.Contains(token, StringComparer.CurrentCulture))
{
// this is a system token
gameObject.SystemVariant = token;
}
// check for video
if (TOSECVideo.Contains(token, StringComparer.CurrentCulture))
{
// this is a system token
gameObject.Video = token;
}
// check for country
if (TOSECCountry.ContainsKey(token))
{
gameObject.Country = token;
}
// check for language
if (TOSECLanguage.ContainsKey(token))
{
gameObject.Language = token;
}
// check for copyright
if (TOSECCopyright.ContainsKey(token))
{
gameObject.Copyright = token;
}
}
}
StartToken += 1;
}
gameObject.Roms = new List<RomSignatureObject.Game.Rom>();
// get the roms
string romDescription = "";
foreach (XmlNode xmlGameDetail in xmlGame.ChildNodes)
{
switch (xmlGameDetail.Name.ToLower())
{
case "description":
romDescription = xmlGameDetail.InnerText;
break;
case "rom":
RomSignatureObject.Game.Rom romObject = new RomSignatureObject.Game.Rom();
if (xmlGameDetail != null)
{
romObject.Name = xmlGameDetail.Attributes["name"]?.Value;
if (xmlGameDetail.Attributes["size"]?.Value != null)
{
romObject.Size = UInt64.Parse(xmlGameDetail.Attributes["size"]?.Value);
}
else
{
romObject.Size = 0;
}
romObject.Crc = xmlGameDetail.Attributes["crc"]?.Value;
romObject.Md5 = xmlGameDetail.Attributes["md5"]?.Value;
romObject.Sha1 = xmlGameDetail.Attributes["sha1"]?.Value;
// parse name
string[] romNameTokens = romDescription.Split("(");
foreach (string rawToken in romNameTokens)
{
string[] tokenSplit = rawToken.Split("[");
// replace the extra closing bracket
string token = tokenSplit[0].Replace(")", "").Trim();
// check for copyright
if (TOSECDevelopment.ContainsKey(token))
{
romObject.DevelopmentStatus = token;
}
// check for media type
if (token.StartsWith("Disc") ||
token.StartsWith("Disk") ||
token.StartsWith("File") ||
token.StartsWith("Part") ||
token.StartsWith("Side") ||
token.StartsWith("Tape"))
{
string[] tokens = token.Split(" ");
switch (tokens[0])
{
case "Disc":
romObject.RomType = RomSignatureObject.Game.Rom.RomTypes.Disc;
break;
case "Disk":
romObject.RomType = RomSignatureObject.Game.Rom.RomTypes.Disk;
break;
case "File":
romObject.RomType = RomSignatureObject.Game.Rom.RomTypes.File;
break;
case "Part":
romObject.RomType = RomSignatureObject.Game.Rom.RomTypes.Part;
break;
case "Side":
romObject.RomType = RomSignatureObject.Game.Rom.RomTypes.Side;
break;
case "Tape":
romObject.RomType = RomSignatureObject.Game.Rom.RomTypes.Tape;
break;
}
romObject.RomTypeMedia = token;
}
// check for media label
if (token.Length > 0 &&
(token + ")") == gameNameTokens.Last() &&
(
token != romObject.RomTypeMedia &&
token != gameObject.Publisher &&
token != gameObject.SystemVariant &&
token != gameObject.Video &&
token != gameObject.Country &&
token != gameObject.Copyright &&
token != gameObject.Language &&
token != romObject.DevelopmentStatus
)
)
{
// likely the media label?
romObject.MediaLabel = token;
}
// process dump flags
if (rawToken.IndexOf("[") > 0)
{
// has dump flags
string rawDumpFlags = rawToken.Substring(rawToken.IndexOf("["));
string[] dumpFlags = rawDumpFlags.Split("[");
foreach (string dumpFlag in dumpFlags)
{
string dToken = dumpFlag.Replace("]", "");
if (dToken.Length > 0)
{
string[] dTokenCompare = dToken.Split(" ");
if (dTokenCompare[0].Trim().ToLower().StartsWith("a"))
{
romObject.flags.Add(dTokenCompare[0].Trim());
}
else
{
switch (dTokenCompare[0].Trim().ToLower())
{
case "cr":
// cracked
case "f":
// fixed
case "h":
// hacked
case "m":
// modified
case "p":
// pirated
case "t":
// trained
case "tr":
// translated
case "o":
// overdump
case "u":
// underdump
case "v":
// virus
case "b":
// bad dump
case "a":
// alternate
case "!":
// known verified dump
// -------------------
romObject.flags.Add(dToken);
break;
}
}
}
}
}
}
}
gameObject.Roms.Add(romObject);
break;
}
}
// search for existing gameObject to update
bool existingGameFound = false;
foreach (RomSignatureObject.Game existingGame in tosecObject.Games)
{
if (existingGame.Name == gameObject.Name &&
existingGame.Year == gameObject.Year &&
existingGame.Publisher == gameObject.Publisher &&
existingGame.Country == gameObject.Country &&
existingGame.Language == gameObject.Language)
{
existingGame.Roms.AddRange(gameObject.Roms);
existingGameFound = true;
break;
}
}
if (existingGameFound == false)
{
tosecObject.Games.Add(gameObject);
}
}
return tosecObject;
}
}
}

View File

@@ -0,0 +1,9 @@
CW,Cardware
CW-R,Cardware-Registered
FW,Freeware
GW,Giftware
GW-R,Giftware-Registered
LW,Licenceware
PD,Public Domain
SW,Shareware
SW-R,Shareware-Registered

View File

@@ -0,0 +1,68 @@
AE,United Arab Emirates
AL,Albania
AS,Asia
AT,Austria
AU,Australia
BA,Bosnia and Herzegovina
BE,Belgium
BG,Bulgaria
BR,Brazil
CA,Canada
CH,Switzerland
CL,Chile
CN,China
CS,Serbia and Montenegro
CY,Cyprus
CZ,Czech Republic
DE,Germany
DK,Denmark
EE,Estonia
EG,Egypt
ES,Spain
EU,Europe
FI,Finland
FR,France
GB,United Kingdom
GR,Greece
HK,Hong Kong
HR,Croatia
HU,Hungary
ID,Indonesia
IE,Ireland
IL,Israel
IN,India
IR,Iran
IS,Iceland
IT,Italy
JO,Jordan
JP,Japan
KR,South Korea
LT,Lithuania
LU,Luxembourg
LV,Latvia
MN,Mongolia
MX,Mexico
MY,Malaysia
NL,Netherlands
NO,Norway
NP,Nepal
NZ,New Zealand
OM,Oman
PE,Peru
PH,Philippines
PL,Poland
PT,Portugal
QA,Qatar
RO,Romania
RU,Russia
SE,Sweden
SG,Singapore
SI,Slovenia
SK,Slovakia
TH,Thailand
TR,Turkey
TW,Taiwan
US,United States
VN,Vietnam
YU,Yugoslavia
ZA,South Africa

View File

@@ -0,0 +1,5 @@
alpha,Early test build
beta,Later; feature complete test build
preview,Near complete build
pre-release,Near complete build
proto,Unreleased; prototype software

View File

@@ -0,0 +1,45 @@
ar,Arabic
bg,Bulgarian
bs,Bosnian
cs,Czech
cy,Welsh
da,Danish
de,German
el,Greek
en,English
eo,Esperanto
es,Spanish
et,Estonian
fa,Persian
fi,Finnish
fr,French
ga,Irish
gu,Gujarati
he,Hebrew
hi,Hindi
hr,Croatian
hu,Hungarian
is,Icelandic
it,Italian
ja,Japanese
ko,Korean
lt,Lithuanian
lv,Latvian
ms,Malay
nl,Dutch
no,Norwegian
pl,Polish
pt,Portuguese
ro,Romanian
ru,Russian
sk,Slovakian
sl,Slovenian
sq,Albanian
sr,Serbian
sv,Swedish
th,Thai
tr,Turkish
ur,Urdu
vi,Vietnamese
yi,Yiddish
zh,Chinese

View File

@@ -0,0 +1,57 @@
+2
+2a
+3
130XE
A1000
A1200
A1200-A4000
A2000
A2000-A3000
A2024
A2500-A3000UX
A3000
A4000
A4000T
A500
A500+
A500-A1000-A2000
A500-A1000-A2000-CDTV
A500-A1200
A500-A1200-A2000-A4000
A500-A2000
A500-A600-A2000
A570
A600
A600HD
AGA
AGA-CD32
Aladdin Deck Enhancer
CD32
CDTV
Computrainer
Doctor PC Jr.
ECS
ECS-AGA
Executive
Mega ST
Mega-STE
OCS
OCS-AGA
ORCH80
Osbourne 1
PIANO90
PlayChoice-10
Plus4
Primo-A
Primo-A64
Primo-B
Primo-B64
Pro-Primo
ST
STE
STE-Falcon
TT
TURBO-R GT
TURBO-R ST
VS DualSystem
VS UniSystem

View File

@@ -0,0 +1,13 @@
CGA
EGA
HGC
MCGA
MDA
NTSC
NTSC-PAL
PAL
PAL-60
PAL-NTSC
SVGA
VGA
XGA

View File

@@ -0,0 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>gaseous_signature_parser</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<None Remove="Support\Parsers\TOSEC\Copyright.txt" />
<None Remove="Support\Parsers\TOSEC\Country.txt" />
<None Remove="Support\Parsers\TOSEC\DevelopmentStatus.txt" />
<None Remove="Support\Parsers\TOSEC\Language.txt" />
<None Remove="Support\Parsers\TOSEC\Systems.txt" />
<None Remove="Support\Parsers\TOSEC\Video.txt" />
<None Remove="Support\" />
<None Remove="Classes\" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Support\Parsers\TOSEC\Copyright.txt" />
<EmbeddedResource Include="Support\Parsers\TOSEC\Country.txt" />
<EmbeddedResource Include="Support\Parsers\TOSEC\DevelopmentStatus.txt" />
<EmbeddedResource Include="Support\Parsers\TOSEC\Language.txt" />
<EmbeddedResource Include="Support\Parsers\TOSEC\Systems.txt" />
<EmbeddedResource Include="Support\Parsers\TOSEC\Video.txt" />
</ItemGroup>
<ItemGroup>
<Folder Include="Support\" />
<Folder Include="Classes\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\gaseous-romsignatureobject\gaseous-romsignatureobject.csproj" />
</ItemGroup>
</Project>

63
gaseous-tools/Common.cs Normal file
View File

@@ -0,0 +1,63 @@
using System;
using System.Security.Cryptography;
namespace gaseous_tools
{
public class Common
{
/// <summary>
/// Returns IfNullValue if the ObjectToCheck is null
/// </summary>
/// <param name="ObjectToCheck">Any nullable object to check for null</param>
/// <param name="IfNullValue">Any object to return if ObjectToCheck is null</param>
/// <returns></returns>
static public object ReturnValueIfNull(object? ObjectToCheck, object IfNullValue)
{
if (ObjectToCheck == null)
{
return IfNullValue;
} else
{
return ObjectToCheck;
}
}
public class hashObject
{
public hashObject(string FileName)
{
var xmlStream = File.OpenRead(FileName);
var md5 = MD5.Create();
byte[] md5HashByte = md5.ComputeHash(xmlStream);
string md5Hash = BitConverter.ToString(md5HashByte).Replace("-", "").ToLowerInvariant();
_md5hash = md5hash;
var sha1 = SHA1.Create();
byte[] sha1HashByte = sha1.ComputeHash(xmlStream);
string sha1Hash = BitConverter.ToString(sha1HashByte).Replace("-", "").ToLowerInvariant();
_sha1hash = sha1hash;
}
string _md5hash = "";
string _sha1hash = "";
public string md5hash
{
get
{
return _md5hash;
}
}
public string sha1hash
{
get
{
return _sha1hash;
}
}
}
}
}

112
gaseous-tools/Config.cs Normal file
View File

@@ -0,0 +1,112 @@
using System;
using Newtonsoft.Json;
namespace gaseous_tools
{
public static class Config
{
static ConfigFile _config;
public static string ConfigurationPath
{
get
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".gaseous-server");
}
}
static string ConfigurationFilePath
{
get
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".gaseous-server", "config.json");
}
}
static string ConfigurationFilePath_Backup
{
get
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".gaseous-server", "config.json.backup");
}
}
public static ConfigFile.Database DatabaseConfiguration
{
get
{
return _config.DatabaseConfiguration;
}
}
static Config()
{
if (_config == null)
{
// load the config file
if (File.Exists(ConfigurationFilePath))
{
string configRaw = File.ReadAllText(ConfigurationFilePath);
ConfigFile? _tempConfig = Newtonsoft.Json.JsonConvert.DeserializeObject<ConfigFile>(configRaw);
if (_tempConfig != null)
{
_config = _tempConfig;
} else
{
throw new Exception("There was an error reading the config file: Json returned null");
}
} else
{
// no config file!
// use defaults and save
_config = new ConfigFile();
string configRaw = Newtonsoft.Json.JsonConvert.SerializeObject(_config, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText(ConfigurationFilePath, configRaw);
}
}
Console.WriteLine("Using configuration:");
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(_config, Formatting.Indented));
}
public static void UpdateConfig()
{
// save any updates to the configuration
string configRaw = Newtonsoft.Json.JsonConvert.SerializeObject(_config, Newtonsoft.Json.Formatting.Indented);
if (File.Exists(ConfigurationFilePath_Backup))
{
File.Delete(ConfigurationFilePath_Backup);
}
if (File.Exists(ConfigurationFilePath))
{
File.Move(ConfigurationFilePath, ConfigurationFilePath_Backup);
}
File.WriteAllText(ConfigurationFilePath, configRaw);
}
public class ConfigFile
{
public Database DatabaseConfiguration = new Database();
public class Database
{
public string HostName = "localhost";
public string UserName = "gaseous";
public string Password = "gaseous";
public string DatabaseName = "gaseous";
public int Port = 3306;
[JsonIgnore]
public string ConnectionString
{
get
{
string dbConnString = "server=" + HostName + ";port=" + Port + ";userid=" + UserName + ";password=" + Password + ";database=" + DatabaseName + "";
return dbConnString;
}
}
}
}
}
}

192
gaseous-tools/Database.cs Normal file
View File

@@ -0,0 +1,192 @@
using System;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Reflection;
using MySql.Data.MySqlClient;
namespace gaseous_tools
{
public class Database
{
public Database()
{
}
public Database(databaseType Type, string ConnectionString)
{
_ConnectorType = Type;
_ConnectionString = ConnectionString;
}
public enum databaseType
{
MySql
}
string _ConnectionString = "";
public string ConnectionString
{
get
{
return _ConnectionString;
}
set
{
_ConnectionString = value;
}
}
databaseType? _ConnectorType = null;
public databaseType? ConnectorType
{
get
{
return _ConnectorType;
}
set
{
_ConnectorType = value;
}
}
public void InitDB()
{
// load resources
var assembly = Assembly.GetExecutingAssembly();
switch (_ConnectorType)
{
case databaseType.MySql:
// check if the database exists first - first run must have permissions to create a database
string sql = "CREATE DATABASE IF NOT EXISTS `" + Config.DatabaseConfiguration.DatabaseName + "`;";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
ExecuteCMD(sql, dbDict, 30, "server=" + Config.DatabaseConfiguration.HostName + ";port=" + Config.DatabaseConfiguration.Port + ";userid=" + Config.DatabaseConfiguration.UserName + ";password=" + Config.DatabaseConfiguration.Password);
// check if schema version table is in place - if not, create the schema version table
sql = "SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'gaseous' AND TABLE_NAME = 'schema_version';";
DataTable SchemaVersionPresent = ExecuteCMD(sql, dbDict);
if (SchemaVersionPresent.Rows.Count == 0)
{
// no schema table present - create it
sql = "CREATE TABLE `schema_version` (`schema_version` INT NOT NULL, PRIMARY KEY (`schema_version`)); INSERT INTO `schema_version` (`schema_version`) VALUES (0);";
ExecuteCMD(sql, dbDict);
}
for (int i = 1000; i < 10000; i++)
{
string resourceName = "gaseous_tools.Database.MySQL.gaseous-" + i + ".sql";
string dbScript = "";
string[] resources = Assembly.GetExecutingAssembly().GetManifestResourceNames();
if (resources.Contains(resourceName))
{
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
dbScript = reader.ReadToEnd();
// apply script
sql = "SELECT schema_version FROM schema_version;";
DataTable SchemaVersion = ExecuteCMD(sql, dbDict);
if (SchemaVersion.Rows.Count == 0)
{
// something is broken here... where's the table?
throw new Exception("schema_version table is missing!");
}
else
{
int SchemaVer = (int)SchemaVersion.Rows[0][0];
if (SchemaVer < i)
{
// apply schema!
ExecuteCMD(dbScript, dbDict);
sql = "UPDATE schema_version SET schema_version=@schemaver";
dbDict.Add("schemaver", i);
ExecuteCMD(sql, dbDict);
}
}
}
}
}
break;
}
}
public DataTable ExecuteCMD(string Command)
{
Dictionary<string, object> dbDict = new Dictionary<string, object>();
return _ExecuteCMD(Command, dbDict, 30, "");
}
public DataTable ExecuteCMD(string Command, Dictionary<string, object> Parameters)
{
return _ExecuteCMD(Command, Parameters, 30, "");
}
public DataTable ExecuteCMD(string Command, Dictionary<string, object> Parameters, int Timeout = 30, string ConnectionString = "")
{
return _ExecuteCMD(Command, Parameters, Timeout, ConnectionString);
}
private DataTable _ExecuteCMD(string Command, Dictionary<string, object> Parameters, int Timeout = 30, string ConnectionString = "")
{
if (ConnectionString == "") { ConnectionString = _ConnectionString; }
switch (_ConnectorType)
{
case databaseType.MySql:
MySQLServerConnector conn = new MySQLServerConnector(ConnectionString);
return (DataTable)conn.ExecCMD(Command, Parameters, Timeout);
default:
return new DataTable();
}
}
private partial class MySQLServerConnector
{
private string DBConn = "";
public MySQLServerConnector(string ConnectionString)
{
DBConn = ConnectionString;
}
public DataTable ExecCMD(string SQL, Dictionary<string, object> Parameters, int Timeout)
{
DataTable RetTable = new DataTable();
MySqlConnection conn = new MySqlConnection(DBConn);
conn.Open();
MySqlCommand cmd = new MySqlCommand
{
Connection = conn,
CommandText = SQL,
CommandTimeout = Timeout
};
foreach (string Parameter in Parameters.Keys)
{
cmd.Parameters.AddWithValue(Parameter, Parameters[Parameter]);
}
try
{
RetTable.Load(cmd.ExecuteReader());
} catch (Exception ex) {
Trace.WriteLine("Error executing " + SQL);
Trace.WriteLine("Full exception: " + ex.ToString());
}
conn.Close();
return RetTable;
}
}
}
}

View File

@@ -0,0 +1,146 @@
-- MySQL dump 10.13 Distrib 8.0.32, for macos13.0 (arm64)
--
-- Host: localhost Database: gaseous
-- ------------------------------------------------------
-- Server version 8.0.32
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `signatures_games`
--
DROP TABLE IF EXISTS `signatures_games`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `signatures_games` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`description` varchar(255) DEFAULT NULL,
`year` varchar(15) DEFAULT NULL,
`publisherid` int DEFAULT NULL,
`demo` int DEFAULT NULL,
`systemid` int DEFAULT NULL,
`systemvariant` varchar(100) DEFAULT NULL,
`video` varchar(10) DEFAULT NULL,
`country` varchar(5) DEFAULT NULL,
`language` varchar(5) DEFAULT NULL,
`copyright` varchar(15) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `publisher_idx` (`publisherid`),
KEY `system_idx` (`systemid`),
KEY `ingest_idx` (`name`,`year`,`publisherid`,`systemid`,`country`,`language`) USING BTREE,
CONSTRAINT `publisher` FOREIGN KEY (`publisherid`) REFERENCES `signatures_publishers` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `system` FOREIGN KEY (`systemid`) REFERENCES `signatures_platforms` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1466355 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `signatures_platforms`
--
DROP TABLE IF EXISTS `signatures_platforms`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `signatures_platforms` (
`id` int NOT NULL AUTO_INCREMENT,
`platform` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idsignatures_platforms_UNIQUE` (`id`),
KEY `platforms_idx` (`platform`,`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1231 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `signatures_publishers`
--
DROP TABLE IF EXISTS `signatures_publishers`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `signatures_publishers` (
`id` int NOT NULL AUTO_INCREMENT,
`publisher` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `publisher_idx` (`publisher`,`id`)
) ENGINE=InnoDB AUTO_INCREMENT=97693 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `signatures_roms`
--
DROP TABLE IF EXISTS `signatures_roms`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `signatures_roms` (
`id` int NOT NULL AUTO_INCREMENT,
`gameid` int DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`size` bigint DEFAULT NULL,
`crc` varchar(20) DEFAULT NULL,
`md5` varchar(100) DEFAULT NULL,
`sha1` varchar(100) DEFAULT NULL,
`developmentstatus` varchar(100) DEFAULT NULL,
`flags` json DEFAULT NULL,
`romtype` int DEFAULT NULL,
`romtypemedia` varchar(100) DEFAULT NULL,
`medialabel` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`,`gameid`) USING BTREE,
KEY `gameid_idx` (`gameid`),
KEY `md5_idx` (`md5`) USING BTREE,
KEY `sha1_idx` (`sha1`) USING BTREE,
KEY `flags_idx` ((cast(`flags` as char(255) array))),
CONSTRAINT `gameid` FOREIGN KEY (`gameid`) REFERENCES `signatures_games` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3350963 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `signatures_sources`
--
DROP TABLE IF EXISTS `signatures_sources`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `signatures_sources` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`description` varchar(255) DEFAULT NULL,
`category` varchar(45) DEFAULT NULL,
`version` varchar(45) DEFAULT NULL,
`author` varchar(255) DEFAULT NULL,
`email` varchar(45) DEFAULT NULL,
`homepage` varchar(45) DEFAULT NULL,
`url` varchar(45) DEFAULT NULL,
`sourcetype` varchar(45) DEFAULT NULL,
`sourcemd5` varchar(45) DEFAULT NULL,
`sourcesha1` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `sourcemd5_idx` (`sourcemd5`,`id`) USING BTREE,
KEY `sourcesha1_idx` (`sourcesha1`,`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=7573 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2023-02-27 8:54:22

View File

@@ -0,0 +1,25 @@
CREATE
ALGORITHM = UNDEFINED
DEFINER = `root`@`localhost`
SQL SECURITY DEFINER
VIEW `view_signatures_games` AS
SELECT
`signatures_games`.`id` AS `id`,
`signatures_games`.`name` AS `name`,
`signatures_games`.`description` AS `description`,
`signatures_games`.`year` AS `year`,
`signatures_games`.`publisherid` AS `publisherid`,
`signatures_publishers`.`publisher` AS `publisher`,
`signatures_games`.`demo` AS `demo`,
`signatures_games`.`systemid` AS `platformid`,
`signatures_platforms`.`platform` AS `platform`,
`signatures_games`.`systemvariant` AS `systemvariant`,
`signatures_games`.`video` AS `video`,
`signatures_games`.`country` AS `country`,
`signatures_games`.`language` AS `language`,
`signatures_games`.`copyright` AS `copyright`
FROM
((`signatures_games`
JOIN `signatures_publishers` ON ((`signatures_games`.`publisherid` = `signatures_publishers`.`id`)))
JOIN `signatures_platforms` ON ((`signatures_games`.`systemid` = `signatures_platforms`.`id`)));

View File

@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>gaseous_tools</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MySql.Data" Version="8.0.32" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>
<ItemGroup>
<None Remove="Database\" />
<None Remove="Database\MySQL\" />
<None Remove="Database\MySQL\gaseous-1000.sql" />
<None Remove="Database\MySQL\gaseous-1001.sql" />
</ItemGroup>
<ItemGroup>
<Folder Include="Database\" />
<Folder Include="Database\MySQL\" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Database\MySQL\gaseous-1000.sql" />
<EmbeddedResource Include="Database\MySQL\gaseous-1001.sql" />
</ItemGroup>
</Project>