diff --git a/BizHawk.Client.Common/PathManager.cs b/BizHawk.Client.Common/PathManager.cs
index 932ec07f8d..32c707939b 100644
--- a/BizHawk.Client.Common/PathManager.cs
+++ b/BizHawk.Client.Common/PathManager.cs
@@ -1,11 +1,6 @@
-using System;
-using System.Linq;
-using System.IO;
+using System.IO;
using System.Reflection;
-using BizHawk.Common;
-using BizHawk.Emulation.Common;
-
namespace BizHawk.Client.Common
{
public static class PathManager
@@ -53,93 +48,5 @@ namespace BizHawk.Client.Common
{
DefaultIniPath = newDefaultIniPath;
}
-
- // Decides if a path is non-empty, not . and not .\
- public static bool PathIsSet(string path)
- {
- if (!string.IsNullOrWhiteSpace(path))
- {
- return path != "." && path != ".\\";
- }
-
- return false;
- }
-
- public static string RemoveInvalidFileSystemChars(string name)
- {
- var newStr = name;
- var chars = Path.GetInvalidFileNameChars();
- return chars.Aggregate(newStr, (current, c) => current.Replace(c.ToString(), ""));
- }
-
- public static string FilesystemSafeName(GameInfo game)
- {
- var filesystemSafeName = game.Name
- .Replace("|", "+")
- .Replace(":", " -") // Path.GetFileName scraps everything to the left of a colon unfortunately, so we need this hack here
- .Replace("\"", "") // Ivan IronMan Stewart's Super Off-Road has quotes in game name
- .Replace("/", "+"); // Mario Bros / Duck hunt has a slash in the name which GetDirectoryName and GetFileName treat as if it were a folder
-
- // zero 06-nov-2015 - regarding the below, i changed my mind. for libretro i want subdirectories here.
- var filesystemDir = Path.GetDirectoryName(filesystemSafeName);
- filesystemSafeName = Path.GetFileName(filesystemSafeName);
-
- filesystemSafeName = RemoveInvalidFileSystemChars(filesystemSafeName);
-
- // zero 22-jul-2012 - i don't think this is used the same way it used to. game.Name shouldn't be a path, so this stuff is illogical.
- // if game.Name is a path, then someone should have made it not-a-path already.
- // return Path.Combine(Path.GetDirectoryName(filesystemSafeName), Path.GetFileNameWithoutExtension(filesystemSafeName));
-
- // adelikat:
- // This hack is to prevent annoying things like Super Mario Bros..bk2
- if (filesystemSafeName.EndsWith("."))
- {
- filesystemSafeName = filesystemSafeName.Remove(filesystemSafeName.Length - 1, 1);
- }
-
- return Path.Combine(filesystemDir, filesystemSafeName);
- }
-
- public static string MakeRelativeTo(string absolutePath, string basePath)
- {
- if (IsSubfolder(basePath, absolutePath))
- {
- return absolutePath.Replace(basePath, ".");
- }
-
- return absolutePath;
- }
-
- /// Algorithm for Windows taken from https://stackoverflow.com/a/7710620/7467292
- public static bool IsSubfolder(string parentPath, string childPath)
- {
- if (OSTailoredCode.IsUnixHost)
- {
-#if true
- return OSTailoredCode.SimpleSubshell("realpath", $"-L \"{childPath}\"", $"invalid path {childPath} or missing realpath binary")
- .StartsWith(OSTailoredCode.SimpleSubshell("realpath", $"-L \"{parentPath}\"", $"invalid path {parentPath} or missing realpath binary"));
-#else // written for Unix port but may be useful for Windows when moving to .NET Core
- var parentUriPath = new Uri(parentPath.TrimEnd('.')).AbsolutePath.TrimEnd('/');
- try
- {
- for (var childUri = new DirectoryInfo(childPath).Parent; childUri != null; childUri = childUri?.Parent)
- {
- if (new Uri(childUri.FullName).AbsolutePath.TrimEnd('/') == parentUriPath) return true;
- }
- }
- catch
- {
- // ignored
- }
- return false;
-#endif
- }
- var parentUri = new Uri(parentPath);
- for (var childUri = new DirectoryInfo(childPath).Parent; childUri != null; childUri = childUri?.Parent)
- {
- if (new Uri(childUri.FullName) == parentUri) return true;
- }
- return false;
- }
}
}
diff --git a/BizHawk.Client.Common/config/PathEntryCollection.cs b/BizHawk.Client.Common/config/PathEntryCollection.cs
index db77c805f5..dec8227ac2 100644
--- a/BizHawk.Client.Common/config/PathEntryCollection.cs
+++ b/BizHawk.Client.Common/config/PathEntryCollection.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using BizHawk.Common.PathExtensions;
using Newtonsoft.Json;
namespace BizHawk.Client.Common
@@ -47,7 +48,7 @@ namespace BizHawk.Client.Common
}
// we don't have anything for the system in question. add a set of stock paths
- var systemPath = $"{PathManager.RemoveInvalidFileSystemChars(system)}_INTERIM";
+ var systemPath = $"{system.RemoveInvalidFileSystemChars()}_INTERIM";
var systemDisp = $"{system} (INTERIM)";
Paths.AddRange(new[]
diff --git a/BizHawk.Client.Common/config/PathEntryCollectionExtensions.cs b/BizHawk.Client.Common/config/PathEntryCollectionExtensions.cs
index 4d79d08e75..c4e674be34 100644
--- a/BizHawk.Client.Common/config/PathEntryCollectionExtensions.cs
+++ b/BizHawk.Client.Common/config/PathEntryCollectionExtensions.cs
@@ -1,6 +1,7 @@
using System;
using System.IO;
using BizHawk.Common;
+using BizHawk.Common.PathExtensions;
using BizHawk.Emulation.Common;
namespace BizHawk.Client.Common
@@ -208,11 +209,11 @@ namespace BizHawk.Client.Common
var path = collection[systemId, "ROM"];
- if (path == null || !PathManager.PathIsSet(path.Path))
+ if (!path.Path.PathIsSet())
{
path = collection["Global", "ROM"];
- if (path != null && PathManager.PathIsSet(path.Path))
+ if (path.Path.PathIsSet())
{
return collection.AbsolutePathFor(path.Path, null);
}
@@ -223,7 +224,7 @@ namespace BizHawk.Client.Common
public static string SaveRamAbsolutePath(this PathEntryCollection collection, GameInfo game, bool movieIsActive)
{
- var name = PathManager.FilesystemSafeName(game);
+ var name = game.Name.FilesystemSafeName();
if (movieIsActive)
{
name += $".{Path.GetFileNameWithoutExtension(Global.MovieSession.Movie.Filename)}";
@@ -238,11 +239,11 @@ namespace BizHawk.Client.Common
// Shenanigans
public static string RetroSaveRamAbsolutePath(this PathEntryCollection collection, GameInfo game, bool movieIsActive, string movieFilename)
{
- var name = PathManager.FilesystemSafeName(game);
+ var name = game.Name.FilesystemSafeName();
name = Path.GetDirectoryName(name);
if (name == "")
{
- name = PathManager.FilesystemSafeName(game);
+ name = game.Name.FilesystemSafeName();
}
if (movieIsActive)
@@ -259,11 +260,11 @@ namespace BizHawk.Client.Common
// Shenanigans
public static string RetroSystemAbsolutePath(this PathEntryCollection collection, GameInfo game)
{
- var name = PathManager.FilesystemSafeName(game);
+ var name = game.Name.FilesystemSafeName();
name = Path.GetDirectoryName(name);
if (string.IsNullOrEmpty(name))
{
- name = PathManager.FilesystemSafeName(game);
+ name = game.Name.FilesystemSafeName();
}
var pathEntry = collection[game.System, "System"]
@@ -317,7 +318,10 @@ namespace BizHawk.Client.Common
? collection.GlobalBaseAbsolutePath()
: collection.AbsolutePathFor(collection.BaseFor(system), system);
#if true
- if (!PathManager.IsSubfolder(parentPath, absolutePath)) return absolutePath;
+ if (!absolutePath.IsSubfolderOf(parentPath))
+ {
+ return absolutePath;
+ }
return OSTailoredCode.IsUnixHost
? "./" + OSTailoredCode.SimpleSubshell("realpath", $"--relative-to=\"{parentPath}\" \"{absolutePath}\"", $"invalid path {absolutePath} or missing realpath binary")
diff --git a/BizHawk.Client.Common/lua/LuaFileList.cs b/BizHawk.Client.Common/lua/LuaFileList.cs
index 8bd16ac3b0..c907901320 100644
--- a/BizHawk.Client.Common/lua/LuaFileList.cs
+++ b/BizHawk.Client.Common/lua/LuaFileList.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
+using BizHawk.Common.PathExtensions;
namespace BizHawk.Client.Common
{
@@ -138,8 +139,7 @@ namespace BizHawk.Client.Common
sb
.Append(file.Enabled ? "1" : "0")
.Append(' ')
- .Append(PathManager.MakeRelativeTo(Global.Config.PathEntries.AbsolutePathFor(file.Path, ""),
- Path.GetDirectoryName(path)))
+ .Append(Global.Config.PathEntries.AbsolutePathFor(file.Path, "").MakeRelativeTo(Path.GetDirectoryName(path)))
.AppendLine();
}
}
diff --git a/BizHawk.Client.Common/movie/conversions/MovieConversionExtensions.cs b/BizHawk.Client.Common/movie/conversions/MovieConversionExtensions.cs
index 850a53b75b..fd34d851f7 100644
--- a/BizHawk.Client.Common/movie/conversions/MovieConversionExtensions.cs
+++ b/BizHawk.Client.Common/movie/conversions/MovieConversionExtensions.cs
@@ -2,6 +2,7 @@
using System.IO;
using System.Linq;
+using BizHawk.Common.PathExtensions;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Nintendo.Gameboy;
using BizHawk.Emulation.Cores.Nintendo.GBHawk;
@@ -292,7 +293,7 @@ namespace BizHawk.Client.Common.MovieConversionExtensions
if (Global.Game != null)
{
- movie.GameName = PathManager.FilesystemSafeName(Global.Game);
+ movie.GameName = Global.Game.Name.FilesystemSafeName();
movie.Hash = Global.Game.Hash;
if (Global.Game.FirmwareHash != null)
{
diff --git a/BizHawk.Client.EmuHawk/AVOut/SynclessRecordingTools.cs b/BizHawk.Client.EmuHawk/AVOut/SynclessRecordingTools.cs
index 74cc3bd490..3393b16ec1 100644
--- a/BizHawk.Client.EmuHawk/AVOut/SynclessRecordingTools.cs
+++ b/BizHawk.Client.EmuHawk/AVOut/SynclessRecordingTools.cs
@@ -6,6 +6,7 @@ using System.Windows.Forms;
using BizHawk.Bizware.BizwareGL;
using BizHawk.Client.Common;
+using BizHawk.Common.PathExtensions;
namespace BizHawk.Client.EmuHawk
{
@@ -32,7 +33,7 @@ namespace BizHawk.Client.EmuHawk
{
var ofd = new OpenFileDialog
{
- FileName = $"{PathManager.FilesystemSafeName(Global.Game)}.syncless.txt",
+ FileName = $"{Global.Game.Name.FilesystemSafeName()}.syncless.txt",
InitialDirectory = Global.Config.PathEntries.AvAbsolutePath()
};
diff --git a/BizHawk.Client.EmuHawk/MainForm.Events.cs b/BizHawk.Client.EmuHawk/MainForm.Events.cs
index 0bd03f2970..3bc2824e64 100644
--- a/BizHawk.Client.EmuHawk/MainForm.Events.cs
+++ b/BizHawk.Client.EmuHawk/MainForm.Events.cs
@@ -19,6 +19,7 @@ using BizHawk.Client.EmuHawk.ToolExtensions;
using BizHawk.Emulation.Cores.Computers.AppleII;
using BizHawk.Client.ApiHawk;
using BizHawk.Common;
+using BizHawk.Common.PathExtensions;
using BizHawk.Emulation.Cores.Atari.A7800Hawk;
using BizHawk.Emulation.Cores.Computers.Commodore64;
using BizHawk.Emulation.Cores.Nintendo.Gameboy;
@@ -535,7 +536,7 @@ namespace BizHawk.Client.EmuHawk
var filename = MovieSession.Movie.Filename;
if (string.IsNullOrWhiteSpace(filename))
{
- filename = PathManager.FilesystemSafeName(Game);
+ filename = Game.Name.FilesystemSafeName();
}
var file = ToolFormBase.SaveFileDialog(
diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs
index 9c47a64ec1..d72ba21497 100644
--- a/BizHawk.Client.EmuHawk/MainForm.cs
+++ b/BizHawk.Client.EmuHawk/MainForm.cs
@@ -27,6 +27,7 @@ using BizHawk.Emulation.Cores.Nintendo.GBHawkLink;
using BizHawk.Client.EmuHawk.ToolExtensions;
using BizHawk.Client.EmuHawk.CoreExtensions;
using BizHawk.Client.ApiHawk;
+using BizHawk.Common.PathExtensions;
using BizHawk.Emulation.Common.Base_Implementations;
using BizHawk.Emulation.Cores.Nintendo.SNES9X;
using BizHawk.Emulation.Cores.Consoles.SNK;
@@ -1045,7 +1046,7 @@ namespace BizHawk.Client.EmuHawk
private string ScreenshotPrefix()
{
var screenPath = Config.PathEntries.ScreenshotAbsolutePathFor(Game.System);
- var name = PathManager.FilesystemSafeName(Game);
+ var name = Game.Name.FilesystemSafeName();
return Path.Combine(screenPath, name);
}
@@ -3241,7 +3242,7 @@ namespace BizHawk.Client.EmuHawk
using var sfd = new SaveFileDialog();
if (Game != null)
{
- sfd.FileName = $"{PathManager.FilesystemSafeName(Game)}.{ext}"; // don't use Path.ChangeExtension, it might wreck game names with dots in them
+ sfd.FileName = $"{Game.Name.FilesystemSafeName()}.{ext}"; // don't use Path.ChangeExtension, it might wreck game names with dots in them
sfd.InitialDirectory = Config.PathEntries.AvAbsolutePath();
}
else
@@ -3467,7 +3468,7 @@ namespace BizHawk.Client.EmuHawk
public string SaveStatePrefix()
{
- var name = PathManager.FilesystemSafeName(Game);
+ var name = Game.Name.FilesystemSafeName();
// Neshawk and Quicknes have incompatible savestates, store the name to keep them separate
if (Emulator.SystemId == "NES")
diff --git a/BizHawk.Client.EmuHawk/config/GB/BmpView.cs b/BizHawk.Client.EmuHawk/config/GB/BmpView.cs
index 331bd2c575..9a550b5f5f 100644
--- a/BizHawk.Client.EmuHawk/config/GB/BmpView.cs
+++ b/BizHawk.Client.EmuHawk/config/GB/BmpView.cs
@@ -8,6 +8,7 @@ using System.Windows.Forms;
using BizHawk.Client.Common;
using BizHawk.Common;
+using BizHawk.Common.PathExtensions;
namespace BizHawk.Client.EmuHawk
{
@@ -102,7 +103,7 @@ namespace BizHawk.Client.EmuHawk
using var sfd = new SaveFileDialog
{
- FileName = $"{PathManager.FilesystemSafeName(Global.Game)}-Palettes",
+ FileName = $"{Global.Game.Name.FilesystemSafeName()}-Palettes",
InitialDirectory = path,
Filter = FilesystemFilterSet.Screenshots.ToString(),
RestoreDirectory = true
diff --git a/BizHawk.Client.EmuHawk/movie/PlayMovie.cs b/BizHawk.Client.EmuHawk/movie/PlayMovie.cs
index 69469a8b40..7c8a307666 100644
--- a/BizHawk.Client.EmuHawk/movie/PlayMovie.cs
+++ b/BizHawk.Client.EmuHawk/movie/PlayMovie.cs
@@ -9,6 +9,7 @@ using System.Windows.Forms;
using BizHawk.Client.Common;
using BizHawk.Common;
+using BizHawk.Common.PathExtensions;
using BizHawk.Emulation.Common;
namespace BizHawk.Client.EmuHawk
@@ -167,7 +168,7 @@ namespace BizHawk.Client.EmuHawk
// Pull out matching names
for (var i = 0; i < _movieList.Count; i++)
{
- if (PathManager.FilesystemSafeName(_game) == _movieList[i].GameName)
+ if (_game.Name.FilesystemSafeName() == _movieList[i].GameName)
{
indices.Add(i);
}
diff --git a/BizHawk.Client.EmuHawk/movie/RecordMovie.cs b/BizHawk.Client.EmuHawk/movie/RecordMovie.cs
index 228773eb5d..aeb880e92b 100644
--- a/BizHawk.Client.EmuHawk/movie/RecordMovie.cs
+++ b/BizHawk.Client.EmuHawk/movie/RecordMovie.cs
@@ -6,6 +6,7 @@ using System.Linq;
using BizHawk.Emulation.Common;
using BizHawk.Client.Common;
using BizHawk.Client.Common.MovieConversionExtensions;
+using BizHawk.Common.PathExtensions;
namespace BizHawk.Client.EmuHawk
{
@@ -197,7 +198,7 @@ namespace BizHawk.Client.EmuHawk
private void RecordMovie_Load(object sender, EventArgs e)
{
- RecordBox.Text = PathManager.FilesystemSafeName(_game);
+ RecordBox.Text = _game.Name.FilesystemSafeName();
StartFromCombo.SelectedIndex = 0;
DefaultAuthorCheckBox.Checked = _config.UseDefaultAuthor;
if (_config.UseDefaultAuthor)
diff --git a/BizHawk.Client.EmuHawk/tools/CDL.cs b/BizHawk.Client.EmuHawk/tools/CDL.cs
index 4343e9c8bf..a532d9cfeb 100644
--- a/BizHawk.Client.EmuHawk/tools/CDL.cs
+++ b/BizHawk.Client.EmuHawk/tools/CDL.cs
@@ -6,6 +6,7 @@ using BizHawk.Emulation.Common;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk.ToolExtensions;
+using BizHawk.Common.PathExtensions;
// TODO - select which memorydomains go out to the CDL file. will this cause a problem when re-importing it?
// perhaps missing domains shouldn't fail a check
@@ -493,7 +494,7 @@ namespace BizHawk.Client.EmuHawk
try
{
_autoloading = true;
- var autoResumeFile = $"{PathManager.FilesystemSafeName(Global.Game)}.cdl";
+ var autoResumeFile = $"{Global.Game.Name.FilesystemSafeName()}.cdl";
var autoResumeDir = Config.PathEntries.LogAbsolutePath();
var autoResumePath = Path.Combine(autoResumeDir, autoResumeFile);
if (File.Exists(autoResumePath))
diff --git a/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs b/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs
index a019c46159..b337c2e3fd 100644
--- a/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs
+++ b/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs
@@ -12,6 +12,7 @@ using BizHawk.Common;
using BizHawk.Common.NumberExtensions;
using BizHawk.Common.StringExtensions;
using BizHawk.Common.IOExtensions;
+using BizHawk.Common.PathExtensions;
using BizHawk.Emulation.Common;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk.ToolExtensions;
@@ -969,7 +970,7 @@ namespace BizHawk.Client.EmuHawk
, FileName =
_domain.Name == "File on Disk"
? RomName
- : PathManager.FilesystemSafeName(Global.Game)
+ : Global.Game.Name.FilesystemSafeName()
};
var result = sfd.ShowHawkDialog();
@@ -982,7 +983,7 @@ namespace BizHawk.Client.EmuHawk
{
FileName = _domain.Name == "File on Disk"
? $"{Path.GetFileNameWithoutExtension(RomName)}.txt"
- : PathManager.FilesystemSafeName(Global.Game),
+ : Global.Game.Name.FilesystemSafeName(),
Filter = new FilesystemFilterSet(FilesystemFilter.TextFiles).ToString(),
InitialDirectory = RomDirectory,
RestoreDirectory = true
diff --git a/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs b/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs
index edd6eb2943..acb223c3d1 100644
--- a/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs
+++ b/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs
@@ -11,6 +11,7 @@ using System.Windows.Forms;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk.ToolExtensions;
using BizHawk.Common;
+using BizHawk.Common.PathExtensions;
using BizHawk.Emulation.Common;
namespace BizHawk.Client.EmuHawk
@@ -569,7 +570,7 @@ namespace BizHawk.Client.EmuHawk
}
else if (Global.Game != null)
{
- sfd.FileName = PathManager.FilesystemSafeName(Global.Game);
+ sfd.FileName = Global.Game.Name.FilesystemSafeName();
sfd.InitialDirectory = Config.PathEntries.LuaAbsolutePath();
}
else
diff --git a/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs b/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs
index 05e54f60b5..5cb0943948 100644
--- a/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs
+++ b/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs
@@ -6,6 +6,7 @@ using System.IO;
using BizHawk.Emulation.Common;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk.ToolExtensions;
+using BizHawk.Common.PathExtensions;
namespace BizHawk.Client.EmuHawk
{
@@ -279,7 +280,7 @@ namespace BizHawk.Client.EmuHawk
{
return Config.PathEntries.AbsolutePathFor(Path.Combine(
Config.PathEntries["Global", "Macros"].Path,
- PathManager.FilesystemSafeName(Global.Game)), null);
+ Global.Game.Name.FilesystemSafeName()), null);
}
#endregion
diff --git a/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs b/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs
index 7c0fb69e0e..262584d18b 100644
--- a/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs
+++ b/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs
@@ -10,6 +10,7 @@ using System.Xml.Linq;
using BizHawk.Emulation.Common;
using BizHawk.Client.Common;
using BizHawk.Common;
+using BizHawk.Common.PathExtensions;
using BizHawk.Emulation.Cores.Sega.MasterSystem;
namespace BizHawk.Client.EmuHawk
@@ -239,7 +240,7 @@ namespace BizHawk.Client.EmuHawk
filename = NameBox.Text;
if (string.IsNullOrWhiteSpace(filename))
{
- filename = Path.ChangeExtension(PathManager.FilesystemSafeName(Global.Game), ".xml");
+ filename = Path.ChangeExtension(Global.Game.Name.FilesystemSafeName(), ".xml");
}
initialDirectory = Path.GetDirectoryName(filename);
@@ -267,7 +268,7 @@ namespace BizHawk.Client.EmuHawk
if (OSTailoredCode.IsUnixHost)
{
#if true
- return PathManager.IsSubfolder(toPath, fromPath)
+ return fromPath.IsSubfolderOf(toPath)
? "./" + OSTailoredCode.SimpleSubshell("realpath", $"--relative-to=\"{toPath}\" \"{fromPath}\"", $"invalid path {fromPath} or missing realpath binary")
: fromPath;
#else // written for Unix port but may be useful for .NET Core
diff --git a/BizHawk.Client.EmuHawk/tools/NES/NameTableViewer.cs b/BizHawk.Client.EmuHawk/tools/NES/NameTableViewer.cs
index 3b25288014..2d59b56d2a 100644
--- a/BizHawk.Client.EmuHawk/tools/NES/NameTableViewer.cs
+++ b/BizHawk.Client.EmuHawk/tools/NES/NameTableViewer.cs
@@ -4,6 +4,7 @@ using System.IO;
using System.Drawing.Imaging;
using BizHawk.Client.Common;
+using BizHawk.Common.PathExtensions;
namespace BizHawk.Client.EmuHawk
{
@@ -68,7 +69,7 @@ namespace BizHawk.Client.EmuHawk
{
using var sfd = new SaveFileDialog
{
- FileName = $"{PathManager.FilesystemSafeName(Global.Game)}-Nametables",
+ FileName = $"{Global.Game.Name.FilesystemSafeName()}-Nametables",
InitialDirectory = Global.Config.PathEntries.ScreenshotAbsolutePathFor("NES"),
Filter = FilesystemFilterSet.Screenshots.ToString(),
RestoreDirectory = true
diff --git a/BizHawk.Client.EmuHawk/tools/NES/PaletteViewer.cs b/BizHawk.Client.EmuHawk/tools/NES/PaletteViewer.cs
index 43a45ba89a..dbc34c080e 100644
--- a/BizHawk.Client.EmuHawk/tools/NES/PaletteViewer.cs
+++ b/BizHawk.Client.EmuHawk/tools/NES/PaletteViewer.cs
@@ -4,6 +4,7 @@ using System.IO;
using System.Drawing.Imaging;
using BizHawk.Client.Common;
+using BizHawk.Common.PathExtensions;
namespace BizHawk.Client.EmuHawk
{
@@ -74,7 +75,7 @@ namespace BizHawk.Client.EmuHawk
{
var sfd = new SaveFileDialog
{
- FileName = $"{PathManager.FilesystemSafeName(Global.Game)}-Palettes",
+ FileName = $"{Global.Game.Name.FilesystemSafeName()}-Palettes",
InitialDirectory = Global.Config.PathEntries.ScreenshotAbsolutePathFor("NES"),
Filter = FilesystemFilterSet.Screenshots.ToString(),
RestoreDirectory = true
diff --git a/BizHawk.Client.EmuHawk/tools/NES/PatternViewer.cs b/BizHawk.Client.EmuHawk/tools/NES/PatternViewer.cs
index 383667a460..badafbb3a2 100644
--- a/BizHawk.Client.EmuHawk/tools/NES/PatternViewer.cs
+++ b/BizHawk.Client.EmuHawk/tools/NES/PatternViewer.cs
@@ -4,6 +4,7 @@ using System.IO;
using System.Drawing.Imaging;
using BizHawk.Client.Common;
+using BizHawk.Common.PathExtensions;
namespace BizHawk.Client.EmuHawk
{
@@ -36,7 +37,7 @@ namespace BizHawk.Client.EmuHawk
{
var sfd = new SaveFileDialog
{
- FileName = $"{PathManager.FilesystemSafeName(Global.Game)}-Patterns",
+ FileName = $"{Global.Game.Name.FilesystemSafeName()}-Patterns",
InitialDirectory = Global.Config.PathEntries.ScreenshotAbsolutePathFor("NES"),
Filter = FilesystemFilterSet.Screenshots.ToString(),
RestoreDirectory = true
diff --git a/BizHawk.Client.EmuHawk/tools/NES/SpriteViewer.cs b/BizHawk.Client.EmuHawk/tools/NES/SpriteViewer.cs
index 5ff4f746d4..1f55225be3 100644
--- a/BizHawk.Client.EmuHawk/tools/NES/SpriteViewer.cs
+++ b/BizHawk.Client.EmuHawk/tools/NES/SpriteViewer.cs
@@ -4,6 +4,7 @@ using System.IO;
using System.Drawing.Imaging;
using BizHawk.Client.Common;
+using BizHawk.Common.PathExtensions;
namespace BizHawk.Client.EmuHawk
{
@@ -38,7 +39,7 @@ namespace BizHawk.Client.EmuHawk
{
var sfd = new SaveFileDialog
{
- FileName = $"{PathManager.FilesystemSafeName(Global.Game)}-Sprites",
+ FileName = $"{Global.Game.Name.FilesystemSafeName()}-Sprites",
InitialDirectory = Global.Config.PathEntries.ScreenshotAbsolutePathFor("NES"),
Filter = FilesystemFilterSet.Screenshots.ToString(),
RestoreDirectory = true
diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs
index a03aa0f3be..6ada6b56f4 100644
--- a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs
+++ b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs
@@ -11,6 +11,7 @@ using BizHawk.Emulation.Common;
using BizHawk.Client.Common;
using BizHawk.Client.Common.MovieConversionExtensions;
using BizHawk.Client.EmuHawk.ToolExtensions;
+using BizHawk.Common.PathExtensions;
using BizHawk.Emulation.Cores.Nintendo.N64;
namespace BizHawk.Client.EmuHawk
@@ -866,7 +867,7 @@ namespace BizHawk.Client.EmuHawk
{
return Path.Combine(
Global.Config.PathEntries.MovieAbsolutePath(),
- $"{PathManager.FilesystemSafeName(Global.Game)}.{TasMovie.Extension}");
+ $"{Global.Game.Name.FilesystemSafeName()}.{TasMovie.Extension}");
}
private void SaveTas()
diff --git a/BizHawk.Client.EmuHawk/tools/ToolFormBase.cs b/BizHawk.Client.EmuHawk/tools/ToolFormBase.cs
index d61528bd89..459c61bf8b 100644
--- a/BizHawk.Client.EmuHawk/tools/ToolFormBase.cs
+++ b/BizHawk.Client.EmuHawk/tools/ToolFormBase.cs
@@ -1,11 +1,11 @@
using System.Collections.Generic;
+using System.Drawing;
using System.IO;
using System.Windows.Forms;
-using BizHawk.Emulation.Common;
-
using BizHawk.Client.Common;
-using System.Drawing;
+using BizHawk.Common.PathExtensions;
+using BizHawk.Emulation.Common;
namespace BizHawk.Client.EmuHawk
{
@@ -26,7 +26,7 @@ namespace BizHawk.Client.EmuHawk
{
FileName = !string.IsNullOrWhiteSpace(currentFile)
? Path.GetFileName(currentFile)
- : $"{PathManager.FilesystemSafeName(Global.Game)}.{fileExt}",
+ : $"{Global.Game.Name.FilesystemSafeName()}.{fileExt}",
InitialDirectory = path,
Filter = new FilesystemFilterSet(new FilesystemFilter(fileType, new[] { fileExt })).ToString(),
RestoreDirectory = true
@@ -52,7 +52,7 @@ namespace BizHawk.Client.EmuHawk
{
FileName = !string.IsNullOrWhiteSpace(currentFile)
? Path.GetFileName(currentFile)
- : $"{PathManager.FilesystemSafeName(Global.Game)}.{fileExt}",
+ : $"{Global.Game.Name.FilesystemSafeName()}.{fileExt}",
InitialDirectory = path,
Filter = new FilesystemFilterSet(new FilesystemFilter(fileType, new[] { fileExt })).ToString(),
RestoreDirectory = true,
diff --git a/BizHawk.Client.EmuHawk/tools/ToolManager.cs b/BizHawk.Client.EmuHawk/tools/ToolManager.cs
index 3536c76e0c..846c42979a 100644
--- a/BizHawk.Client.EmuHawk/tools/ToolManager.cs
+++ b/BizHawk.Client.EmuHawk/tools/ToolManager.cs
@@ -12,6 +12,7 @@ using BizHawk.Client.ApiHawk;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk.CoreExtensions;
using BizHawk.Common;
+using BizHawk.Common.PathExtensions;
using BizHawk.Common.ReflectionExtensions;
using BizHawk.Emulation.Common;
@@ -873,7 +874,7 @@ namespace BizHawk.Client.EmuHawk
f.Directory.Create();
}
- return Path.Combine(path, $"{PathManager.FilesystemSafeName(Global.Game)}.cht");
+ return Path.Combine(path, $"{Global.Game.Name.FilesystemSafeName()}.cht");
}
public void UpdateCheatRelatedTools(object sender, CheatCollection.CheatListEventArgs e)
diff --git a/BizHawk.Client.EmuHawk/tools/TraceLogger.cs b/BizHawk.Client.EmuHawk/tools/TraceLogger.cs
index b46d7062c4..a0a20b635d 100644
--- a/BizHawk.Client.EmuHawk/tools/TraceLogger.cs
+++ b/BizHawk.Client.EmuHawk/tools/TraceLogger.cs
@@ -6,8 +6,9 @@ using System.Linq;
using System.Text;
using System.Windows.Forms;
-using BizHawk.Emulation.Common;
using BizHawk.Client.Common;
+using BizHawk.Common.PathExtensions;
+using BizHawk.Emulation.Common;
namespace BizHawk.Client.EmuHawk
{
@@ -284,12 +285,12 @@ namespace BizHawk.Client.EmuHawk
using var sfd = new SaveFileDialog();
if (LogFile == null)
{
- sfd.FileName = PathManager.FilesystemSafeName(Global.Game) + _extension;
+ sfd.FileName = Global.Game.Name.FilesystemSafeName() + _extension;
sfd.InitialDirectory = Config.PathEntries.LogAbsolutePath();
}
else if (!string.IsNullOrWhiteSpace(LogFile.FullName))
{
- sfd.FileName = PathManager.FilesystemSafeName(Global.Game);
+ sfd.FileName = Global.Game.Name.FilesystemSafeName();
sfd.InitialDirectory = Path.GetDirectoryName(LogFile.FullName);
}
else
@@ -457,7 +458,7 @@ namespace BizHawk.Client.EmuHawk
{
FileBox.Visible = true;
BrowseBox.Visible = true;
- var name = PathManager.FilesystemSafeName(Global.Game);
+ var name = Global.Game.Name.FilesystemSafeName();
var filename = Path.Combine(Config.PathEntries.LogAbsolutePath(), name) + _extension;
LogFile = new FileInfo(filename);
if (LogFile.Directory != null && !LogFile.Directory.Exists)
diff --git a/BizHawk.Common/Extensions/PathExtensions.cs b/BizHawk.Common/Extensions/PathExtensions.cs
new file mode 100644
index 0000000000..baade0e839
--- /dev/null
+++ b/BizHawk.Common/Extensions/PathExtensions.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Linq;
+using System.IO;
+
+namespace BizHawk.Common.PathExtensions
+{
+ public static class PathExtensions
+ {
+ public static string RemoveInvalidFileSystemChars(this string name)
+ {
+ var newStr = name;
+ var chars = Path.GetInvalidFileNameChars();
+ return chars.Aggregate(newStr, (current, c) => current.Replace(c.ToString(), ""));
+ }
+
+ ///
+ /// Decides if a path is non-empty, not . and not .\
+ ///
+ public static bool PathIsSet(this string path)
+ {
+ return !string.IsNullOrWhiteSpace(path) && path != "." && path != ".\\";
+ }
+
+ /// Algorithm for Windows taken from https://stackoverflow.com/a/7710620/7467292
+ public static bool IsSubfolderOf(this string childPath, string parentPath)
+ {
+ if (OSTailoredCode.IsUnixHost)
+ {
+#if true
+ return OSTailoredCode.SimpleSubshell("realpath", $"-L \"{childPath}\"", $"invalid path {childPath} or missing realpath binary")
+ .StartsWith(OSTailoredCode.SimpleSubshell("realpath", $"-L \"{parentPath}\"", $"invalid path {parentPath} or missing realpath binary"));
+#else // written for Unix port but may be useful for Windows when moving to .NET Core
+ var parentUriPath = new Uri(parentPath.TrimEnd('.')).AbsolutePath.TrimEnd('/');
+ try
+ {
+ for (var childUri = new DirectoryInfo(childPath).Parent; childUri != null; childUri = childUri?.Parent)
+ {
+ if (new Uri(childUri.FullName).AbsolutePath.TrimEnd('/') == parentUriPath) return true;
+ }
+ }
+ catch
+ {
+ // ignored
+ }
+ return false;
+#endif
+ }
+
+ var parentUri = new Uri(parentPath);
+ for (var childUri = new DirectoryInfo(childPath).Parent; childUri != null; childUri = childUri?.Parent)
+ {
+ if (new Uri(childUri.FullName) == parentUri) return true;
+ }
+
+ return false;
+ }
+
+ public static string MakeRelativeTo(this string absolutePath, string basePath)
+ {
+ if (absolutePath.IsSubfolderOf(basePath))
+ {
+ return absolutePath.Replace(basePath, ".");
+ }
+
+ return absolutePath;
+ }
+
+ public static string FilesystemSafeName(this string? name)
+ {
+ name ??= "";
+
+ var filesystemSafeName = name
+ .Replace("|", "+")
+ .Replace(":", " -") // Path.GetFileName scraps everything to the left of a colon unfortunately, so we need this hack here
+ .Replace("\"", "") // Ivan IronMan Stewart's Super Off-Road has quotes in game name
+ .Replace("/", "+"); // Mario Bros / Duck hunt has a slash in the name which GetDirectoryName and GetFileName treat as if it were a folder
+
+ // zero 06-nov-2015 - regarding the below, i changed my mind. for libretro i want subdirectories here.
+ var filesystemDir = Path.GetDirectoryName(filesystemSafeName);
+ filesystemSafeName = Path.GetFileName(filesystemSafeName);
+
+ filesystemSafeName = filesystemSafeName.RemoveInvalidFileSystemChars();
+
+ // zero 22-jul-2012 - i don't think this is used the same way it used to. game.Name shouldn't be a path, so this stuff is illogical.
+ // if game.Name is a path, then someone should have made it not-a-path already.
+ // return Path.Combine(Path.GetDirectoryName(filesystemSafeName), Path.GetFileNameWithoutExtension(filesystemSafeName));
+
+ // adelikat:
+ // This hack is to prevent annoying things like Super Mario Bros..bk2
+ if (filesystemSafeName.EndsWith("."))
+ {
+ filesystemSafeName = filesystemSafeName.Remove(filesystemSafeName.Length - 1, 1);
+ }
+
+ return Path.Combine(filesystemDir, filesystemSafeName);
+ }
+ }
+}