DevTools: DAT->GameDB parser (currently only TOSEC implemented)

This commit is contained in:
Asnivor 2018-09-21 13:18:48 +01:00
parent 2ed0c919d2
commit 5d4d9c94a4
7 changed files with 1087 additions and 7 deletions

View File

@ -54,6 +54,14 @@
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Compile Include="DATTools\DATConverter.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="DATTools\DATConverter.Designer.cs">
<DependentUpon>DATConverter.cs</DependentUpon>
</Compile>
<Compile Include="DATTools\DATParserBase.cs" />
<Compile Include="DATTools\TOSECParser.cs" />
<Compile Include="DB.cs" />
<Compile Include="DBMan_MainForm.cs">
<SubType>Form</SubType>
@ -67,6 +75,9 @@
<Compile Include="DiscHash.cs" />
<Compile Include="PsxDBJob.cs" />
<Compile Include="RomHasher.cs" />
<EmbeddedResource Include="DATTools\DATConverter.resx">
<DependentUpon>DATConverter.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="DBMan_MainForm.resx">
<DependentUpon>DBMan_MainForm.cs</DependentUpon>
</EmbeddedResource>
@ -117,4 +128,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>

View File

@ -0,0 +1,201 @@
namespace BizHawk.Client.DBMan
{
partial class DATConverter
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.comboBoxSystemSelect = new System.Windows.Forms.ComboBox();
this.label1 = new System.Windows.Forms.Label();
this.groupImportTypes = new System.Windows.Forms.GroupBox();
this.radioTOSEC = new System.Windows.Forms.RadioButton();
this.listBoxFiles = new System.Windows.Forms.ListBox();
this.buttonAddFiles = new System.Windows.Forms.Button();
this.buttonRemove = new System.Windows.Forms.Button();
this.buttonStartProcessing = new System.Windows.Forms.Button();
this.textBoxOutputFolder = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.button2 = new System.Windows.Forms.Button();
this.groupImportTypes.SuspendLayout();
this.SuspendLayout();
//
// comboBoxSystemSelect
//
this.comboBoxSystemSelect.FormattingEnabled = true;
this.comboBoxSystemSelect.Location = new System.Drawing.Point(13, 13);
this.comboBoxSystemSelect.Name = "comboBoxSystemSelect";
this.comboBoxSystemSelect.Size = new System.Drawing.Size(121, 21);
this.comboBoxSystemSelect.TabIndex = 0;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(141, 20);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(74, 13);
this.label1.TabIndex = 1;
this.label1.Text = "Select System";
//
// groupImportTypes
//
this.groupImportTypes.Controls.Add(this.radioTOSEC);
this.groupImportTypes.Location = new System.Drawing.Point(13, 50);
this.groupImportTypes.Name = "groupImportTypes";
this.groupImportTypes.Size = new System.Drawing.Size(200, 100);
this.groupImportTypes.TabIndex = 2;
this.groupImportTypes.TabStop = false;
this.groupImportTypes.Text = "Import Type";
//
// radioTOSEC
//
this.radioTOSEC.AutoSize = true;
this.radioTOSEC.Location = new System.Drawing.Point(7, 20);
this.radioTOSEC.Name = "radioTOSEC";
this.radioTOSEC.Size = new System.Drawing.Size(61, 17);
this.radioTOSEC.TabIndex = 0;
this.radioTOSEC.TabStop = true;
this.radioTOSEC.Text = "TOSEC";
this.radioTOSEC.UseVisualStyleBackColor = true;
//
// listBoxFiles
//
this.listBoxFiles.FormattingEnabled = true;
this.listBoxFiles.HorizontalScrollbar = true;
this.listBoxFiles.Location = new System.Drawing.Point(13, 180);
this.listBoxFiles.Name = "listBoxFiles";
this.listBoxFiles.SelectionMode = System.Windows.Forms.SelectionMode.MultiExtended;
this.listBoxFiles.Size = new System.Drawing.Size(328, 121);
this.listBoxFiles.TabIndex = 3;
this.listBoxFiles.UseTabStops = false;
//
// buttonAddFiles
//
this.buttonAddFiles.Location = new System.Drawing.Point(348, 180);
this.buttonAddFiles.Name = "buttonAddFiles";
this.buttonAddFiles.Size = new System.Drawing.Size(107, 23);
this.buttonAddFiles.TabIndex = 4;
this.buttonAddFiles.Text = "Browse";
this.buttonAddFiles.UseVisualStyleBackColor = true;
this.buttonAddFiles.Click += new System.EventHandler(this.buttonAddFiles_Click);
//
// buttonRemove
//
this.buttonRemove.Location = new System.Drawing.Point(348, 210);
this.buttonRemove.Name = "buttonRemove";
this.buttonRemove.Size = new System.Drawing.Size(107, 23);
this.buttonRemove.TabIndex = 5;
this.buttonRemove.Text = "Remove";
this.buttonRemove.UseVisualStyleBackColor = true;
this.buttonRemove.Click += new System.EventHandler(this.buttonRemove_Click);
//
// buttonStartProcessing
//
this.buttonStartProcessing.Location = new System.Drawing.Point(13, 356);
this.buttonStartProcessing.Name = "buttonStartProcessing";
this.buttonStartProcessing.Size = new System.Drawing.Size(101, 23);
this.buttonStartProcessing.TabIndex = 6;
this.buttonStartProcessing.Text = "Start Processing";
this.buttonStartProcessing.UseVisualStyleBackColor = true;
this.buttonStartProcessing.Click += new System.EventHandler(this.buttonStartProcessing_Click);
//
// textBoxOutputFolder
//
this.textBoxOutputFolder.Location = new System.Drawing.Point(13, 330);
this.textBoxOutputFolder.Name = "textBoxOutputFolder";
this.textBoxOutputFolder.Size = new System.Drawing.Size(328, 20);
this.textBoxOutputFolder.TabIndex = 7;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(12, 164);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(75, 13);
this.label2.TabIndex = 8;
this.label2.Text = "Files to Import:";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(12, 314);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(87, 13);
this.label3.TabIndex = 9;
this.label3.Text = "Output Directory:";
//
// button2
//
this.button2.Location = new System.Drawing.Point(348, 328);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(107, 23);
this.button2.TabIndex = 10;
this.button2.Text = "Select Output DIR";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// DATConverter
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(469, 391);
this.Controls.Add(this.button2);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.textBoxOutputFolder);
this.Controls.Add(this.buttonStartProcessing);
this.Controls.Add(this.buttonRemove);
this.Controls.Add(this.buttonAddFiles);
this.Controls.Add(this.listBoxFiles);
this.Controls.Add(this.groupImportTypes);
this.Controls.Add(this.label1);
this.Controls.Add(this.comboBoxSystemSelect);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Name = "DATConverter";
this.Text = "DATConverter";
this.groupImportTypes.ResumeLayout(false);
this.groupImportTypes.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ComboBox comboBoxSystemSelect;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.GroupBox groupImportTypes;
private System.Windows.Forms.RadioButton radioTOSEC;
private System.Windows.Forms.ListBox listBoxFiles;
private System.Windows.Forms.Button buttonAddFiles;
private System.Windows.Forms.Button buttonRemove;
private System.Windows.Forms.Button buttonStartProcessing;
private System.Windows.Forms.TextBox textBoxOutputFolder;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button button2;
}
}

