diff --git a/AssM.csproj b/AssM.csproj index 5bf58c0..c6b55a4 100644 --- a/AssM.csproj +++ b/AssM.csproj @@ -5,11 +5,11 @@ enable true app.manifest - 1.8.1 + 1.9.0 SubZeroPL https://github.com/SubZeroPL/AssM - 1.8.1 - 1.8.1 + 1.9.0 + 1.9.0 AssM https://github.com/SubZeroPL/AssM/blob/master/LICENSE https://github.com/SubZeroPL/AssM/ @@ -19,17 +19,17 @@ - - - - - + + + + + - + - - - + + + diff --git a/Avalonia.Labs b/Avalonia.Labs index 657577c..7d86b80 160000 --- a/Avalonia.Labs +++ b/Avalonia.Labs @@ -1 +1 @@ -Subproject commit 657577c0d42872c2f922d83f3dbdf407bbcb6685 +Subproject commit 7d86b80d576b9c0052fda104303c1ec1acb74f53 diff --git a/Classes/Functions.cs b/Classes/Functions.cs index 06a5ba7..b0fc9d7 100644 --- a/Classes/Functions.cs +++ b/Classes/Functions.cs @@ -5,6 +5,8 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; using AssM.Data; using Avalonia.Threading; using DiscTools; @@ -12,7 +14,7 @@ namespace AssM.Classes; -public static class Functions +public static partial class Functions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); public static string OutputPath(Game game) => Path.Combine(game.Platform.ToString(), game.Id); @@ -229,12 +231,23 @@ public static List GetReadmeFilesInDirectory(string directory) public static Game? AddGameToList(string imagePath, Configuration configuration, ObservableCollection gameList) { Logger.Debug($"Adding game to list from {imagePath}"); - var di = DiscInspector.ScanDisc(imagePath); + var di = DiscInspector.ScanDiscQuick(imagePath); // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - apparently there are games that have no Id in image (like SLPS-00018) if (di.Data.SerialNumber == null) { - Logger.Error($"Failed to add game to list from {imagePath}{Environment.NewLine}Id not present in image"); - return null; + // let's try to find the ID manually + var id = ScanForId(imagePath); + if (id != null) + { + di.Data.SerialNumber = id; + di.DetectedDiscType = DetectedDiscType.SonyPS2; + } + else + { + Logger.Error( + $"Failed to add game to list from {imagePath}{Environment.NewLine}Id not present in image"); + return null; + } } var title = configuration.GetTitleFromCue ? Path.GetFileNameWithoutExtension(imagePath) : di.Data.GameTitle; @@ -259,6 +272,43 @@ public static List GetReadmeFilesInDirectory(string directory) return game; } + + [GeneratedRegex(@"(SL[A-Z]{2}_\d+\.\d+)(?=;)")] + private static partial Regex IdPsRegex(); + + [GeneratedRegex("""FILE "(.+\.bin)" BINARY""")] + private static partial Regex BinFile(); + + private static string? ScanForId(string imagePath) + { + if (imagePath.EndsWith(".cue", StringComparison.OrdinalIgnoreCase)) + { + var lines = File.ReadAllLines(imagePath); + var match = BinFile().Match(lines[0]); + if (match.Success) + { + var dir = Path.GetDirectoryName(imagePath); + var file = match.Groups[1].Value; + imagePath = Path.Join(dir, file); + } + } + using var fs = new FileStream(imagePath, FileMode.Open, FileAccess.Read); + var buf = new Span(new byte[1024 * 8]); + const int backtrack = 15; + var read = fs.Read(buf); + while (read > 0 && read != backtrack) + { + var textId = Encoding.ASCII.GetString(buf); + var matches = IdPsRegex().Match(textId); + if (matches.Success) + { + return matches.Groups[1].Value.Replace('_', '-').Replace(".", ""); + } + fs.Seek(-backtrack, SeekOrigin.Current); + read = fs.Read(buf); + } + return null; + } public static void ProcessJson(Configuration configuration, Game game, Action reportProgress) { diff --git a/Windows/AddFolderProgressWindow.axaml b/Windows/AddFolderProgressWindow.axaml index 42e5e7d..ce33eed 100644 --- a/Windows/AddFolderProgressWindow.axaml +++ b/Windows/AddFolderProgressWindow.axaml @@ -14,7 +14,7 @@ - + diff --git a/Windows/AddFolderProgressWindow.axaml.cs b/Windows/AddFolderProgressWindow.axaml.cs index d24fb08..c9e57af 100644 --- a/Windows/AddFolderProgressWindow.axaml.cs +++ b/Windows/AddFolderProgressWindow.axaml.cs @@ -6,6 +6,7 @@ using AssM.Data; using Avalonia.Controls; using Avalonia.Interactivity; +using Avalonia.Labs.Gif; namespace AssM.Windows; @@ -21,9 +22,13 @@ public partial class AddFolderProgressWindow : Window { private readonly BackgroundWorker _worker; + private readonly GifStreamSource _gifStreamSource = + GifStreamSource.FromUriString("avares://AssM/Assets/loading.gif"); + public AddFolderProgressWindow() { InitializeComponent(); + GifImage.Source = _gifStreamSource; _worker = new BackgroundWorker(); _worker.WorkerReportsProgress = true; _worker.WorkerSupportsCancellation = true; @@ -101,6 +106,7 @@ private void CancelButton_OnClick(object? sender, RoutedEventArgs e) private void Window_OnClosing(object? sender, WindowClosingEventArgs e) { _worker.CancelAsync(); + _gifStreamSource.Dispose(); if (!e.IsProgrammatic) e.Cancel = true; } } \ No newline at end of file diff --git a/Windows/MainWindow.axaml b/Windows/MainWindow.axaml index 185ef58..df3a7c1 100644 --- a/Windows/MainWindow.axaml +++ b/Windows/MainWindow.axaml @@ -76,11 +76,11 @@ - + + PlaceholderText="Enter game description" KeyUp="TextDescription_OnKeyUp">