Skip to content

Commit 96b36fc

Browse files
committed
Add rename functionality
1 parent 9d03dbb commit 96b36fc

File tree

1 file changed

+182
-4
lines changed

1 file changed

+182
-4
lines changed

IRDKit/Program.cs

Lines changed: 182 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.Linq;
1212
using System.Security.Cryptography;
1313
using System.Text;
14+
using System.Xml.Linq;
1415

1516
namespace IRDKit
1617
{
@@ -24,7 +25,7 @@ internal class Program
2425
[Verb("create", HelpText = "Create an IRD from an ISO")]
2526
public class CreateOptions
2627
{
27-
[Value(0, Required = true, HelpText = "Path to an ISO file, or directory of ISO files")]
28+
[Value(0, Required = true, HelpText = "Path to ISO file(s), or directory of ISO files")]
2829
public IEnumerable<string> ISOPath { get; set; }
2930

3031
[Option('o', "output", HelpText = "Path to the IRD file to be created (will overwrite)")]
@@ -55,7 +56,7 @@ public class CreateOptions
5556
[Verb("info", HelpText = "Print information from an IRD or ISO")]
5657
public class InfoOptions
5758
{
58-
[Value(0, Required = true, HelpText = "Path to an IRD or ISO file, or directory of IRD and/or ISO files")]
59+
[Value(0, Required = true, HelpText = "Path to IRD/ISO file(s), or directory of IRD/ISO files")]
5960
public IEnumerable<string> InPath { get; set; }
6061

6162
[Option('o', "output", HelpText = "Path to the text or json file to be created (will overwrite)")]
@@ -84,6 +85,31 @@ public class DiffOptions
8485
public string OutPath { get; set; }
8586
}
8687

88+
/// <summary>
89+
/// IRD rename command
90+
/// </summary>
91+
[Verb("rename", HelpText = "Rename one or more IRD files according to the redump PS3 DAT")]
92+
public class RenameOptions
93+
{
94+
[Value(0, Required = true, HelpText = "Path to IRD file(s), or directory of IRD files")]
95+
public IEnumerable<string> IRDPath { get; set; }
96+
97+
[Option('d', "datfile", Required = true, HelpText = "Path to the redump PS3 Datfile")]
98+
public string DATPath { get; set; }
99+
100+
[Option('s', "serial", HelpText = "Appends disc serial to new IRD filename")]
101+
public bool Serial { get; set; }
102+
103+
[Option('c', "crc", HelpText = "Appends ISO CRC to new IRD filename")]
104+
public bool CRC { get; set; }
105+
106+
[Option('r', "recurse", HelpText = "Recurse through all subdirectories and rename all IRDs")]
107+
public bool Recurse { get; set; }
108+
109+
[Option('v', "verbose", HelpText = "Print more information about the renaming")]
110+
public bool Verbose { get; set; }
111+
}
112+
87113
#endregion
88114

89115
#region Program
@@ -98,7 +124,7 @@ public static void Main(string[] args)
98124
Console.OutputEncoding = Encoding.UTF8;
99125

100126
// Parse arguments
101-
var result = Parser.Default.ParseArguments<CreateOptions, InfoOptions, DiffOptions>(args).WithParsed(Run);
127+
var result = Parser.Default.ParseArguments<CreateOptions, InfoOptions, DiffOptions, RenameOptions>(args).WithParsed(Run);
102128
}
103129

104130
/// <summary>
@@ -173,7 +199,7 @@ private static void Run(object args)
173199
if (!File.Exists(isoPath))
174200
{
175201
Console.Error.WriteLine($"ISO not found: {isoPath}");
176-
return;
202+
continue;
177203
}
178204

179205
string irdPath;
@@ -330,6 +356,99 @@ private static void Run(object args)
330356

331357
break;
332358

359+
// Process options from a 'rename' command
360+
case RenameOptions opt:
361+
362+
// Validate required parameters
363+
if (opt.IRDPath == null || !opt.IRDPath.Any())
364+
{
365+
Console.Error.WriteLine("Provide a valid IRD path to rename");
366+
return;
367+
}
368+
369+
// Read DAT file
370+
XDocument datfile = DatParser(opt.DATPath);
371+
if (datfile == null)
372+
{
373+
Console.Error.WriteLine("Unable to parse DAT file");
374+
return;
375+
}
376+
377+
foreach (string irdPath in opt.IRDPath)
378+
{
379+
// Validate IRD path
380+
if (string.IsNullOrEmpty(irdPath))
381+
continue;
382+
383+
// If directory, search for all ISOs in current directory
384+
if (Directory.Exists(irdPath))
385+
{
386+
// If recurse option enabled, search recursively
387+
IEnumerable<string> irdFiles;
388+
if (opt.Recurse)
389+
{
390+
if (opt.Verbose && irdPath == ".")
391+
Console.WriteLine($"Recursively renaming IRDs in current directory");
392+
else if (opt.Verbose)
393+
Console.WriteLine($"Recursively renaming IRDs in {irdPath}");
394+
irdFiles = Directory.EnumerateFiles(irdPath, "*.ird", SearchOption.AllDirectories);
395+
}
396+
else
397+
{
398+
if (opt.Verbose && irdPath == ".")
399+
Console.WriteLine($"Renaming IRDs in current directory");
400+
else if (opt.Verbose)
401+
Console.WriteLine($"Renaming IRDs in {irdPath}");
402+
irdFiles = Directory.EnumerateFiles(irdPath, "*.ird", SearchOption.TopDirectoryOnly);
403+
}
404+
405+
// Warn if no files are found
406+
if (!irdFiles.Any())
407+
{
408+
if (opt.Recurse)
409+
Console.Error.WriteLine($"No IRDs found in {irdPath} (ensure .ird extension)");
410+
else
411+
Console.Error.WriteLine($"No IRDs found in {irdPath} (ensure .ird extension, or try use -r)");
412+
continue;
413+
}
414+
415+
// Rename all IRD files found
416+
foreach (string file in irdFiles.OrderBy(x => x))
417+
{
418+
try
419+
{
420+
RenameIRD(file, datfile, serial: opt.Serial, crc: opt.CRC, verbose: opt.Verbose);
421+
}
422+
catch (Exception e)
423+
{
424+
Console.Error.WriteLine(e);
425+
}
426+
}
427+
428+
}
429+
else
430+
{
431+
// Check that given file exists
432+
if (!File.Exists(irdPath))
433+
{
434+
Console.Error.WriteLine($"IRD not found: {irdPath}");
435+
continue;
436+
}
437+
438+
// Rename provided IRD path
439+
try
440+
{
441+
RenameIRD(irdPath, datfile, serial: opt.Serial, crc: opt.CRC, verbose: opt.Verbose);
442+
}
443+
catch (Exception e)
444+
{
445+
Console.Error.WriteLine(e);
446+
}
447+
}
448+
}
449+
450+
break;
451+
333452
// Unknown command
334453
default:
335454
break;
@@ -895,6 +1014,65 @@ public static string ISO2IRD(string isoPath, string irdPath = null, string hexKe
8951014
}
8961015
}
8971016

