[skip ci] GSDumpGui: Only reload dumps and dlls separately if their respective settings change, make config portable, autodetect dump/dll folder. (#2926)

- Add simple logging infrastructure and further improve the existing one
- Delegate loading of dlls and dumps into dedicated loader classes
- Adjust user interaction to restrict updates to only relevant parts
- Gsdx dlls (dumps) are only reloaded when a new path for gsdx dlls (dumps) was given. That means dlls are not reloaded just because the dumps path was changed or another dump was selected
- When GSDumpGui can not find the specified settings folder or there is no setting saved so far it will look into the directory of the currently running application (however as before only exactly in the directory and not in subdirectories)
- Further decouple model, view and 'controller' logic.
- Restrict directory checks to application basepath instead of current directory as current directly is changed at too man places
- Avoid some minor memory leaks by disposing some disposable elements

Note: Net framework requirement has been increased to 4.0 to run/compile the application.
This commit is contained in:
willkuer 2019-04-15 17:24:25 +02:00 committed by lightningterror
parent 773be7bb95
commit 1414d64b18
21 changed files with 1067 additions and 207 deletions

View File

@ -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<GsFile> { }
}

View File

@ -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; }
}
}

View File

@ -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<GsDumpFile>
{
private FileInfo GsDumpPreviewFile { get; set; }
}
}

View File

@ -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; }
}
}

View File

@ -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<TUnderlying>
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<TUnderlying> Files { get; } = new BindingList<TUnderlying>();
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);
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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<GsDumpFile> 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
};
}
}
}
}

View File

@ -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<GsFile> 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;
}
}
}
}

View File

@ -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);
}
}

View File

@ -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<GsDumpFile> GetValidGsdxDumps(DirectoryInfo directory);
}
}

View File

@ -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<GsFile> GetEnrichedPathToValidGsdxDlls(DirectoryInfo directory);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}
}
}
}

View File

@ -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;

View File

@ -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<Process> 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<Process>();
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<TModel, TElement>(ListControl lb, TModel model, Func<TModel, BindingList<TElement>> collectionAccessor, Expression<Func<TElement, string>> displayTextAccessor, Expression<Func<TModel, int>> 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<object>(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<GsDumpFile>.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)

View File

@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>GSDumpGUI</RootNamespace>
<AssemblyName>GSDumpGUI</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ApplicationIcon>Resources\AppIcon.ico</ApplicationIcon>
<FileUpgradeFlags>
@ -18,6 +18,7 @@
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -29,6 +30,8 @@
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>6</LangVersion>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -39,22 +42,39 @@
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>x86</PlatformTarget>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Compile Include="Forms\Entities\GsDlls.cs" />
<Compile Include="Forms\Entities\GsDumpFile.cs" />
<Compile Include="Forms\Entities\GsDumps.cs" />
<Compile Include="Forms\Entities\GsFile.cs" />
<Compile Include="Forms\Entities\GsFiles.cs" />
<Compile Include="Forms\frmMain.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\frmMain.Designer.cs">
<DependentUpon>frmMain.cs</DependentUpon>
</Compile>
<Compile Include="Forms\Helper\FolderWithFallBackFinder.cs" />
<Compile Include="Forms\Helper\GsDumpFinder.cs" />
<Compile Include="Forms\Helper\GsdxDllFinder.cs" />
<Compile Include="Forms\Helper\IFolderWithFallBackFinder.cs" />
<Compile Include="Forms\Helper\IGsDumpFinder.cs" />
<Compile Include="Forms\Helper\IGsdxDllFinder.cs" />
<Compile Include="Forms\Helper\ILogger.cs" />
<Compile Include="Forms\Helper\RichTextBoxLogger.cs" />
<Compile Include="Forms\SettingsProvider\PortableXmlSettingsProvider.cs" />
<Compile Include="Library\GSDump\GSData\GIFPacket\GIFPrim.cs" />
<Compile Include="Library\GSDump\GSData\GIFPacket\GIFReg\GIFRegNOP.cs" />
<Compile Include="Library\GSDump\GSData\GIFPacket\GIFReg\GIFRegUnimpl.cs" />

View File

@ -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()

View File

@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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 {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary>
internal static System.Drawing.Icon AppIcon {
get {
object obj = ResourceManager.GetObject("AppIcon", resourceCulture);

View File

@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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())));

View File

@ -15,4 +15,4 @@
</setting>
</GSDumpGUI.Properties.Settings>
</userSettings>
<startup/></configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>