2011-05-04 02:00:08 +00:00
using System ;
using System.Linq ;
using System.IO ;
2013-11-03 16:05:49 +00:00
using System.Reflection ;
2011-05-04 02:00:08 +00:00
2019-08-12 10:03:40 +00:00
using BizHawk.Common ;
2014-07-03 15:05:02 +00:00
using BizHawk.Common.StringExtensions ;
2013-11-04 01:06:36 +00:00
using BizHawk.Emulation.Common ;
2014-05-31 14:29:27 +00:00
using BizHawk.Emulation.Common.IEmulatorExtensions ;
2014-05-04 13:43:29 +00:00
using BizHawk.Emulation.Cores.Nintendo.SNES ;
2017-06-04 23:29:27 +00:00
using BizHawk.Emulation.Cores.Nintendo.SNES9X ;
2013-11-04 01:06:36 +00:00
2013-10-27 07:54:00 +00:00
namespace BizHawk.Client.Common
2011-05-04 02:00:08 +00:00
{
2011-07-06 01:53:15 +00:00
public static class PathManager
{
2018-12-23 05:23:57 +00:00
static PathManager ( )
{
SetDefaultIniPath ( MakeProgramRelativePath ( "config.ini" ) ) ;
}
2011-07-06 01:53:15 +00:00
public static string GetExeDirectoryAbsolute ( )
{
2014-05-04 01:54:58 +00:00
var path = Path . GetDirectoryName ( Assembly . GetEntryAssembly ( ) . Location ) ;
2013-11-01 22:37:05 +00:00
if ( path . EndsWith ( Path . DirectorySeparatorChar . ToString ( ) ) )
{
path = path . Remove ( path . Length - 1 , 1 ) ;
}
2014-05-04 01:54:58 +00:00
2013-11-01 22:37:05 +00:00
return path ;
2011-07-06 01:53:15 +00:00
}
2011-05-04 02:00:08 +00:00
2017-04-15 20:37:30 +00:00
/// <summary>
/// Makes a path relative to the %exe% directory
/// </summary>
2017-04-14 19:59:01 +00:00
public static string MakeProgramRelativePath ( string path )
{
2019-03-20 05:01:12 +00:00
return MakeAbsolutePath ( $"%exe%/{path}" , null ) ;
2017-04-14 19:59:01 +00:00
}
2011-06-11 22:15:08 +00:00
2017-04-14 19:59:01 +00:00
public static string GetDllDirectory ( )
{
return Path . Combine ( GetExeDirectoryAbsolute ( ) , "dll" ) ;
}
2015-08-20 23:35:53 +00:00
2011-06-11 22:15:08 +00:00
/// <summary>
/// The location of the default INI file
/// </summary>
2018-12-23 05:23:57 +00:00
public static string DefaultIniPath { get ; private set ; }
public static void SetDefaultIniPath ( string newDefaultIniPath )
{
DefaultIniPath = newDefaultIniPath ;
}
2011-06-11 22:15:08 +00:00
/// <summary>
/// Gets absolute base as derived from EXE
/// </summary>
2017-06-26 04:12:31 +00:00
public static string GetGlobalBasePathAbsolute ( )
2011-07-06 01:53:15 +00:00
{
2017-06-26 04:12:31 +00:00
var gbase = Global . Config . PathEntries . GlobalBaseFragment ;
2011-05-04 02:00:08 +00:00
2017-06-26 04:12:31 +00:00
// if %exe% prefixed then substitute exe path and repeat
if ( gbase . StartsWith ( "%exe%" , StringComparison . InvariantCultureIgnoreCase ) )
gbase = GetExeDirectoryAbsolute ( ) + gbase . Substring ( 5 ) ;
2014-05-04 01:54:58 +00:00
2017-06-26 04:12:31 +00:00
//rooted paths get returned without change
//(this is done after keyword substitution to avoid problems though)
if ( Path . IsPathRooted ( gbase ) )
return gbase ;
2014-05-04 01:54:58 +00:00
2017-06-26 04:12:31 +00:00
//not-rooted things are relative to exe path
gbase = Path . Combine ( GetExeDirectoryAbsolute ( ) , gbase ) ;
2011-05-04 02:00:08 +00:00
2017-06-26 04:12:31 +00:00
return gbase ;
2011-07-06 01:53:15 +00:00
}
2011-05-04 02:00:08 +00:00
2011-07-06 01:53:15 +00:00
public static string GetPlatformBase ( string system )
{
2013-08-11 21:48:17 +00:00
return Global . Config . PathEntries [ system , "Base" ] . Path ;
2011-07-06 01:53:15 +00:00
}
2011-05-04 02:00:08 +00:00
2012-12-30 17:33:33 +00:00
public static string StandardFirmwareName ( string name )
{
2013-12-13 05:20:50 +00:00
return Path . Combine ( MakeAbsolutePath ( Global . Config . PathEntries . FirmwaresPathFragment , null ) , name ) ;
2012-12-30 17:33:33 +00:00
}
2013-08-23 17:49:15 +00:00
public static string MakeAbsolutePath ( string path , string system )
2017-07-11 00:26:26 +00:00
{
//warning: supposedly Path.GetFullPath accesses directories (and needs permissions)
//if this poses a problem, we need to paste code from .net or mono sources and fix them to not pose problems, rather than homebrew stuff
return Path . GetFullPath ( MakeAbsolutePathInner ( path , system ) ) ;
}
static string MakeAbsolutePathInner ( string path , string system )
2011-07-06 01:53:15 +00:00
{
2014-05-04 01:54:58 +00:00
// Hack
2013-08-11 23:07:32 +00:00
if ( system = = "Global" )
{
system = null ;
}
2014-05-04 01:54:58 +00:00
// This function translates relative path and special identifiers in absolute paths
2011-07-06 01:53:15 +00:00
if ( path . Length < 1 )
2014-05-04 01:54:58 +00:00
{
2017-06-26 04:12:31 +00:00
return GetGlobalBasePathAbsolute ( ) ;
2014-05-04 01:54:58 +00:00
}
2011-05-04 02:00:08 +00:00
2011-07-06 01:53:15 +00:00
if ( path = = "%recent%" )
{
return Environment . SpecialFolder . Recent . ToString ( ) ;
}
2011-05-04 02:00:08 +00:00
2018-11-15 00:03:53 +00:00
if ( path . StartsWith ( "%exe%" ) )
return GetExeDirectoryAbsolute ( ) + path . Substring ( 5 ) ;
if ( path . StartsWith ( "%rom%" ) )
return Global . Config . LastRomPath + path . Substring ( 5 ) ;
2011-05-04 02:00:08 +00:00
2011-07-06 01:53:15 +00:00
if ( path [ 0 ] = = '.' )
{
2014-05-04 01:54:58 +00:00
if ( ! string . IsNullOrWhiteSpace ( system ) )
2011-07-06 01:53:15 +00:00
{
path = path . Remove ( 0 , 1 ) ;
path = path . Insert ( 0 , GetPlatformBase ( system ) ) ;
}
2014-05-04 01:54:58 +00:00
2011-07-06 01:53:15 +00:00
if ( path . Length = = 1 )
2014-05-04 01:54:58 +00:00
{
2017-06-26 04:12:31 +00:00
return GetGlobalBasePathAbsolute ( ) ;
2014-05-04 01:54:58 +00:00
}
2014-08-13 17:55:34 +00:00
2014-05-04 01:54:58 +00:00
if ( path [ 0 ] = = '.' )
2011-07-06 01:53:15 +00:00
{
2014-05-04 01:54:58 +00:00
path = path . Remove ( 0 , 1 ) ;
2017-06-26 04:12:31 +00:00
path = path . Insert ( 0 , GetGlobalBasePathAbsolute ( ) ) ;
2011-07-06 01:53:15 +00:00
}
2011-05-04 02:00:08 +00:00
2014-05-04 01:54:58 +00:00
return path ;
}
2011-05-04 02:00:08 +00:00
2017-07-17 14:47:25 +00:00
if ( Path . IsPathRooted ( path ) )
return path ;
2017-07-11 00:26:26 +00:00
//handling of initial .. was removed (Path.GetFullPath can handle it)
//handling of file:// or file:\\ was removed (can Path.GetFullPath handle it? not sure)
2011-05-04 02:00:08 +00:00
2018-09-12 01:32:34 +00:00
// all bad paths default to EXE
2011-07-06 01:53:15 +00:00
return GetExeDirectoryAbsolute ( ) ;
}
2011-05-04 02:00:08 +00:00
2011-07-06 01:53:15 +00:00
public static string RemoveParents ( string path , string workingpath )
{
2014-05-04 01:54:58 +00:00
// determines number of parents, then removes directories from working path, return absolute path result
// Ex: "..\..\Bob\", "C:\Projects\Emulators\Bizhawk" will return "C:\Projects\Bob\"
2011-07-06 01:53:15 +00:00
int x = NumParentDirectories ( path ) ;
if ( x > 0 )
{
2014-07-03 15:05:02 +00:00
int y = path . HowMany ( "..\\" ) ;
int z = workingpath . HowMany ( "\\" ) ;
2011-07-06 01:53:15 +00:00
if ( y > = z )
{
2017-04-14 19:59:01 +00:00
// Return drive letter only, working path must be absolute?
2011-07-06 01:53:15 +00:00
}
2014-05-04 01:54:58 +00:00
2017-05-10 11:45:23 +00:00
return "" ;
2011-07-06 01:53:15 +00:00
}
2014-05-04 01:54:58 +00:00
return path ;
2011-07-06 01:53:15 +00:00
}
2011-05-04 02:00:08 +00:00
2011-07-06 01:53:15 +00:00
public static int NumParentDirectories ( string path )
{
2014-05-04 01:54:58 +00:00
// determine the number of parent directories in path and return result
2014-07-03 15:05:02 +00:00
int x = path . HowMany ( '\\' ) ;
2011-07-06 01:53:15 +00:00
if ( x > 0 )
{
2014-07-03 15:05:02 +00:00
return path . HowMany ( "..\\" ) ;
2011-07-06 01:53:15 +00:00
}
2014-05-04 01:54:58 +00:00
2011-07-06 01:53:15 +00:00
return 0 ;
}
2011-05-04 02:00:08 +00:00
2011-07-06 01:53:15 +00:00
public static bool IsRecent ( string path )
{
2013-08-23 16:03:57 +00:00
return path = = "%recent%" ;
2011-07-06 01:53:15 +00:00
}
2011-05-21 01:13:48 +00:00
2012-11-29 18:42:13 +00:00
public static string GetLuaPath ( )
{
2013-12-13 05:20:50 +00:00
return MakeAbsolutePath ( Global . Config . PathEntries . LuaPathFragment , null ) ;
2012-11-29 18:42:13 +00:00
}
2014-07-21 23:41:41 +00:00
// Decides if a path is non-empty, not . and not .\
private static bool PathIsSet ( string path )
{
if ( ! string . IsNullOrWhiteSpace ( path ) )
{
return path ! = "." & & path ! = ".\\" ;
}
return false ;
}
2017-05-09 12:21:38 +00:00
public static string GetRomsPath ( string sysId )
2011-07-06 01:53:15 +00:00
{
if ( Global . Config . UseRecentForROMs )
2013-08-11 21:48:17 +00:00
{
2011-07-06 01:53:15 +00:00
return Environment . SpecialFolder . Recent . ToString ( ) ;
2013-08-11 21:48:17 +00:00
}
2011-07-06 01:53:15 +00:00
2017-05-09 12:21:38 +00:00
var path = Global . Config . PathEntries [ sysId , "ROM" ] ;
2014-07-21 23:41:41 +00:00
if ( path = = null | | ! PathIsSet ( path . Path ) )
{
path = Global . Config . PathEntries [ "Global" , "ROM" ] ;
if ( path ! = null & & PathIsSet ( path . Path ) )
{
return MakeAbsolutePath ( path . Path , null ) ;
}
}
2013-08-11 21:48:17 +00:00
2017-05-09 12:21:38 +00:00
return MakeAbsolutePath ( path . Path , sysId ) ;
2011-07-06 01:53:15 +00:00
}
2011-08-04 03:20:54 +00:00
2011-09-04 19:24:40 +00:00
public static string RemoveInvalidFileSystemChars ( string name )
{
2014-05-04 01:54:58 +00:00
var newStr = name ;
var chars = Path . GetInvalidFileNameChars ( ) ;
2017-05-10 11:45:23 +00:00
return chars . Aggregate ( newStr , ( current , c ) = > current . Replace ( c . ToString ( ) , "" ) ) ;
2011-09-04 19:24:40 +00:00
}
2011-08-10 23:50:01 +00:00
public static string FilesystemSafeName ( GameInfo game )
{
2016-09-21 14:27:28 +00:00
var filesystemSafeName = game . Name
. Replace ( "|" , "+" )
2016-10-14 01:16:26 +00:00
. Replace ( ":" , " -" ) // adelikat - Path.GetFileName scraps everything to the left of a colon unfortunately, so we need this hack here
2018-05-06 20:10:08 +00:00
. Replace ( "\"" , "" ) // adelikat - Ivan Ironman Stewart's Super Off-Road has quotes in game name
. Replace ( "/" , "+" ) ; // Narry - Mario Bros / Duck hunt has a slash in the name which GetDirectoryName and GetFileName treat as if it were a folder
2015-11-06 14:31:50 +00:00
// 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 ) ;
2011-09-04 19:24:40 +00:00
filesystemSafeName = RemoveInvalidFileSystemChars ( filesystemSafeName ) ;
2014-05-04 01:54:58 +00:00
// zero 22-jul-2012 - i dont think this is used the same way it used to. game.Name shouldnt be a path, so this stuff is illogical.
// if game.Name is a path, then someone shouldve made it not-a-path already.
// return Path.Combine(Path.GetDirectoryName(filesystemSafeName), Path.GetFileNameWithoutExtension(filesystemSafeName));
2014-06-20 18:36:03 +00:00
// adelikat:
// This hack is to prevent annoying things like Super Mario Bros..bk2
if ( filesystemSafeName . EndsWith ( "." ) )
{
2015-11-06 14:31:50 +00:00
filesystemSafeName = filesystemSafeName . Remove ( filesystemSafeName . Length - 1 , 1 ) ;
2014-06-20 18:36:03 +00:00
}
2015-11-06 14:31:50 +00:00
return Path . Combine ( filesystemDir , filesystemSafeName ) ;
2011-08-10 23:50:01 +00:00
}
2011-08-04 03:20:54 +00:00
2011-08-10 23:50:01 +00:00
public static string SaveRamPath ( GameInfo game )
{
2014-05-04 01:54:58 +00:00
var name = FilesystemSafeName ( game ) ;
2013-10-24 22:26:28 +00:00
if ( Global . MovieSession . Movie . IsActive )
2012-03-03 18:11:07 +00:00
{
2019-03-20 05:01:12 +00:00
name + = $".{Path.GetFileNameWithoutExtension(Global.MovieSession.Movie.Filename)}" ;
2012-03-03 18:11:07 +00:00
}
2011-09-17 14:23:23 +00:00
2014-05-04 01:54:58 +00:00
var pathEntry = Global . Config . PathEntries [ game . System , "Save RAM" ] ? ?
2014-08-13 17:55:34 +00:00
Global . Config . PathEntries [ game . System , "Base" ] ;
2013-08-11 21:48:17 +00:00
2019-03-20 05:01:12 +00:00
return $"{Path.Combine(MakeAbsolutePath(pathEntry.Path, game.System), name)}.SaveRAM" ;
2011-08-10 23:50:01 +00:00
}
2017-08-20 06:14:08 +00:00
public static string AutoSaveRamPath ( GameInfo game )
{
var path = SaveRamPath ( game ) ;
return path . Insert ( path . Length - 8 , ".AutoSaveRAM" ) ;
}
2011-08-04 03:20:54 +00:00
2015-11-09 01:18:08 +00:00
public static string RetroSaveRAMDirectory ( GameInfo game )
{
2017-04-14 19:59:01 +00:00
// hijinx here to get the core name out of the game name
2015-11-09 01:18:08 +00:00
var name = FilesystemSafeName ( game ) ;
name = Path . GetDirectoryName ( name ) ;
2017-05-10 11:45:23 +00:00
if ( name = = "" )
2017-05-09 12:21:38 +00:00
{
name = FilesystemSafeName ( game ) ;
}
2015-11-09 01:18:08 +00:00
if ( Global . MovieSession . Movie . IsActive )
{
2019-03-20 05:01:12 +00:00
name = Path . Combine ( name , $"movie-{Path.GetFileNameWithoutExtension(Global.MovieSession.Movie.Filename)}" ) ;
2015-11-09 01:18:08 +00:00
}
var pathEntry = Global . Config . PathEntries [ game . System , "Save RAM" ] ? ?
Global . Config . PathEntries [ game . System , "Base" ] ;
return Path . Combine ( MakeAbsolutePath ( pathEntry . Path , game . System ) , name ) ;
}
public static string RetroSystemPath ( GameInfo game )
{
2017-04-14 19:59:01 +00:00
// hijinx here to get the core name out of the game name
2015-11-09 01:18:08 +00:00
var name = FilesystemSafeName ( game ) ;
name = Path . GetDirectoryName ( name ) ;
2017-05-10 11:45:23 +00:00
if ( name = = "" )
2017-04-14 19:59:01 +00:00
{
name = FilesystemSafeName ( game ) ;
}
2015-11-09 01:18:08 +00:00
var pathEntry = Global . Config . PathEntries [ game . System , "System" ] ? ?
Global . Config . PathEntries [ game . System , "Base" ] ;
return Path . Combine ( MakeAbsolutePath ( pathEntry . Path , game . System ) , name ) ;
}
2015-11-07 08:29:04 +00:00
public static string GetGameBasePath ( GameInfo game )
{
var name = FilesystemSafeName ( game ) ;
var pathEntry = Global . Config . PathEntries [ game . System , "Base" ] ;
return MakeAbsolutePath ( pathEntry . Path , game . System ) ;
}
2012-04-22 13:56:34 +00:00
public static string GetSaveStatePath ( GameInfo game )
{
2014-05-04 01:54:58 +00:00
var pathEntry = Global . Config . PathEntries [ game . System , "Savestates" ] ? ?
2014-08-13 17:55:34 +00:00
Global . Config . PathEntries [ game . System , "Base" ] ;
2013-08-11 21:48:17 +00:00
2013-08-23 16:03:57 +00:00
return MakeAbsolutePath ( pathEntry . Path , game . System ) ;
2012-04-22 13:56:34 +00:00
}
2011-08-10 23:50:01 +00:00
public static string SaveStatePrefix ( GameInfo game )
{
2014-05-04 01:54:58 +00:00
var name = FilesystemSafeName ( game ) ;
2014-05-04 13:20:59 +00:00
2014-05-04 13:43:29 +00:00
// Neshawk and Quicknes have incompatible savestates, store the name to keep them separate
2014-05-04 13:20:59 +00:00
if ( Global . Emulator . SystemId = = "NES" )
{
2019-03-20 05:01:12 +00:00
name + = $".{Global.Emulator.Attributes().CoreName}" ;
2014-05-04 13:20:59 +00:00
}
2017-12-15 19:29:11 +00:00
// Gambatte and GBHawk have incompatible savestates, store the name to keep them separate
if ( Global . Emulator . SystemId = = "GB" )
{
2019-03-20 05:01:12 +00:00
name + = $".{Global.Emulator.Attributes().CoreName}" ;
2017-12-15 19:29:11 +00:00
}
2017-06-04 23:29:27 +00:00
if ( Global . Emulator is Snes9x ) // Keep snes9x savestate away from libsnes, we want to not be too tedious so bsnes names will just have the profile name not the core name
{
2019-03-20 05:01:12 +00:00
name + = $".{Global.Emulator.Attributes().CoreName}" ;
2017-06-04 23:29:27 +00:00
}
2014-05-04 13:43:29 +00:00
// Bsnes profiles have incompatible savestates so save the profile name
if ( Global . Emulator is LibsnesCore )
{
2019-03-20 05:01:12 +00:00
name + = $".{((LibsnesCore)Global.Emulator).CurrentProfile}" ;
2014-05-04 13:43:29 +00:00
}
2015-06-06 21:06:59 +00:00
if ( Global . Emulator . SystemId = = "GBA" )
{
2019-03-20 05:01:12 +00:00
name + = $".{Global.Emulator.Attributes().CoreName}" ;
2015-06-06 21:06:59 +00:00
}
2013-12-04 02:43:40 +00:00
if ( Global . MovieSession . Movie . IsActive )
2012-09-03 19:42:53 +00:00
{
2019-03-20 05:01:12 +00:00
name + = $".{Path.GetFileNameWithoutExtension(Global.MovieSession.Movie.Filename)}" ;
2012-09-03 19:42:53 +00:00
}
2013-08-11 21:48:17 +00:00
2014-05-04 01:54:58 +00:00
var pathEntry = Global . Config . PathEntries [ game . System , "Savestates" ] ? ?
2014-08-13 17:55:34 +00:00
Global . Config . PathEntries [ game . System , "Base" ] ;
2013-08-11 21:48:17 +00:00
2013-08-23 16:03:57 +00:00
return Path . Combine ( MakeAbsolutePath ( pathEntry . Path , game . System ) , name ) ;
2011-08-10 23:50:01 +00:00
}
2011-08-04 03:20:54 +00:00
2013-10-04 22:21:09 +00:00
public static string GetCheatsPath ( GameInfo game )
{
2014-05-04 01:54:58 +00:00
var pathEntry = Global . Config . PathEntries [ game . System , "Cheats" ] ? ?
2014-08-13 17:55:34 +00:00
Global . Config . PathEntries [ game . System , "Base" ] ;
2013-10-04 22:21:09 +00:00
return MakeAbsolutePath ( pathEntry . Path , game . System ) ;
}
2015-11-06 14:31:50 +00:00
public static string GetPathType ( string system , string type )
{
2017-05-09 12:21:38 +00:00
var path = GetPathEntryWithFallback ( type , system ) . Path ;
2015-11-06 14:31:50 +00:00
return MakeAbsolutePath ( path , system ) ;
}
2011-08-10 23:50:01 +00:00
public static string ScreenshotPrefix ( GameInfo game )
{
2014-05-04 01:54:58 +00:00
var name = FilesystemSafeName ( game ) ;
2013-08-11 21:48:17 +00:00
2014-05-04 01:54:58 +00:00
var pathEntry = Global . Config . PathEntries [ game . System , "Screenshots" ] ? ?
2014-08-13 17:55:34 +00:00
Global . Config . PathEntries [ game . System , "Base" ] ;
2013-08-11 21:48:17 +00:00
2013-08-23 17:49:15 +00:00
return Path . Combine ( MakeAbsolutePath ( pathEntry . Path , game . System ) , name ) ;
2011-08-10 23:50:01 +00:00
}
2013-08-13 00:50:14 +00:00
/// <summary>
/// Takes an absolute path and attempts to convert it to a relative, based on the system,
/// or global base if no system is supplied, if it is not a subfolder of the base, it will return the path unaltered
/// </summary>
2014-05-04 01:54:58 +00:00
public static string TryMakeRelative ( string absolutePath , string system = null )
2013-08-13 00:50:14 +00:00
{
2019-08-12 10:03:40 +00:00
var parentPath = string . IsNullOrWhiteSpace ( system )
? GetGlobalBasePathAbsolute ( )
: MakeAbsolutePath ( GetPlatformBase ( system ) , system ) ;
2019-08-17 05:45:26 +00:00
#if true
2019-08-12 10:03:40 +00:00
if ( ! IsSubfolder ( parentPath , absolutePath ) ) return absolutePath ;
return OSTailoredCode . CurrentOS = = OSTailoredCode . DistinctOS . Windows
? absolutePath . Replace ( parentPath , "." )
: "./" + OSTailoredCode . SimpleSubshell ( "realpath" , $"--relative-to=\" { parentPath } \ " \"{absolutePath}\"" , $"invalid path {absolutePath} or missing realpath binary" ) ;
2019-08-17 05:45:26 +00:00
#else // written for Unix port but may be useful for .NET Core
if ( ! IsSubfolder ( parentPath , absolutePath ) )
{
return OSTailoredCode . CurrentOS = = OSTailoredCode . DistinctOS . Windows
| | parentPath . TrimEnd ( '.' ) ! = $"{absolutePath}/"
? absolutePath
: "." ;
}
return OSTailoredCode . CurrentOS = = OSTailoredCode . DistinctOS . Windows
? absolutePath . Replace ( parentPath , "." )
: absolutePath . Replace ( parentPath . TrimEnd ( '.' ) , "./" ) ;
#endif
2013-08-13 00:50:14 +00:00
}
2015-01-29 02:08:12 +00:00
public static string MakeRelativeTo ( string absolutePath , string basePath )
{
if ( IsSubfolder ( basePath , absolutePath ) )
{
return absolutePath . Replace ( basePath , "." ) ;
}
return absolutePath ;
}
2019-08-12 10:03:40 +00:00
/// <remarks>Algorithm for Windows taken from https://stackoverflow.com/a/7710620/7467292</remarks>
2017-04-14 19:59:01 +00:00
private static bool IsSubfolder ( string parentPath , string childPath )
2013-08-13 00:50:14 +00:00
{
2019-08-12 10:03:40 +00:00
if ( OSTailoredCode . CurrentOS = = OSTailoredCode . DistinctOS . Windows )
2013-08-13 00:50:14 +00:00
{
2019-08-12 10:03:40 +00:00
var parentUri = new Uri ( parentPath ) ;
2019-08-17 05:45:26 +00:00
for ( var childUri = new DirectoryInfo ( childPath ) . Parent ; childUri ! = null ; childUri = childUri ? . Parent )
2013-08-13 00:50:14 +00:00
{
2019-08-12 10:03:40 +00:00
if ( new Uri ( childUri . FullName ) = = parentUri ) return true ;
2013-08-13 00:50:14 +00:00
}
2019-08-12 10:03:40 +00:00
return false ;
2013-08-13 00:50:14 +00:00
}
2019-08-17 05:45:26 +00:00
#if true
2019-08-12 10:03:40 +00:00
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" ) ) ;
2019-08-17 05:45:26 +00:00
#else // written for Unix port but may be useful for .NET Core
{
var parentUri = new Uri ( parentPath . TrimEnd ( '.' ) ) ;
try
{
for ( var childUri = new DirectoryInfo ( childPath ) . Parent ; childUri ! = null ; childUri = childUri ? . Parent )
{
if ( new Uri ( childUri . FullName ) . AbsolutePath . TrimEnd ( '/' ) = = parentUri . AbsolutePath . TrimEnd ( '/' ) ) return true ;
}
}
catch
{
// ignored
}
return false ;
}
#endif
2013-08-13 00:50:14 +00:00
}
2014-08-13 17:50:24 +00:00
/// <summary>
/// Don't only valid system ids to system ID, pathType is ROM, Screenshot, etc
/// Returns the desired path, if does not exist, returns platform base, else it returns base
/// </summary>
2017-04-14 19:59:01 +00:00
private static PathEntry GetPathEntryWithFallback ( string pathType , string systemId )
2014-08-13 17:50:24 +00:00
{
2017-04-14 19:59:01 +00:00
var entry = Global . Config . PathEntries [ systemId , pathType ] ;
2014-08-13 17:50:24 +00:00
if ( entry = = null )
{
2017-04-14 19:59:01 +00:00
entry = Global . Config . PathEntries [ systemId , "Base" ] ;
2014-08-13 17:50:24 +00:00
}
if ( entry = = null )
{
entry = Global . Config . PathEntries [ "Global" , "Base" ] ;
}
return entry ;
}
2018-09-12 01:32:34 +00:00
/// <summary>
/// Puts the currently configured temp path into the environment for use as actual temp directory
/// </summary>
public static void RefreshTempPath ( )
{
if ( Global . Config . PathEntries . TempFilesFragment ! = "" )
{
//TODO - BUG - needs to route through PathManager.MakeAbsolutePath or something similar, but how?
string target = Global . Config . PathEntries . TempFilesFragment ;
BizHawk . Common . TempFileManager . HelperSetTempPath ( target ) ;
}
}
2011-07-06 01:53:15 +00:00
}
2018-09-12 01:32:34 +00:00
2011-05-04 02:00:08 +00:00
}