diff --git a/tools/GSDumpGUI/Forms/Entities/GsDlls.cs b/tools/GSDumpGUI/Forms/Entities/GsDlls.cs new file mode 100644 index 000000000..1b18b3795 --- /dev/null +++ b/tools/GSDumpGUI/Forms/Entities/GsDlls.cs @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2009-2019 PCSX2 Dev Team + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +namespace GSDumpGUI.Forms.Entities +{ + public sealed class GsDlls : GsFiles { } +} \ No newline at end of file diff --git a/tools/GSDumpGUI/Forms/Entities/GsDumpFile.cs b/tools/GSDumpGUI/Forms/Entities/GsDumpFile.cs new file mode 100644 index 000000000..d6250fc5a --- /dev/null +++ b/tools/GSDumpGUI/Forms/Entities/GsDumpFile.cs @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2009-2019 PCSX2 Dev Team + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +using System.IO; + +namespace GSDumpGUI.Forms.Entities +{ + public sealed class GsDumpFile : GsFile + { + public FileInfo PreviewFile { get; set; } + } +} \ No newline at end of file diff --git a/tools/GSDumpGUI/Forms/Entities/GsDumps.cs b/tools/GSDumpGUI/Forms/Entities/GsDumps.cs new file mode 100644 index 000000000..e58878236 --- /dev/null +++ b/tools/GSDumpGUI/Forms/Entities/GsDumps.cs @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2009-2019 PCSX2 Dev Team + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +using System.IO; + +namespace GSDumpGUI.Forms.Entities +{ + public sealed class GsDumps : GsFiles + { + private FileInfo GsDumpPreviewFile { get; set; } + } +} diff --git a/tools/GSDumpGUI/Forms/Entities/GsFile.cs b/tools/GSDumpGUI/Forms/Entities/GsFile.cs new file mode 100644 index 000000000..b098ee1ee --- /dev/null +++ b/tools/GSDumpGUI/Forms/Entities/GsFile.cs @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2009-2019 PCSX2 Dev Team + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +using System.IO; + +namespace GSDumpGUI.Forms.Entities +{ + public class GsFile + { + public FileInfo File { get; set; } + public string DisplayText { get; set; } + } +} \ No newline at end of file diff --git a/tools/GSDumpGUI/Forms/Entities/GsFiles.cs b/tools/GSDumpGUI/Forms/Entities/GsFiles.cs new file mode 100644 index 000000000..6a882a448 --- /dev/null +++ b/tools/GSDumpGUI/Forms/Entities/GsFiles.cs @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2009-2019 PCSX2 Dev Team + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +using System; +using System.ComponentModel; + +namespace GSDumpGUI.Forms.Entities +{ + public abstract class GsFiles + where TUnderlying : GsFile + { + private int _selectedFileIndex = -1; + + public class SelectedIndexUpdatedEventArgs + { + public SelectedIndexUpdatedEventArgs(int formerIndex, int updatedIndex) + { + FormerIndex = formerIndex; + UpdatedIndex = updatedIndex; + } + + public int FormerIndex { get; } + public int UpdatedIndex { get; } + } + + public delegate void SelectedIndexUpdateEventHandler(object sender, SelectedIndexUpdatedEventArgs args); + + public event SelectedIndexUpdateEventHandler OnIndexUpdatedEvent; + public BindingList Files { get; } = new BindingList(); + + public int SelectedFileIndex + { + get + { + return _selectedFileIndex; + } + set + { + var oldValue = _selectedFileIndex; + _selectedFileIndex = value; + OnIndexUpdatedEvent?.Invoke(this, new SelectedIndexUpdatedEventArgs(oldValue, value)); + } + } + + public bool IsSelected => SelectedFileIndex != -1 && Files.Count > SelectedFileIndex; + + public TUnderlying Selected + { + get + { + return SelectedFileIndex >= 0 ? Files[SelectedFileIndex] : null; + } + set + { + SelectedFileIndex = Files.IndexOf(value); + } + } + } +} \ No newline at end of file diff --git a/tools/GSDumpGUI/Forms/Helper/FolderWithFallBackFinder.cs b/tools/GSDumpGUI/Forms/Helper/FolderWithFallBackFinder.cs new file mode 100644 index 000000000..9279dfc9c --- /dev/null +++ b/tools/GSDumpGUI/Forms/Helper/FolderWithFallBackFinder.cs @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2009-2019 PCSX2 Dev Team + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +using System; +using System.IO; +using System.Linq; + +namespace GSDumpGUI.Forms.Helper +{ + public class FolderWithFallBackFinder : IFolderWithFallBackFinder + { + public DirectoryInfo GetViaPatternWithFallback(string defaultDir, string filePattern, params string[] fallBackFolder) + { + if (!string.IsNullOrWhiteSpace(defaultDir)) + return new DirectoryInfo(defaultDir); + + DirectoryInfo gsdxDllDirectory; + if (TryGetExistingDirectory(fallBackFolder, filePattern, out gsdxDllDirectory)) + return gsdxDllDirectory; + return new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory); + } + + private static bool TryGetExistingDirectory(string[] relativePaths, string pattern, out DirectoryInfo validDirectory) + { + if (relativePaths == null) + throw new ArgumentNullException(nameof(relativePaths)); + foreach (var relativePath in relativePaths) + { + + var candidate = new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, relativePath)); + if (candidate.Exists && candidate.GetFiles(pattern).Any()) + { + validDirectory = candidate; + return true; + } + } + + validDirectory = null; + return false; + } + } +} diff --git a/tools/GSDumpGUI/Forms/Helper/GsDumpFinder.cs b/tools/GSDumpGUI/Forms/Helper/GsDumpFinder.cs new file mode 100644 index 000000000..1e575750b --- /dev/null +++ b/tools/GSDumpGUI/Forms/Helper/GsDumpFinder.cs @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009-2011 Ferreri Alessio + * Copyright (C) 2009-2019 PCSX2 Dev Team + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +using System.Collections.Generic; +using System.IO; +using GSDumpGUI.Forms.Entities; + +namespace GSDumpGUI.Forms.Helper +{ + public class GsDumpFinder : IGsDumpFinder + { + private readonly ILogger _logger; + + public GsDumpFinder(ILogger logger) + { + _logger = logger; + } + + public IEnumerable GetValidGsdxDumps(DirectoryInfo directory) + { + var dumps = directory.GetFiles("*.gs", SearchOption.TopDirectoryOnly); + + foreach (var dump in dumps) + { + int crc; + using (var fileStream = File.Open(dump.FullName, FileMode.Open)) + { + using (var br = new BinaryReader(fileStream)) + { + crc = br.ReadInt32(); + br.Close(); + } + } + + var extensions = new[] {".png", ".bmp"}; + var dumpPreview = default(FileInfo); + foreach (var extension in extensions) + { + var imageFile = new FileInfo(Path.ChangeExtension(dump.FullName, extension)); + if (!imageFile.Exists) + continue; + dumpPreview = imageFile; + break; + } + + _logger.Information($"Identified Dump for game ({crc:X}) with filename '{dump}'"); + yield return new GsDumpFile + { + DisplayText = dump.Name + " | CRC : " + crc.ToString("X"), + File = dump, + PreviewFile = dumpPreview + }; + } + } + } +} diff --git a/tools/GSDumpGUI/Forms/Helper/GsdxDllFinder.cs b/tools/GSDumpGUI/Forms/Helper/GsdxDllFinder.cs new file mode 100644 index 000000000..5fbe15907 --- /dev/null +++ b/tools/GSDumpGUI/Forms/Helper/GsdxDllFinder.cs @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2009-2011 Ferreri Alessio + * Copyright (C) 2009-2019 PCSX2 Dev Team + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +using System.Collections.Generic; +using System.IO; +using GSDumpGUI.Forms.Entities; + +namespace GSDumpGUI.Forms.Helper +{ + public class GsdxDllFinder : IGsdxDllFinder + { + private readonly ILogger _logger; + + public GsdxDllFinder(ILogger logger) + { + _logger = logger; + } + + public IEnumerable GetEnrichedPathToValidGsdxDlls(DirectoryInfo directory) + { + var availableDlls = directory.GetFiles("*.dll", SearchOption.TopDirectoryOnly); + + var wrap = new GSDXWrapper(); + foreach (var availableDll in availableDlls) + { + GsFile dll; + try + { + wrap.Load(availableDll.FullName); + + dll = new GsFile + { + DisplayText = availableDll.Name + " | " + wrap.PSEGetLibName(), + File = availableDll + }; + _logger.Information($"'{availableDll}' correctly identified as '{wrap.PSEGetLibName()}'"); + + wrap.Unload(); + } + catch (InvalidGSPlugin) + { + _logger.Warning($"Failed to load '{availableDll}'. Is it really a GSdx DLL?"); + continue; + } + + yield return dll; + } + } + } +} diff --git a/tools/GSDumpGUI/Forms/Helper/IFolderWithFallBackFinder.cs b/tools/GSDumpGUI/Forms/Helper/IFolderWithFallBackFinder.cs new file mode 100644 index 000000000..6905006f0 --- /dev/null +++ b/tools/GSDumpGUI/Forms/Helper/IFolderWithFallBackFinder.cs @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2009-2019 PCSX2 Dev Team + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +using System.IO; + +namespace GSDumpGUI.Forms.Helper +{ + public interface IFolderWithFallBackFinder + { + DirectoryInfo GetViaPatternWithFallback(string defaultDir, string filePattern, params string[] fallBackFolder); + } +} \ No newline at end of file diff --git a/tools/GSDumpGUI/Forms/Helper/IGsDumpFinder.cs b/tools/GSDumpGUI/Forms/Helper/IGsDumpFinder.cs new file mode 100644 index 000000000..27682aad2 --- /dev/null +++ b/tools/GSDumpGUI/Forms/Helper/IGsDumpFinder.cs @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2009-2019 PCSX2 Dev Team + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +using System.Collections.Generic; +using System.IO; +using GSDumpGUI.Forms.Entities; + +namespace GSDumpGUI.Forms.Helper +{ + public interface IGsDumpFinder + { + IEnumerable GetValidGsdxDumps(DirectoryInfo directory); + } +} \ No newline at end of file diff --git a/tools/GSDumpGUI/Forms/Helper/IGsdxDllFinder.cs b/tools/GSDumpGUI/Forms/Helper/IGsdxDllFinder.cs new file mode 100644 index 000000000..d4d129fee --- /dev/null +++ b/tools/GSDumpGUI/Forms/Helper/IGsdxDllFinder.cs @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2009-2019 PCSX2 Dev Team + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +using System.Collections.Generic; +using System.IO; +using GSDumpGUI.Forms.Entities; + +namespace GSDumpGUI.Forms.Helper +{ + public interface IGsdxDllFinder + { + IEnumerable GetEnrichedPathToValidGsdxDlls(DirectoryInfo directory); + } +} \ No newline at end of file diff --git a/tools/GSDumpGUI/Forms/Helper/ILogger.cs b/tools/GSDumpGUI/Forms/Helper/ILogger.cs new file mode 100644 index 000000000..d771d65f6 --- /dev/null +++ b/tools/GSDumpGUI/Forms/Helper/ILogger.cs @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2009-2019 PCSX2 Dev Team + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +namespace GSDumpGUI.Forms.Helper +{ + public interface ILogger + { + void Information(string line = null); + void Warning(string line = null); + void Error(string line = null); + } +} \ No newline at end of file diff --git a/tools/GSDumpGUI/Forms/Helper/RichTextBoxLogger.cs b/tools/GSDumpGUI/Forms/Helper/RichTextBoxLogger.cs new file mode 100644 index 000000000..7f37a8e52 --- /dev/null +++ b/tools/GSDumpGUI/Forms/Helper/RichTextBoxLogger.cs @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2009-2019 PCSX2 Dev Team + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GSDumpGUI.Forms.Helper +{ + public class RichTextBoxLogger : ILogger + { + private readonly RichTextBox _richTextBox; + public RichTextBoxLogger(RichTextBox richTextBox) + { + _richTextBox = richTextBox; + _richTextBox.BackColor = Color.White; + _richTextBox.Focus(); + _richTextBox.HideSelection = false; + } + + private void WriteLine(Color color, string line = null) + { + _richTextBox.Invoke(new MethodInvoker(delegate + { + ThreadLocalWrite(color, line); + })); + } + + private void ThreadLocalWrite(Color color, string line) + { + if (line == null) + { + _richTextBox.AppendText(Environment.NewLine); + return; + } + + _richTextBox.SelectionStart = _richTextBox.TextLength; + _richTextBox.SelectionLength = 0; + + _richTextBox.SelectionColor = color; + _richTextBox.AppendText(line); + _richTextBox.SelectionColor = _richTextBox.ForeColor; + + _richTextBox.AppendText(Environment.NewLine); + } + + public void Information(string line = null) => WriteLine(Color.Black, line); + public void Warning(string line = null) => WriteLine(Color.DarkGoldenrod, line); + public void Error(string line = null) => WriteLine(Color.DarkRed, line); + } +} diff --git a/tools/GSDumpGUI/Forms/SettingsProvider/PortableXmlSettingsProvider.cs b/tools/GSDumpGUI/Forms/SettingsProvider/PortableXmlSettingsProvider.cs new file mode 100644 index 000000000..8927b2e87 --- /dev/null +++ b/tools/GSDumpGUI/Forms/SettingsProvider/PortableXmlSettingsProvider.cs @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2009-2019 PCSX2 Dev Team + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +using System; +using System.Collections.Specialized; +using System.Configuration; +using System.IO; +using System.Xml; +using System.Xml.Linq; + +namespace GSDumpGUI.Forms.SettingsProvider +{ + public sealed class PortableXmlSettingsProvider : System.Configuration.SettingsProvider, IApplicationSettingsProvider + { + private const string RootNode = "configuration"; + private static string SettingsDirectory => AppDomain.CurrentDomain.BaseDirectory; + public override string Name => nameof(PortableXmlSettingsProvider); + private static string ApplicationSettingsFile => Path.Combine(SettingsDirectory, "portable.config"); + + public static void ApplyProvider(params ApplicationSettingsBase[] settingsList) + => ApplyProvider(new PortableXmlSettingsProvider(), settingsList); + + public override string ApplicationName + { + get + { + return nameof(GSDumpGUI); + } + set { } + } + + private static XDocument GetOrCreateXmlDocument() + { + if (!File.Exists(ApplicationSettingsFile)) + return CreateNewDocument(); + try + { + return XDocument.Load(ApplicationSettingsFile); + } + catch + { + return CreateNewDocument(); + } + } + + private static void ApplyProvider(PortableXmlSettingsProvider provider, params ApplicationSettingsBase[] settingsList) + { + foreach (ApplicationSettingsBase settings in settingsList) + { + settings.Providers.Clear(); + settings.Providers.Add(provider); + foreach (SettingsProperty property in settings.Properties) + property.Provider = provider; + settings.Reload(); + } + } + + public override void Initialize(string name, NameValueCollection config) + { + if (String.IsNullOrEmpty(name)) + name = Name; + base.Initialize(name, config); + } + + public SettingsPropertyValue GetPreviousVersion(SettingsContext context, SettingsProperty property) + { + throw new NotImplementedException(); + } + + public void Reset(SettingsContext context) + { + if (!File.Exists(ApplicationSettingsFile)) + return; + File.Delete(ApplicationSettingsFile); + } + + public void Upgrade(SettingsContext context, SettingsPropertyCollection properties) { } + + private static XDocument CreateNewDocument() + { + return new XDocument(new XElement(RootNode)); + } + + public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection) + { + var xmlDoc = GetOrCreateXmlDocument(); + var propertyValueCollection = new SettingsPropertyValueCollection(); + foreach (SettingsProperty settingsProperty in collection) + { + propertyValueCollection.Add(new SettingsPropertyValue(settingsProperty) + { + IsDirty = false, + SerializedValue = GetValue(xmlDoc, settingsProperty) + }); + } + + return propertyValueCollection; + } + + public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection) + { + var xmlDoc = GetOrCreateXmlDocument(); + foreach (SettingsPropertyValue settingsPropertyValue in collection) + SetValue(xmlDoc, settingsPropertyValue); + try + { + using (var writer = CreateWellFormattedXmlWriter(ApplicationSettingsFile)) + { + xmlDoc.Save(writer); + } + } + catch { } + } + + private static XmlWriter CreateWellFormattedXmlWriter(string outputFileName) + { + var settings = new XmlWriterSettings + { + NewLineHandling = NewLineHandling.Entitize, + Indent = true + }; + return XmlWriter.Create(outputFileName, settings); + } + + private static object GetValue(XContainer xmlDoc, SettingsProperty prop) + { + if (xmlDoc == null) + return prop.DefaultValue; + + var rootNode = xmlDoc.Element(RootNode); + if (rootNode == null) + return prop.DefaultValue; + + var settingNode = rootNode.Element(prop.Name); + if (settingNode == null) + return prop.DefaultValue; + + return DeserializeSettingValueFromXmlNode(settingNode, prop); + } + + private static void SetValue(XContainer xmlDoc, SettingsPropertyValue value) + { + if (xmlDoc == null) + throw new ArgumentNullException(nameof(xmlDoc)); + + var rootNode = xmlDoc.Element(RootNode); + if (rootNode == null) + throw new ArgumentNullException(nameof(rootNode)); + + var settingNode = rootNode.Element(value.Name); + + var settingValueNode = SerializeSettingValueToXmlNode(value); + if (settingNode == null) + rootNode.Add(new XElement(value.Name, settingValueNode)); + else + settingNode.ReplaceAll(settingValueNode); + + } + + private static XNode SerializeSettingValueToXmlNode(SettingsPropertyValue value) + { + if (value.SerializedValue == null) + return new XText(""); + switch (value.Property.SerializeAs) + { + case SettingsSerializeAs.String: + return new XText((string) value.SerializedValue); + case SettingsSerializeAs.Xml: + case SettingsSerializeAs.Binary: + case SettingsSerializeAs.ProviderSpecific: + throw new NotImplementedException($"I don't know how to handle serialization of settings that should be serialized as {value.Property.SerializeAs}"); + default: + throw new ArgumentOutOfRangeException(); + } + } + + private static object DeserializeSettingValueFromXmlNode(XNode node, SettingsProperty prop) + { + using (var reader = node.CreateReader()) + { + reader.MoveToContent(); + switch (prop.SerializeAs) + { + case SettingsSerializeAs.Xml: + case SettingsSerializeAs.Binary: + case SettingsSerializeAs.ProviderSpecific: + throw new NotImplementedException($"I don't know how to handle deserialization of settings that should be deserialized as {prop.SerializeAs}"); + + case SettingsSerializeAs.String: + return reader.ReadElementContentAsString(); + default: + throw new ArgumentOutOfRangeException(); + } + } + } + } +} diff --git a/tools/GSDumpGUI/Forms/frmMain.Designer.cs b/tools/GSDumpGUI/Forms/frmMain.Designer.cs index b8aa8c638..c78631721 100644 --- a/tools/GSDumpGUI/Forms/frmMain.Designer.cs +++ b/tools/GSDumpGUI/Forms/frmMain.Designer.cs @@ -41,7 +41,7 @@ this.GsdxList = new System.Windows.Forms.Label(); this.cmdRun = new System.Windows.Forms.Button(); this.cmdConfigGSDX = new System.Windows.Forms.Button(); - this.txtLog = new System.Windows.Forms.TextBox(); + this.txtLog = new System.Windows.Forms.RichTextBox(); this.lblLog = new System.Windows.Forms.Label(); this.cmdOpenIni = new System.Windows.Forms.Button(); this.pctBox = new System.Windows.Forms.PictureBox(); @@ -54,7 +54,7 @@ this.lblOverride = new System.Windows.Forms.Label(); this.rdaNone = new System.Windows.Forms.RadioButton(); this.lblInternalLog = new System.Windows.Forms.Label(); - this.txtIntLog = new System.Windows.Forms.TextBox(); + this.txtIntLog = new System.Windows.Forms.RichTextBox(); this.lblDebugger = new System.Windows.Forms.Label(); this.lstProcesses = new System.Windows.Forms.ListBox(); this.lblChild = new System.Windows.Forms.Label(); @@ -161,7 +161,6 @@ this.lstDumps.Name = "lstDumps"; this.lstDumps.Size = new System.Drawing.Size(433, 173); this.lstDumps.TabIndex = 0; - this.lstDumps.SelectedIndexChanged += new System.EventHandler(this.lstDumps_SelectedIndexChanged); // // lblDumps // @@ -209,7 +208,7 @@ this.txtLog.Multiline = true; this.txtLog.Name = "txtLog"; this.txtLog.ReadOnly = true; - this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.txtLog.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Both; this.txtLog.Size = new System.Drawing.Size(430, 160); this.txtLog.TabIndex = 13; this.txtLog.TabStop = false; @@ -242,7 +241,7 @@ this.pctBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; this.pctBox.TabIndex = 16; this.pctBox.TabStop = false; - this.pctBox.Click += new System.EventHandler(this.pctBox_Click); + this.pctBox.Click += new System.EventHandler(PreviewImageClick); // // rdaDX9HW // @@ -354,7 +353,7 @@ this.txtIntLog.Multiline = true; this.txtIntLog.Name = "txtIntLog"; this.txtIntLog.ReadOnly = true; - this.txtIntLog.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.txtIntLog.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Both; this.txtIntLog.Size = new System.Drawing.Size(411, 160); this.txtIntLog.TabIndex = 24; this.txtIntLog.TabStop = false; @@ -744,7 +743,7 @@ private System.Windows.Forms.Label GsdxList; private System.Windows.Forms.Button cmdRun; private System.Windows.Forms.Button cmdConfigGSDX; - private System.Windows.Forms.TextBox txtLog; + private System.Windows.Forms.RichTextBox txtLog; private System.Windows.Forms.Label lblLog; private System.Windows.Forms.Button cmdOpenIni; private System.Windows.Forms.PictureBox pctBox; @@ -757,7 +756,7 @@ private System.Windows.Forms.Label lblOverride; private System.Windows.Forms.RadioButton rdaNone; private System.Windows.Forms.Label lblInternalLog; - private System.Windows.Forms.TextBox txtIntLog; + private System.Windows.Forms.RichTextBox txtIntLog; private System.Windows.Forms.Label lblDebugger; private System.Windows.Forms.Label lblChild; public System.Windows.Forms.ListBox lstProcesses; diff --git a/tools/GSDumpGUI/Forms/frmMain.cs b/tools/GSDumpGUI/Forms/frmMain.cs index c488c089a..51509d316 100644 --- a/tools/GSDumpGUI/Forms/frmMain.cs +++ b/tools/GSDumpGUI/Forms/frmMain.cs @@ -22,23 +22,31 @@ */ using System; +using System.Collections; using System.Collections.Generic; using System.ComponentModel; -using System.Data; using System.Drawing; -using System.Text; using System.Windows.Forms; using System.IO; -using System.Runtime.InteropServices; -using System.Threading; using System.Diagnostics; -using System.Security; +using System.Linq; +using System.Linq.Expressions; +using GSDumpGUI.Forms.Entities; +using GSDumpGUI.Forms.Helper; +using GSDumpGUI.Forms.SettingsProvider; +using GSDumpGUI.Properties; using TCPLibrary.MessageBased.Core; namespace GSDumpGUI { public partial class GSDumpGUI : Form { + private readonly ILogger _internalLogger; + private readonly ILogger _gsdxLogger; + private readonly IGsdxDllFinder _gsdxDllFinder; + private readonly IGsDumpFinder _gsDumpFinder; + private readonly IFolderWithFallBackFinder _folderWithFallBackFinder; + public List Processes; private Int32 _selected; @@ -77,86 +85,96 @@ namespace GSDumpGUI } } - private Bitmap NoImage; + private readonly Bitmap NoImage; + + private Settings Settings => Settings.Default; + + private readonly GsDumps _availableGsDumps; + private readonly GsDlls _availableGsDlls; public GSDumpGUI() { + PortableXmlSettingsProvider.ApplyProvider(Settings); + InitializeComponent(); + _internalLogger = new RichTextBoxLogger(txtIntLog); + _gsdxLogger = new RichTextBoxLogger(txtLog); + _gsdxDllFinder = new GsdxDllFinder(_internalLogger); + _gsDumpFinder = new GsDumpFinder(_internalLogger); + _folderWithFallBackFinder = new FolderWithFallBackFinder(); + _availableGsDumps = new GsDumps(); + _availableGsDlls = new GsDlls(); + + _availableGsDumps.OnIndexUpdatedEvent += UpdatePreviewImage; + + txtGSDXDirectory.DataBindings.Add(nameof(TextBox.Text), Settings, nameof(Settings.GSDXDir)); + txtDumpsDirectory.DataBindings.Add(nameof(TextBox.Text), Settings, nameof(Settings.DumpDir)); + + BindListControl(lstDumps, _availableGsDumps, g => g.Files, f => f.DisplayText, g => g.SelectedFileIndex); + BindListControl(lstGSDX, _availableGsDlls, g => g.Files, f => f.DisplayText, g => g.SelectedFileIndex); + Processes = new List(); - NoImage = new Bitmap(320, 240, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - Graphics g = Graphics.FromImage(NoImage); - g.FillRectangle(new SolidBrush(Color.Black), new Rectangle(0, 0, 320, 240)); - g.DrawString("No Image", new Font(FontFamily.GenericSansSerif, 48, FontStyle.Regular), new SolidBrush(Color.White), new PointF(0, 70)); - g.Dispose(); + NoImage = CreateDefaultImage(); } - public void ReloadGSDXs() + private static void BindListControl(ListControl lb, TModel model, Func> collectionAccessor, Expression> displayTextAccessor, Expression> selectedIndexAccessor) { - txtIntLog.Text += "Starting GSdx Loading Procedures" + Environment.NewLine + Environment.NewLine; - - txtGSDXDirectory.Text = Properties.Settings.Default.GSDXDir; - txtDumpsDirectory.Text = Properties.Settings.Default.DumpDir; - - lstGSDX.Items.Clear(); - lstDumps.Items.Clear(); - - if (Directory.Exists(txtGSDXDirectory.Text)) + lb.DataSource = new BindingSource { - String[] File = Directory.GetFiles(txtGSDXDirectory.Text, "*.dll", SearchOption.TopDirectoryOnly); + DataSource = collectionAccessor(model) + }; + lb.DisplayMember = ((MemberExpression)displayTextAccessor.Body).Member.Name; + lb.DataBindings.Add(nameof(lb.SelectedIndex), model, ((MemberExpression)selectedIndexAccessor.Body).Member.Name, false, DataSourceUpdateMode.OnPropertyChanged); + } - GSDXWrapper wrap = new GSDXWrapper(); - foreach (var itm in File) - { - try - { - wrap.Load(itm); - - lstGSDX.Items.Add(Path.GetFileName(itm) + " | " + wrap.PSEGetLibName()); - txtIntLog.Text += "\"" + itm + "\" correctly identified as " + wrap.PSEGetLibName() + Environment.NewLine; - - wrap.Unload(); - } - catch (InvalidGSPlugin) - { - txtIntLog.Text += "Failed to load \"" + itm + "\". Is it really a GSdx DLL?" + Environment.NewLine; - } - } + private static Bitmap CreateDefaultImage() + { + var defaultImage = new Bitmap(320, 240, System.Drawing.Imaging.PixelFormat.Format32bppArgb); + using (var g = Graphics.FromImage(defaultImage)) + { + g.FillRectangle(new SolidBrush(Color.Black), new Rectangle(0, 0, 320, 240)); + g.DrawString("No Image", new Font(FontFamily.GenericSansSerif, 48, FontStyle.Regular), new SolidBrush(Color.White), new PointF(0, 70)); } - txtIntLog.Text += Environment.NewLine + "Completed GSdx Loading Procedures" + Environment.NewLine + Environment.NewLine; + return defaultImage; + } - txtIntLog.Text += "Starting GSdx Dumps Loading Procedures : " + Environment.NewLine + Environment.NewLine; - if (Directory.Exists(txtDumpsDirectory.Text)) - { - String[] Dumps = Directory.GetFiles(txtDumpsDirectory.Text, "*.gs", SearchOption.TopDirectoryOnly); + private void ReloadGsdxDlls() + { + _internalLogger.Information("Starting GSdx Loading Procedures"); - foreach (var itm in Dumps) - { - BinaryReader br = new BinaryReader(System.IO.File.Open(itm, FileMode.Open)); - Int32 CRC = br.ReadInt32(); - br.Close(); - lstDumps.Items.Add(Path.GetFileName(itm) + " | CRC : " + CRC.ToString("X")); - txtIntLog.Text += "Identified Dump for game (" + CRC.ToString("X") + ") with filename \"" + itm + "\"" + Environment.NewLine; - } - } - txtIntLog.Text += Environment.NewLine + "Completed GSdx Dumps Loading Procedures : " + Environment.NewLine + Environment.NewLine; - txtIntLog.SelectionStart = txtIntLog.TextLength; - txtIntLog.ScrollToCaret(); + var gsdxFolder = _folderWithFallBackFinder.GetViaPatternWithFallback(Settings.GSDXDir, "*.dll", "", "plugins", "dll", "dlls"); + _availableGsDlls.Files.Clear(); + foreach (var file in _gsdxDllFinder.GetEnrichedPathToValidGsdxDlls(gsdxFolder)) + _availableGsDlls.Files.Add(file); + + Settings.GSDXDir = gsdxFolder.FullName; + _internalLogger.Information("Completed GSdx Loading Procedures"); + } + + private void ReloadGsdxDumps() + { + _internalLogger.Information("Starting GSdx Dump Loading Procedures..."); + + var dumpFolder = _folderWithFallBackFinder.GetViaPatternWithFallback(Settings.DumpDir, "*.gs", "", "dumps", "gsdumps"); + + _availableGsDumps.Files.Clear(); + foreach (var file in _gsDumpFinder.GetValidGsdxDumps(dumpFolder)) + _availableGsDumps.Files.Add(file); + + Settings.DumpDir = dumpFolder.FullName; + _internalLogger.Information("...Completed GSdx Dump Loading Procedures"); } private void GSDumpGUI_Load(object sender, EventArgs e) { - ReloadGSDXs(); + ReloadGsdxDlls(); + ReloadGsdxDumps(); - // Auto select GS dump - lstDumps.Focus(); - if (lstDumps.Items.Count > 0) - lstDumps.SelectedIndex = 0; - - // Auto select GSdx dll - if (lstGSDX.Items.Count > 0) - lstGSDX.SelectedIndex = 0; + // Auto select GS dump and GSdx dll + _availableGsDumps.Selected = _availableGsDumps.Files.FirstOrDefault(); + _availableGsDlls.Selected = _availableGsDlls.Files.FirstOrDefault(); } private void cmdBrowseGSDX_Click(object sender, EventArgs e) @@ -165,9 +183,9 @@ namespace GSDumpGUI fbd.Description = "Select the GSdx DLL Directory"; fbd.SelectedPath = AppDomain.CurrentDomain.BaseDirectory; if (fbd.ShowDialog() == DialogResult.OK) - txtGSDXDirectory.Text = fbd.SelectedPath; - SaveConfig(); - ReloadGSDXs(); + Settings.GSDXDir = fbd.SelectedPath; + Settings.Save(); + ReloadGsdxDlls(); } private void cmdBrowseDumps_Click(object sender, EventArgs e) @@ -176,35 +194,36 @@ namespace GSDumpGUI fbd.Description = "Select the GSdx Dumps Directory"; fbd.SelectedPath = AppDomain.CurrentDomain.BaseDirectory; if (fbd.ShowDialog() == DialogResult.OK) - txtDumpsDirectory.Text = fbd.SelectedPath; - SaveConfig(); - ReloadGSDXs(); + Settings.DumpDir = fbd.SelectedPath; + Settings.Save(); + ReloadGsdxDumps(); } private void cmdRun_Click(object sender, EventArgs e) { // Execute the GSReplay function - if (lstDumps.SelectedIndex != -1) + if (!_availableGsDumps.IsSelected) { - if (lstGSDX.SelectedIndex != -1) - ExecuteFunction("GSReplay"); - else - MessageBox.Show("Select your GSdx first", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - else MessageBox.Show("Select your Dump first", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + + if (!_availableGsDlls.IsSelected) + { + MessageBox.Show("Select your GSdx first", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + + ExecuteFunction("GSReplay"); } private void ExecuteFunction(String Function) { txtLog.Text = ""; - String GSDXName = lstGSDX.SelectedItem.ToString().Split(new char[] { '|' })[0].TrimEnd(); CreateDirs(); // Set the Arguments to pass to the child - String DLLPath = Properties.Settings.Default.GSDXDir + "\\" + GSDXName; - String DumpPath = ""; String SelectedRenderer = ""; switch (SelectedRad) { @@ -230,16 +249,21 @@ namespace GSDumpGUI SelectedRenderer = "13"; break; } + if (SelectedRenderer != "-1") { String GSdxIniPath = AppDomain.CurrentDomain.BaseDirectory + "GSDumpGSDXConfigs\\inis\\gsdx.ini"; NativeMethods.WritePrivateProfileString("Settings", "Renderer", SelectedRenderer, GSdxIniPath); } - if (lstDumps.SelectedItem != null) - DumpPath = Properties.Settings.Default.DumpDir + "\\" + - lstDumps.SelectedItem.ToString().Split(new char[] { '|' })[0]; var port = Program.Server.Port; + var dllPath = _availableGsDlls.Selected.File.FullName; + var dumpPath = _availableGsDumps.Selected.File.FullName; + + _gsdxLogger.Information("Start new gsdx instance"); + _gsdxLogger.Information($"\tdll: {dllPath}"); + _gsdxLogger.Information($"\tdump: {dumpPath}"); + // Start the child and link the events. ProcessStartInfo psi = new ProcessStartInfo(); psi.UseShellExecute = false; @@ -247,7 +271,7 @@ namespace GSDumpGUI psi.RedirectStandardError = false; psi.CreateNoWindow = true; psi.FileName = Process.GetCurrentProcess().ProcessName; - psi.Arguments = "\"" + DLLPath + "\"" + " \"" + DumpPath + "\"" + " \"" + Function + "\"" + " " + SelectedRenderer + " " + port; + psi.Arguments = "\"" + dllPath + "\"" + " \"" + dumpPath + "\"" + " \"" + Function + "\"" + " " + SelectedRenderer + " " + port; Process p = Process.Start(psi); p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived); p.BeginOutputReadLine(); @@ -273,30 +297,27 @@ namespace GSDumpGUI Directory.SetCurrentDirectory(Dir); } - void p_Exited(object sender, EventArgs e) + private void p_Exited(object sender, EventArgs e) { // Remove the child if is closed Processes.Remove((Process)sender); } - void p_OutputDataReceived(object sender, DataReceivedEventArgs e) + private void p_OutputDataReceived(object sender, DataReceivedEventArgs e) { - // Write the log. - txtLog.Invoke(new Action(delegate(object o) - { - txtLog.Text += e.Data + Environment.NewLine; - txtLog.SelectionStart = txtLog.Text.Length - 1; - txtLog.ScrollToCaret(); - }), new object[] { null }); + _gsdxLogger.Information(e.Data); } private void cmdConfigGSDX_Click(object sender, EventArgs e) { // Execute the GSconfigure function - if (lstGSDX.SelectedIndex != -1) - ExecuteFunction("GSconfigure"); - else + if (!_availableGsDlls.IsSelected) + { MessageBox.Show("Select your GSdx first", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + + ExecuteFunction("GSconfigure"); } private void cmdOpenIni_Click(object sender, EventArgs e) @@ -306,35 +327,30 @@ namespace GSDumpGUI Process.Start(AppDomain.CurrentDomain.BaseDirectory + "GSDumpGSDXConfigs\\inis\\gsdx.ini"); } - private void lstDumps_SelectedIndexChanged(object sender, EventArgs e) + private void UpdatePreviewImage(object sender, GsFiles.SelectedIndexUpdatedEventArgs args) { - if (lstDumps.SelectedIndex != -1) + if (pctBox.Image != NoImage) + pctBox.Image?.Dispose(); + if (_availableGsDumps.Selected?.PreviewFile == null) { - String [] Extensions = new String[] { ".png", ".bmp" }; - String DumpFileName = lstDumps.SelectedItem.ToString().Split(new char[] { '|' })[0]; - String Filename = Path.GetDirectoryName(Properties.Settings.Default.DumpDir + "\\") + - "\\" + Path.GetFileNameWithoutExtension(DumpFileName); - - foreach (String Extension in Extensions) - { - if (File.Exists(Filename + Extension)) - { - pctBox.Load(Filename + Extension); - pctBox.Cursor = Cursors.Hand; - return; - } - } pctBox.Image = NoImage; pctBox.Cursor = Cursors.Default; } + else + { + pctBox.Load(_availableGsDumps.Selected.PreviewFile.FullName); + pctBox.Cursor = Cursors.Hand; + } + + pctBox.Tag = _availableGsDumps.Selected?.PreviewFile?.FullName; } - private void pctBox_Click(object sender, EventArgs e) + private static void PreviewImageClick(object sender, EventArgs e) { - if (pctBox.Cursor == Cursors.Hand) - { - Process.Start(pctBox.ImageLocation); - } + var previewControl = (PictureBox)sender; + if (previewControl.Tag == null) + return; + Process.Start((string)previewControl.Tag); } private void GSDumpGUI_KeyDown(object sender, KeyEventArgs e) @@ -358,21 +374,14 @@ namespace GSDumpGUI private void txtGSDXDirectory_Leave(object sender, EventArgs e) { - SaveConfig(); - ReloadGSDXs(); + Settings.Save(); + ReloadGsdxDlls(); } private void txtDumpsDirectory_Leave(object sender, EventArgs e) { - SaveConfig(); - ReloadGSDXs(); - } - - private void SaveConfig() - { - Properties.Settings.Default.GSDXDir = txtGSDXDirectory.Text; - Properties.Settings.Default.DumpDir = txtDumpsDirectory.Text; - Properties.Settings.Default.Save(); + Settings.Save(); + ReloadGsdxDumps(); } private void lstProcesses_SelectedIndexChanged(object sender, EventArgs e) diff --git a/tools/GSDumpGUI/GSDumpGUI.csproj b/tools/GSDumpGUI/GSDumpGUI.csproj index 589c80ff8..4f296fe25 100644 --- a/tools/GSDumpGUI/GSDumpGUI.csproj +++ b/tools/GSDumpGUI/GSDumpGUI.csproj @@ -10,7 +10,7 @@ Properties GSDumpGUI GSDumpGUI - v2.0 + v4.0 512 Resources\AppIcon.ico @@ -18,6 +18,7 @@ 3.5 + true @@ -29,6 +30,8 @@ 4 x86 true + 6 + false pdbonly @@ -39,22 +42,39 @@ 4 true x86 + false + + + + + + + Form frmMain.cs + + + + + + + + + diff --git a/tools/GSDumpGUI/Library/GSDXWrapper.cs b/tools/GSDumpGUI/Library/GSDXWrapper.cs index 5e7feb78c..069a66cfc 100644 --- a/tools/GSDumpGUI/Library/GSDXWrapper.cs +++ b/tools/GSDumpGUI/Library/GSDXWrapper.cs @@ -90,77 +90,87 @@ namespace GSDumpGUI public void Load(String DLL) { - this.DLL = DLL; - NativeMethods.SetErrorMode(0x8007); - - if (Loaded) - Unload(); - - string dir = DLL; - while (true) + var formerDirectory = Directory.GetCurrentDirectory(); + try { - dir = Path.GetDirectoryName(dir); - if (dir == null) - break; - Directory.SetCurrentDirectory(dir); - IntPtr hmod = NativeMethods.LoadLibrary(DLL); - if (hmod.ToInt64() > 0) + this.DLL = DLL; + NativeMethods.SetErrorMode(0x8007); + + if (Loaded) + Unload(); + + string dir = DLL; + while (true) { - DLLAddr = hmod; - - IntPtr funcaddrLibName = NativeMethods.GetProcAddress(hmod, "PS2EgetLibName"); - IntPtr funcaddrConfig = NativeMethods.GetProcAddress(hmod, "GSconfigure"); - - IntPtr funcaddrGIF = NativeMethods.GetProcAddress(hmod, "GSgifTransfer"); - IntPtr funcaddrGIF1 = NativeMethods.GetProcAddress(hmod, "GSgifTransfer1"); - IntPtr funcaddrGIF2 = NativeMethods.GetProcAddress(hmod, "GSgifTransfer2"); - IntPtr funcaddrGIF3 = NativeMethods.GetProcAddress(hmod, "GSgifTransfer3"); - IntPtr funcaddrVSync = NativeMethods.GetProcAddress(hmod, "GSvsync"); - IntPtr funcaddrSetBaseMem = NativeMethods.GetProcAddress(hmod, "GSsetBaseMem"); - IntPtr funcaddrGSReset = NativeMethods.GetProcAddress(hmod, "GSreset"); - IntPtr funcaddrOpen = NativeMethods.GetProcAddress(hmod, "GSopen"); - IntPtr funcaddrSetCRC = NativeMethods.GetProcAddress(hmod, "GSsetGameCRC"); - IntPtr funcaddrClose = NativeMethods.GetProcAddress(hmod, "GSclose"); - IntPtr funcaddrShutdown = NativeMethods.GetProcAddress(hmod, "GSshutdown"); - IntPtr funcaddrFreeze = NativeMethods.GetProcAddress(hmod, "GSfreeze"); - IntPtr funcaddrGSreadFIFO2 = NativeMethods.GetProcAddress(hmod, "GSreadFIFO2"); - IntPtr funcaddrinit = NativeMethods.GetProcAddress(hmod, "GSinit"); - - if (!((funcaddrConfig.ToInt64() > 0) && (funcaddrLibName.ToInt64() > 0) && (funcaddrGIF.ToInt64() > 0))) - { + dir = Path.GetDirectoryName(dir); + if (dir == null) break; + Directory.SetCurrentDirectory(dir); + IntPtr hmod = NativeMethods.LoadLibrary(DLL); + if (hmod.ToInt64() > 0) + { + DLLAddr = hmod; + + IntPtr funcaddrLibName = NativeMethods.GetProcAddress(hmod, "PS2EgetLibName"); + IntPtr funcaddrConfig = NativeMethods.GetProcAddress(hmod, "GSconfigure"); + + IntPtr funcaddrGIF = NativeMethods.GetProcAddress(hmod, "GSgifTransfer"); + IntPtr funcaddrGIF1 = NativeMethods.GetProcAddress(hmod, "GSgifTransfer1"); + IntPtr funcaddrGIF2 = NativeMethods.GetProcAddress(hmod, "GSgifTransfer2"); + IntPtr funcaddrGIF3 = NativeMethods.GetProcAddress(hmod, "GSgifTransfer3"); + IntPtr funcaddrVSync = NativeMethods.GetProcAddress(hmod, "GSvsync"); + IntPtr funcaddrSetBaseMem = NativeMethods.GetProcAddress(hmod, "GSsetBaseMem"); + IntPtr funcaddrGSReset = NativeMethods.GetProcAddress(hmod, "GSreset"); + IntPtr funcaddrOpen = NativeMethods.GetProcAddress(hmod, "GSopen"); + IntPtr funcaddrSetCRC = NativeMethods.GetProcAddress(hmod, "GSsetGameCRC"); + IntPtr funcaddrClose = NativeMethods.GetProcAddress(hmod, "GSclose"); + IntPtr funcaddrShutdown = NativeMethods.GetProcAddress(hmod, "GSshutdown"); + IntPtr funcaddrFreeze = NativeMethods.GetProcAddress(hmod, "GSfreeze"); + IntPtr funcaddrGSreadFIFO2 = NativeMethods.GetProcAddress(hmod, "GSreadFIFO2"); + IntPtr funcaddrinit = NativeMethods.GetProcAddress(hmod, "GSinit"); + + if (!((funcaddrConfig.ToInt64() > 0) && (funcaddrLibName.ToInt64() > 0) && (funcaddrGIF.ToInt64() > 0))) + { + break; + } + + gsConfigure = (GSConfigure) Marshal.GetDelegateForFunctionPointer(funcaddrConfig, typeof(GSConfigure)); + PsegetLibName = (PSEgetLibName) Marshal.GetDelegateForFunctionPointer(funcaddrLibName, typeof(PSEgetLibName)); + + this.GSgifTransfer = (GSgifTransfer) Marshal.GetDelegateForFunctionPointer(funcaddrGIF, typeof(GSgifTransfer)); + this.GSgifTransfer1 = (GSgifTransfer1) Marshal.GetDelegateForFunctionPointer(funcaddrGIF1, typeof(GSgifTransfer1)); + this.GSgifTransfer2 = (GSgifTransfer2) Marshal.GetDelegateForFunctionPointer(funcaddrGIF2, typeof(GSgifTransfer2)); + this.GSgifTransfer3 = (GSgifTransfer3) Marshal.GetDelegateForFunctionPointer(funcaddrGIF3, typeof(GSgifTransfer3)); + this.GSVSync = (GSVSync) Marshal.GetDelegateForFunctionPointer(funcaddrVSync, typeof(GSVSync)); + this.GSsetBaseMem = (GSsetBaseMem) Marshal.GetDelegateForFunctionPointer(funcaddrSetBaseMem, typeof(GSsetBaseMem)); + this.GSopen = (GSopen) Marshal.GetDelegateForFunctionPointer(funcaddrOpen, typeof(GSopen)); + this.GSsetGameCRC = (GSsetGameCRC) Marshal.GetDelegateForFunctionPointer(funcaddrSetCRC, typeof(GSsetGameCRC)); + this.GSclose = (GSclose) Marshal.GetDelegateForFunctionPointer(funcaddrClose, typeof(GSclose)); + this.GSshutdown = (GSshutdown) Marshal.GetDelegateForFunctionPointer(funcaddrShutdown, typeof(GSshutdown)); + this.GSfreeze = (GSfreeze) Marshal.GetDelegateForFunctionPointer(funcaddrFreeze, typeof(GSfreeze)); + this.GSreset = (GSreset) Marshal.GetDelegateForFunctionPointer(funcaddrGSReset, typeof(GSreset)); + this.GSreadFIFO2 = (GSreadFIFO2) Marshal.GetDelegateForFunctionPointer(funcaddrGSreadFIFO2, typeof(GSreadFIFO2)); + this.GSinit = (GSinit) Marshal.GetDelegateForFunctionPointer(funcaddrinit, typeof(GSinit)); + + Loaded = true; } - - gsConfigure = (GSConfigure)Marshal.GetDelegateForFunctionPointer(funcaddrConfig, typeof(GSConfigure)); - PsegetLibName = (PSEgetLibName)Marshal.GetDelegateForFunctionPointer(funcaddrLibName, typeof(PSEgetLibName)); - - this.GSgifTransfer = (GSgifTransfer)Marshal.GetDelegateForFunctionPointer(funcaddrGIF, typeof(GSgifTransfer)); - this.GSgifTransfer1 = (GSgifTransfer1)Marshal.GetDelegateForFunctionPointer(funcaddrGIF1, typeof(GSgifTransfer1)); - this.GSgifTransfer2 = (GSgifTransfer2)Marshal.GetDelegateForFunctionPointer(funcaddrGIF2, typeof(GSgifTransfer2)); - this.GSgifTransfer3 = (GSgifTransfer3)Marshal.GetDelegateForFunctionPointer(funcaddrGIF3, typeof(GSgifTransfer3)); - this.GSVSync = (GSVSync)Marshal.GetDelegateForFunctionPointer(funcaddrVSync, typeof(GSVSync)); - this.GSsetBaseMem = (GSsetBaseMem)Marshal.GetDelegateForFunctionPointer(funcaddrSetBaseMem, typeof(GSsetBaseMem)); - this.GSopen = (GSopen)Marshal.GetDelegateForFunctionPointer(funcaddrOpen, typeof(GSopen)); - this.GSsetGameCRC = (GSsetGameCRC)Marshal.GetDelegateForFunctionPointer(funcaddrSetCRC, typeof(GSsetGameCRC)); - this.GSclose = (GSclose)Marshal.GetDelegateForFunctionPointer(funcaddrClose, typeof(GSclose)); - this.GSshutdown = (GSshutdown)Marshal.GetDelegateForFunctionPointer(funcaddrShutdown, typeof(GSshutdown)); - this.GSfreeze = (GSfreeze)Marshal.GetDelegateForFunctionPointer(funcaddrFreeze, typeof(GSfreeze)); - this.GSreset = (GSreset)Marshal.GetDelegateForFunctionPointer(funcaddrGSReset, typeof(GSreset)); - this.GSreadFIFO2 = (GSreadFIFO2)Marshal.GetDelegateForFunctionPointer(funcaddrGSreadFIFO2, typeof(GSreadFIFO2)); - this.GSinit = (GSinit)Marshal.GetDelegateForFunctionPointer(funcaddrinit, typeof(GSinit)); - - Loaded = true; } - } - if (!Loaded) - { - Exception lasterror = Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()); - System.IO.File.AppendAllText(AppDomain.CurrentDomain.BaseDirectory + "log.txt", DLL + " failed to load. Error " + lasterror.ToString() + Environment.NewLine); + + if (!Loaded) + { + Exception lasterror = Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()); + System.IO.File.AppendAllText(AppDomain.CurrentDomain.BaseDirectory + "log.txt", DLL + " failed to load. Error " + lasterror.ToString() + Environment.NewLine); + NativeMethods.SetErrorMode(0x0000); + Unload(); + throw new InvalidGSPlugin(lasterror.ToString()); + } + NativeMethods.SetErrorMode(0x0000); - Unload(); - throw new InvalidGSPlugin(lasterror.ToString()); } - NativeMethods.SetErrorMode(0x0000); + finally + { + Directory.SetCurrentDirectory(formerDirectory); + } } public void Unload() diff --git a/tools/GSDumpGUI/Properties/Resources.Designer.cs b/tools/GSDumpGUI/Properties/Resources.Designer.cs index 56d87f578..d05c3a159 100644 --- a/tools/GSDumpGUI/Properties/Resources.Designer.cs +++ b/tools/GSDumpGUI/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.1 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -19,7 +19,7 @@ namespace GSDumpGUI.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -60,6 +60,9 @@ namespace GSDumpGUI.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// internal static System.Drawing.Icon AppIcon { get { object obj = ResourceManager.GetObject("AppIcon", resourceCulture); diff --git a/tools/GSDumpGUI/Properties/Settings.Designer.cs b/tools/GSDumpGUI/Properties/Settings.Designer.cs index 09286356d..e6a0a1daf 100644 --- a/tools/GSDumpGUI/Properties/Settings.Designer.cs +++ b/tools/GSDumpGUI/Properties/Settings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.1 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -12,7 +12,7 @@ namespace GSDumpGUI.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/tools/GSDumpGUI/app.config b/tools/GSDumpGUI/app.config index fade5e19a..ad8663627 100644 --- a/tools/GSDumpGUI/app.config +++ b/tools/GSDumpGUI/app.config @@ -15,4 +15,4 @@ - +