AxibugEmuOnline/Tools/MAMEHashTool/Program.cs
2025-01-25 09:58:12 +08:00

298 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Globalization;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
using System.Xml.Linq;
namespace MAMEHashTool
{
class roomHashInfo
{
public int RomID { get; set; }
public string RomDirName { get; set; }
public string RomAllFileHash { get; set; }
public string ParentName { get; set; }
public int ParentID { get; set; }
public string desc { get; set; }
public string board { get; set; }
public string year { get; set; }
public string manufacturer { get; set; }
}
internal class Program
{
static Dictionary<int, roomHashInfo> dict = new Dictionary<int, roomHashInfo>();
static Dictionary<string, int> dictName2RomID = new Dictionary<string, int>();
static string romRootDir = "G:\\MAME.Core\\roms";
static HashSet<string> NoInDB = new HashSet<string>();
static HashSet<string> NotfindParent = new HashSet<string>();
static void Main(string[] args)
{
int RoomSeed = 10000;
MAMEDBHelper.LoadROMXML(File.ReadAllText("./mame.xml"));
// 获取当前程序所在目录
string currentDirectory = romRootDir;
// 列出当前目录下的所有文件夹
string[] directories = Directory.GetDirectories(currentDirectory);
// 文件夹名称
foreach (string directory in directories)
{
// 使用Path.GetFileName来获取文件夹名称不包含路径
string directoryName = Path.GetFileName(directory);
Console.WriteLine($"正在处理,{RoomSeed}|{directoryName}");
string[] files = Directory.GetFiles(directory);
List<byte[]> filedatas = new List<byte[]>();
foreach (string file in files)
{
filedatas.Add(File.ReadAllBytes(file));
}
if (!RomInfo.dictName2Rom.ContainsKey(directoryName))
{
if (!NoInDB.Contains(directoryName))
NoInDB.Add(directoryName);
Console.WriteLine($"数据库中不存在|{directoryName}");
continue;
}
RomInfo xmlinfo = RomInfo.dictName2Rom[directoryName];
roomHashInfo hashrom = new roomHashInfo()
{
RomID = RoomSeed,
ParentName = xmlinfo.Parent,
RomDirName = directoryName,
RomAllFileHash = FileMD5Hash(filedatas),
board = xmlinfo.Board,
desc = xmlinfo.Description,
manufacturer = xmlinfo.Manufacturer,
year = xmlinfo.Year,
};
dict[RoomSeed] = hashrom;
dictName2RomID[hashrom.RomDirName] = RoomSeed;
//StartZip(romRootDir, directory);
RoomSeed++;
}
foreach (var rom in dict.Values)
{
if (string.IsNullOrEmpty(rom.ParentName))
continue;
if (!dictName2RomID.ContainsKey(rom.ParentName))
{
Console.WriteLine($"父级{rom.ParentName}无法找到");
if (!NotfindParent.Contains(rom.ParentName))
NotfindParent.Add(rom.ParentName);
continue;
}
rom.ParentID = dictName2RomID[rom.ParentName];
}
List<string> tempOutInfoList = new List<string>();
foreach (var rom in dict.Values)
{
string ParentID = rom.ParentID == 0 ? "" : rom.ParentID.ToString();
tempOutInfoList.Add($"{rom.RomID}|{rom.RomDirName}|{rom.board}|{rom.year}|{rom.manufacturer}|{rom.desc}|{rom.RomAllFileHash}|{ParentID}");
}
Console.WriteLine($"共{NoInDB.Count}个数据库中不存在");
tempOutInfoList.Add($"共{NoInDB.Count}个数据库中不存在");
foreach (var name in NoInDB)
{
tempOutInfoList.Add(name);
}
Console.WriteLine($"共{NotfindParent.Count}个父级没找到");
tempOutInfoList.Add($"共{NotfindParent.Count}个父级没找到");
foreach (var name in NotfindParent)
{
tempOutInfoList.Add(name);
}
try
{
File.WriteAllLines(romRootDir + "//axiromInfolist.txt", tempOutInfoList);
Console.WriteLine($"写入文件完毕");
}
catch (Exception ex)
{
Console.WriteLine($"写入文件失败:{ex}");
}
Console.ReadLine();
}
static void StartZip(string rootPath, string subDirectory)
{
Console.WriteLine($"压缩{subDirectory}");
string subDirectoryName = Path.GetFileName(subDirectory); // 获取子文件夹名称
string zipFileName = Path.Combine(rootPath, subDirectoryName + ".zip"); // 构建ZIP文件名
// 创建ZIP文件
using (FileStream zipStream = new FileStream(zipFileName, FileMode.Create))
using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create))
{
// 遍历子文件夹中的所有文件并将它们添加到ZIP文件中
foreach (string filePath in Directory.GetFiles(subDirectory, "*.*", SearchOption.AllDirectories))
{
// 获取相对于子文件夹的路径以便在ZIP文件中保持正确的目录结构
string relativePath = filePath.Substring(subDirectory.Length + 1); // +1 是为了排除子文件夹路径末尾的反斜杠
// 创建ZIP条目使用相对于子文件夹的路径作为条目名称
ZipArchiveEntry entry = archive.CreateEntry(relativePath, CompressionLevel.SmallestSize);
// 打开ZIP条目以进行写入
using (Stream entryStream = entry.Open())
{
// 读取文件内容并写入ZIP条目
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
fileStream.CopyTo(entryStream);
}
}
}
}
Console.WriteLine($"Compressed {subDirectoryName} to {zipFileName}");
}
static byte[] FileMD5HashByte(byte[] data)
{
using (var md5 = MD5.Create())
{
using (var stream = new MemoryStream(data))
{
return md5.ComputeHash(stream);
}
}
}
/// <summary>
/// 单个文件hash
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static string FileMD5Hash(byte[] data)
{
byte[] hash = FileMD5HashByte(data);
var sb = new StringBuilder(hash.Length * 2);
foreach (var b in hash)
sb.AppendFormat("{0:x2}", b);
return sb.ToString();
}
/// <summary>
/// 多文件总hash (顺序不影响结果)
/// </summary>
/// <param name="dataList"></param>
/// <returns></returns>
public static string FileMD5Hash(List<byte[]> dataList)
{
string allhash = string.Empty;
List<string> temp = new List<string>();
for (int i = 0; i < dataList.Count; i++)
{
if (dataList[i] == null)
continue;
temp.Add(FileMD5Hash(dataList[i]));
}
temp.Sort();
var sb = new StringBuilder();
for (int i = 0; i < temp.Count; i++)
{
sb.AppendLine(temp[i].ToString());
}
//这里用Ascll
return FileMD5Hash(Encoding.ASCII.GetBytes(sb.ToString()));
}
}
public class MAMEDBHelper
{
public static void LoadROMXML(string xmbString)
{
XElement xe = XElement.Parse(xmbString);
IEnumerable<XElement> elements = from ele in xe.Elements("game") select ele;
showInfoByElements(elements);
}
static void showInfoByElements(IEnumerable<XElement> elements)
{
RomInfo.romList = new List<RomInfo>();
RomInfo.dictName2Rom = new Dictionary<string, RomInfo>();
foreach (var ele in elements)
{
RomInfo rom = new RomInfo();
rom.Name = ele.Attribute("name").Value;
rom.Board = ele.Attribute("board").Value;
rom.Parent = ele.Element("parent").Value;
rom.Direction = ele.Element("direction").Value;
rom.Description = ele.Element("description").Value;
rom.Year = ele.Element("year").Value;
rom.Manufacturer = ele.Element("manufacturer").Value;
RomInfo.romList.Add(rom);
RomInfo.dictName2Rom[rom.Name] = rom;
//loadform.listView1.Items.Add(new ListViewItem(new string[] { rom.Description, rom.Year, rom.Name, rom.Parent, rom.Direction, rom.Manufacturer, rom.Board }));
}
}
}
public class RomInfo
{
public static List<RomInfo> romList = new List<RomInfo>();
public static Dictionary<string, RomInfo> dictName2Rom = new Dictionary<string, RomInfo>();
public static RomInfo Rom;
public string Name, Board;
public string Parent;
public string Direction;
public string Description;
public string Year;
public string Manufacturer;
public string M1Default, M1Stop, M1Min, M1Max, M1Subtype;
public static ushort IStop;
public RomInfo()
{
}
public static RomInfo GetRomByName(string s1)
{
if (!dictName2Rom.TryGetValue(s1, out RomInfo info))
return null;
return info;
}
public static string GetParent(string s1)
{
string sParent = "";
foreach (RomInfo ri in romList)
{
if (s1 == ri.Name)
{
sParent = ri.Parent;
break;
}
}
return sParent;
}
public static List<string> GetParents(string s1)
{
string sChild, sParent;
List<string> ls1 = new List<string>();
sChild = s1;
while (sChild != "")
{
ls1.Add(sChild);
sParent = GetParent(sChild);
sChild = sParent;
}
return ls1;
}
}
}