View File

@ -0,0 +1,153 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using BizHawk.Common;
using System.IO;
namespace BizHawk.Client.DBMan
{
public partial class DATConverter : Form
{
public DATConverter()
{
InitializeComponent();
var systems = Enum.GetValues(typeof(SystemType)).Cast<SystemType>().OrderBy(a => a.ToString()).ToList();
comboBoxSystemSelect.DataSource = systems;
textBoxOutputFolder.Text = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
}
/// <summary>
/// Choose output directory
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
var fbd = new FolderBrowserDialog();
fbd.ShowNewFolderButton = true;
fbd.Description = "Choose a new output folder";
if (fbd.ShowDialog() == DialogResult.OK)
{
textBoxOutputFolder.Text = fbd.SelectedPath;
}
}
/// <summary>
/// Add import files to the list box
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonAddFiles_Click(object sender, EventArgs e)
{
var ofd = new OpenFileDialog();
ofd.CheckFileExists = true;
ofd.CheckPathExists = true;
ofd.InitialDirectory = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
ofd.Multiselect = true;
if (ofd.ShowDialog() == DialogResult.OK)
{
foreach (var f in ofd.FileNames)
{
if (!listBoxFiles.Items.Contains((f)))
{
listBoxFiles.Items.Add(f);
}
}
}
}
/// <summary>
/// Removes selected input files from the listbox
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonRemove_Click(object sender, EventArgs e)
{
List<string> files = new List<string>();
foreach (var s in listBoxFiles.SelectedItems)
{
files.Add(s.ToString());
}
if (files.Count > 0)
{
foreach (var s in files)
listBoxFiles.Items.Remove(s);
}
}
/// <summary>
/// Attempt to process all selected files
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonStartProcessing_Click(object sender, EventArgs e)
{
// initial checks
var checkedBtn = groupImportTypes.Controls.OfType<RadioButton>().FirstOrDefault(r => r.Checked);
if (checkedBtn == null)
{
MessageBox.Show("You need to select an import type.");
return;
}
if (!Directory.Exists(textBoxOutputFolder.Text))
{
MessageBox.Show("Chosen output folder is not valid");
return;
}
if (listBoxFiles.Items.Count == 0)
{
MessageBox.Show("No files chosen for input");
return;
}
List<string> files = new List<string>();
foreach (var s in listBoxFiles.Items)
{
if (s.ToString().Trim() == "")
{
MessageBox.Show("The selected file: " + s.ToString() + "Cannot be found.\n\nSort this out and try again");
return;
}
files.Add((string)s);
}
string res = "";
if (radioTOSEC.Checked)
{
DATParser tp = new TOSECParser((SystemType)Enum.Parse(typeof(SystemType), comboBoxSystemSelect.SelectedValue.ToString()));
res = tp.ParseDAT(files.ToArray());
}
string fName = "gamedb_" +
GameDB.GetSystemCode((SystemType)Enum.Parse(typeof(SystemType), comboBoxSystemSelect.SelectedValue.ToString())) +
"_DevExport_" + DateTime.UtcNow.ToString("yyyy-MM-dd_HH_mm_ss");
try
{
File.WriteAllText(Path.Combine(textBoxOutputFolder.Text, fName), res);
}
catch (Exception ex)
{
MessageBox.Show("Error writing file: " + fName + "\n\n" + ex.Message);
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,193 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace BizHawk.Client.DBMan
{
public abstract class DATParser
{
/// <summary>
/// Required to generate a GameDB file
/// </summary>
public abstract SystemType SysType { get; set; }
/// <summary>
/// Parses a single DAT file
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public abstract void ParseDAT(object dat);
/// <summary>
/// Parses multiple DAT files and returns a single GamesDB format csv string
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public abstract string ParseDAT(string[] filePath);
protected List<string> IncomingData = new List<string>();
protected List<GameDB> Data = new List<GameDB>();
protected StringBuilder sb = new StringBuilder();
protected void AddCommentBlock(string comment)
{
sb.AppendLine(";;;;;;;;;;--------------------------------------------------;;;;;;;;;;");
sb.AppendLine(";;; " + comment.Replace("\r\n", "\r\n;;; "));
sb.AppendLine(";;;;;;;;;;--------------------------------------------------;;;;;;;;;;");
}
protected void AddCommentBlock(string[] comment)
{
sb.AppendLine(";;;;;;;;;;--------------------------------------------------;;;;;;;;;;");
for (int i = 0; i < comment.Length; i++)
{
sb.AppendLine(";;; " + comment[i]);
}
sb.AppendLine(";;;;;;;;;;--------------------------------------------------;;;;;;;;;;");
}
protected void AppendCSVData(List<GameDB> data)
{
if (data == null || data.Count == 0)
{
sb.AppendLine(";");
return;
}
foreach (var d in data)
{
// hash
sb.Append(d.HASH);
sb.Append("\t");
// status
sb.Append(d.Status);
sb.Append("\t");
// name
sb.Append(d.Name);
sb.Append("\t");
// system
sb.Append(d.System);
// notes
if (d.Notes != null)
{
sb.Append("\t");
sb.Append(d.Notes);
}
// metadata
if (d.MetaData != null)
{
sb.Append("\t");
sb.Append(d.MetaData);
}
// region
if (d.Region != null)
{
sb.Append("\t");
sb.Append(d.Region);
}
// force core
if (d.ForcedCore != null)
{
sb.Append("\t");
sb.Append(d.ForcedCore);
}
sb.Append("\r\n");
}
}
}
/// <summary>
/// DAT data is parsed into this object
/// (every field is not always used)
/// </summary>
public class GameDB
{
// COL0: Hash
public string SHA1 { get; set; }
public string MD5 { get; set; }
// COL1: Status code indicator
public string Status { get; set; }
// COL2: Game title
public string Name { get; set; }
// COL3: System code (must match what bizhawk uses in Emulation.Common/Database/Database.cs
public string System { get; set; }
// COL4: Unknown - not currently parsed in database.cs, but some gamedb files use this for publisher/genre/etc
public string Notes { get; set; }
// COL5: Metadata
public string MetaData { get; set; }
// COL6: Region
public string Region { get; set; }
// COL7: Forced Fore
public string ForcedCore { get; set; }
// prefer MD5 if available
public string HASH
{
get
{
if (MD5.Trim() == "")
return "sha1:" + SHA1;
return MD5;
}
}
/// <summary>
/// Used to get the correct system code (that each gamedb csv needs)
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static string GetSystemCode(SystemType type)
{
switch (type)
{
case SystemType.P83:
return "83P";
case SystemType.X32:
return "32X";
default:
return type.ToString();
}
}
}
public enum SystemType
{
SAT,
PSP,
PSX,
GEN,
PCFX,
PCECD,
GB,
DGB,
AppleII,
C64,
ZXSpectrum,
AmstradCPC,
SNES,
NES,
P83,
GBC,
A78,
GBA,
X32,
GG,
SG,
SGX,
A26,
Coleco,
INTV,
N64,
WSWAN,
Lynx,
VB,
UZE
}
}

View File

@ -0,0 +1,384 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using System.Xml;
using System.Windows.Forms;
namespace BizHawk.Client.DBMan
{
public class TOSECParser : DATParser
{
/// <summary>
/// Required to generate a GameDB file
/// </summary>
public override SystemType SysType { get; set; }
private List<XDocument> xmls = new List<XDocument>();
public TOSECParser(SystemType type)
{
SysType = type;
}
/// <summary>
/// Parses multiple DAT files and returns a single GamesDB format csv string
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public override string ParseDAT(string[] filePath)
{
foreach (var s in filePath)
{
try
{
xmls.Add(XDocument.Load(s));
}
catch
{
var res = MessageBox.Show("Could not parse document as valid XML:\n\n" + s + "\n\nDo you wish to continue any other processing?", "Parsing Error", MessageBoxButtons.YesNo);
if (res != DialogResult.Yes)
return "";
}
}
int startIndex = 0;
// actual tosec parsing
foreach (var obj in xmls)
{
startIndex = Data.Count > 0 ? Data.Count - 1 : 0;
// get header info
var header = obj.Root.Descendants("header").First();
var category = header.Element("category").Value;
var name = header.Element("name").Value;
var version = header.Element("version").Value;
var description = header.Element("description").Value;
// start comment block
List<string> comments = new List<string>
{
"Type:\t" + category,
"Source:\t" + description,
"FileGen:\t" + DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss") + " (UTC)",
};
AddCommentBlock(comments.ToArray());
// process each entry
var query = obj.Root.Descendants("game");
foreach (var g in query)
{
GameDB item = new GameDB();
item.Name = g.Value;
item.SHA1 = g.Elements("rom").First().Attribute("sha1").Value.ToUpper();
item.MD5 = g.Elements("rom").First().Attribute("md5").Value.ToUpper();
item.System = GameDB.GetSystemCode(SysType);
ParseTOSECFlags(item);
Data.Add(item);
}
// add this file's data to the stringbuilder
// first we will sort into various ROMSTATUS groups
var working = Data.Skip(startIndex).ToList();
var baddump = working.Where(st => st.Status == "B").OrderBy(na => na.Name).ToList();
AddCommentBlock("Bad Dumps");
AppendCSVData(baddump);
var hack = working.Where(st => st.Status == "H").OrderBy(na => na.Name).ToList();
AddCommentBlock("Hacks");
AppendCSVData(hack);
var over = working.Where(st => st.Status == "O").OrderBy(na => na.Name).ToList();
AddCommentBlock("Over Dumps");
AppendCSVData(over);
var trans = working.Where(st => st.Status == "T").OrderBy(na => na.Name).ToList();
AddCommentBlock("Translated");
AppendCSVData(trans);
var good = working.Where(st => st.Status == "" || st.Status == null).OrderBy(na => na.Name).ToList();
AddCommentBlock("Believed Good");
AppendCSVData(good);
}
string result = sb.ToString();
return sb.ToString();
}
/// <summary>
/// Parses all the weird TOSEC flags within the game field
/// Detailed info here: https://www.tosecdev.org/tosec-naming-convention
/// Guts of this has been reused from here: https://github.com/Asnivor/MedLaunch/blob/master/MedLaunch/_Debug/DATDB/Platforms/TOSEC/StringConverterToSec.cs
/// </summary>
/// <param name="g"></param>
private void ParseTOSECFlags(GameDB g)
{
string nameString = g.Name;
// remove uninteresting options
string a = RemoveUnneededOptions(nameString);
// process data contained in ()
string[] d = a.ToString().Split('(', ')');
if (d.Length > 0)
{
// name field
}
if (d.Length > 1)
{
if (d[1].Length > 3)
{
// year field
}
}
if (d.Length > 3)
{
// publisher field
}
if (d.Length > 4)
{
// parse all other () fields
// because these are not mandatory this can be a confusing process
for (int i = 4; i < d.Length; i++)
{
string f = d[i];
// system field
if (f == "Aladdin Deck Enhancer" ||
f == "PlayChoice-10" ||
f == "VS DualSystem" ||
f == "VS UniSystem")
{
// ignore for now (not currently implemented)
continue;
}
// country flag(s)
if (IsCountryFlag(f) == true)
{
g.Region = f;
continue;
}
// language - if present add to notes
if (IsLanguageFlag(f) == true)
{
g.Notes = f;
continue;
}
// check copyright status (not currently implemented)
if (IsCopyrightStatus(f) == true)
{
continue;
}
// check development status (not currently implemented)
if (IsDevelopmenttStatus(f) == true)
{
continue;
}
// Media Type - ignore for now
// Media Label - ignore for now
}
// process dump info flags and other info contained in []
if (nameString.Contains("[") && nameString.Contains("]"))
{
List<string> e = nameString.ToString().Split('[', ']').ToList();
// remove first entry (this is the bit before the [] entries start
e.RemoveAt(0);
// remove empty entries
e = e.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToList();
if (e.Count > 0)
{
// bizhawk currently only has a few different RomStatus values (not as many as TOSEC anyway)
// Parsing priority will be:
// RomStatus.BadDump
// RomStatus.Hack
// RomStatus.Overdump
// RomStatus.GoodDump
// RomStatus.TranslatedRom
// everything else
// all tosec cr, h, t etc.. will fall under RomStatus.Hack
if (e.Where(str =>
// bad dump
str == "b" || str.StartsWith("b ") ||
// virus
str == "v" || str.StartsWith("v ") ||
// under dump
str == "u" || str.StartsWith("u ")).ToList().Count > 0)
{
// RomStatus.BadDump
g.Status = "B";
}
else if (e.Where(str =>
// cracked
str == "cr" || str.StartsWith("cr ") ||
// fixed
str == "f" || str.StartsWith("f ") ||
// hack
str == "h" || str.StartsWith("h ") ||
// modified
str == "m" || str.StartsWith("m ") ||
// pirated
str == "p" || str.StartsWith("p ") ||
// trained
str == "t" || str.StartsWith("t ")
).ToList().Count > 0)
{
// RomStatus.Hack
g.Status = "H";
}
else if (e.Where(str =>
// over dump
str == "o" || str.StartsWith("o ")).ToList().Count > 0)
{
// RomStatus.Overdump
g.Status = "O";
}
else if (e.Where(str =>
// known verified dump
str == "!").ToList().Count > 0)
{
// RomStatus.GoodDump
g.Status = "";
}
else if (e.Where(str =>
// translated
str == "tr" || str.StartsWith("tr ")).ToList().Count > 0)
{
// RomStatus.TranslatedRom
g.Status = "T";
}
}
}
}
}
public static bool IsDevelopmenttStatus(string s)
{
List<string> DS = new List<string>
{
"alpha", "beta", "preview", "pre-release", "proto"
};
bool b = DS.Any(s.Contains);
return b;
}
public static bool IsCopyrightStatus(string s)
{
List<string> CS = new List<string>
{
"CW", "CW-R", "FW", "GW", "GW-R", "LW", "PD", "SW", "SW-R"
};
bool b = CS.Any(s.Contains);
return b;
}
public static bool IsLanguageFlag(string s)
{
List<string> LC = new List<string>
{
"ar", "bg", "bs", "cs", "cy", "da", "de", "el", "en", "eo", "es", "et", "fa", "fi", "fr", "ga",
"gu", "he", "hi", "hr", "hu", "is", "it", "ja", "ko", "lt", "lv", "ms", "nl", "no", "pl", "pt",
"ro", "ru", "sk", "sl", "sq", "sr", "sv", "th", "tr", "ur", "vi", "yi", "zh", "M1", "M2", "M3",
"M4", "M5", "M6", "M7", "M8", "M9"
};
bool b = false;
if (!s.Contains("[") && !s.Contains("]"))
{
foreach (var x in LC)
{
if (s == x || s.StartsWith(x) || s.EndsWith(x))
{
b = true;
break;
}
}
//b = LC.Any(s.Contains);
}
return b;
}
public static bool IsCountryFlag(string s)
{
List<string> CC = new List<string>
{
"AE", "AL", "AS", "AT", "AU", "BA", "BE", "BG", "BR", "CA", "CH", "CL", "CN", "CS", "CY", "CZ",
"DE", "DK", "EE", "EG", "EU", "ES", "FI", "FR", "GB", "GR", "HK", "HR", "HU", "ID", "IE", "IL",
"IN", "IR", "IS", "IT", "JO", "JP", "KR", "LT", "LU", "LV", "MN", "MX", "MY", "NL", "NO", "NP",
"NZ", "OM", "PE", "PH", "PL", "PT", "QA", "RO", "RU", "SE", "SG", "SI", "SK", "TH", "TR", "TW",
"US", "VN", "YU", "ZA"
};
bool b = false;
if (!s.Contains("[") && !s.Contains("]"))
{
foreach (var x in CC)
{
if (s == x || s.StartsWith(x) || s.EndsWith(x))
{
b = true;
break;
}
}
//b = CC.Any(s.Contains);
}
return b;
}
public static string RemoveUnneededOptions(string nameString)
{
// Remove unneeded entries
string n = nameString
.Replace(" (demo) ", " ")
.Replace(" (demo-kiosk) ", " ")
.Replace(" (demo-playable) ", " ")
.Replace(" (demo-rolling) ", " ")
.Replace(" (demo-slideshow) ", " ");
return n;
}
/// <summary>
/// Parses a single DAT file
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public override void ParseDAT(object xml)
{
try
{
var obj = (XDocument)xml;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
}
}

View File

@ -97,26 +97,44 @@ namespace BizHawk.Client.DBMan
new PsxDBJob().Run(args.Skip(1).ToArray());
return;
}
if (args.Length > 0 && args[0] == "--dbman")
{
try
{
InitDB();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new DBMan_MainForm());
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
finally
{
if (DB.Con != null) DB.Con.Dispose();
}
return;
}
//if (args.Length > 0 && args[0] == "--disccmp")
//{
// new DiscCmp().Run(args.Skip(1).ToArray());
// return;
//}
try
{
InitDB();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new DBMan_MainForm());
Application.Run(new DATConverter());
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
finally
{
if (DB.Con != null) DB.Con.Dispose();
}
return;
}
static void InitDB()