1017+
public static XDocument DatParser(string datpath = null)
1018+
{
1019+
try
1020+
{
1021+
if (!File.Exists(datpath))
1022+
return null;
1023+
1024+
return XDocument.Load(datpath);
1025+
}
1026+
catch
1027+
{
1028+
return null;
1029+
}
1030+
}
1031+
1032+
public static string GetDatFilename(IRD ird, XDocument datfile)
1033+
{
1034+
string crc32 = ird.UID.ToString("X8").ToLower();
1035+
XElement node = datfile.Root.Elements("game").Where(e => e.Element("rom").Attribute("crc").Value == crc32).FirstOrDefault() ?? throw new ArgumentException("Cannot find ISO in redump DAT");
1036+
return node.Attribute("name").Value;
1037+
}
1038+
1039+
public static void RenameIRD(string irdPath, XDocument datfile, bool serial = false, bool crc = false, bool verbose = false)
1040+
{
1041+
IRD ird = IRD.Read(irdPath);
1042+
1043+
if (ird.ExtraConfig != 0x0001)
1044+
throw new ArgumentException($"{irdPath} is not a redump-style IRD");
1045+
1046+
string filename = GetDatFilename(ird, datfile);
1047+
if (filename == null)
1048+
throw new ArgumentException($"Cannot determine DAT filename for {irdPath}");
1049+
if (serial)
1050+
filename += $" [{ird.TitleID[..4]}-{ird.TitleID[4..9]}]";
1051+
if (crc)
1052+
filename += $" [{ird.UID:X8}]";
1053+
1054+
// Rename irdPath to filename
1055+
string directory = Path.GetDirectoryName(Path.GetFullPath(filename));
1056+
string filepath;
1057+
if (!string.IsNullOrEmpty(directory))
1058+
filepath = Path.Combine(Path.GetDirectoryName(irdPath), filename + ".ird");
1059+
else
1060+
filepath = filename + ".ird";
1061+
1062+
// Rename IRD to new name
1063+
if (irdPath != filepath)
1064+
{
1065+
if (verbose)
1066+
Console.WriteLine($"Renaming {Path.GetFileName(irdPath)} to {Path.GetFileName(filepath)}");
1067+
File.Move(irdPath, filepath);
1068+
}
1069+
else
1070+
{
1071+
if (verbose)
1072+
Console.WriteLine($"Skipping {Path.GetFileName(irdPath)}, already named correctly");
1073+
}
1074+
}
1075+
8981076
#endregion
8991077

9001078
#region Helper Functions

0 commit comments

Comments
 (0)