Skip to content

Commit

Permalink
Improve info and extract commands
Browse files Browse the repository at this point in the history
- You can now choose to either specify regions to download or regions to skip
- You can now display more than 4096 files by using the '-a' ('--show-all-files') option with the info command.
  • Loading branch information
LukeFZ committed Aug 31, 2023
1 parent 066715a commit 53e27d0
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 17 deletions.
24 changes: 20 additions & 4 deletions XvdTool.Streaming/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ public sealed class Settings : XvdCommandSettings
[Description("File path to save the output into.")]
[CommandOption("-o|--output")]
public string? OutputPath { get; init; }

[Description("If all files should be printed.\nIf unset, only the first 4096 files will be printed.")]
[CommandOption(("-a|--show-all-files"))]
public bool ShowAllFiles { get; set; }
}

public override int Execute(CommandContext context, Settings settings)
Expand All @@ -160,7 +164,7 @@ public override int Execute(CommandContext context, Settings settings)

using (XvdFile)
{
var infoOutput = XvdFile.PrintInfo();
var infoOutput = XvdFile.PrintInfo(settings.ShowAllFiles);
if (settings.OutputPath != null)
{
var directory = Path.GetDirectoryName(settings.OutputPath);
Expand All @@ -185,8 +189,12 @@ public sealed class Settings : CryptoCommandSettings
public string? OutputDirectory { get; init; }

[Description("List of regions to skip downloading. Defaults to none.")]
[CommandOption("-r|--skip-region")]
public uint[]? SkippedRegions { get; init; }
[CommandOption("-b|--skip-region")]
public uint[]? SkipRegions { get; init; }

[Description("List of regions to download. Defaults to all.")]
[CommandOption("-w|--download-region")]
public uint[]? DownloadRegions { get; init; }

[Description("Skips performing hash verification on the pages prior to decryption.\nMassively improves performance at the cost of integrity.\nOnly use this if you know the file is not corrupt!")]
[CommandOption("-n|--no-hash-check")]
Expand All @@ -210,13 +218,21 @@ public override int Execute(CommandContext context, Settings settings)

using (XvdFile)
{
XvdFile.ExtractFiles(outputPath, keyEntry, settings.SkipHashCheck, settings.SkippedRegions);
XvdFile.ExtractFiles(outputPath, keyEntry, settings.SkipHashCheck, settings.SkipRegions, settings.DownloadRegions);
}

ConsoleLogger.WriteInfoLine("[green bold]Successfully[/] extracted files.");

return 0;
}

public override ValidationResult Validate(CommandContext context, Settings settings)
{
if (settings is {DownloadRegions: not null, SkipRegions: not null})
return ValidationResult.Error("'--skip-region' and '--download-region' cannot be used together.");

return ValidationResult.Success();
}
}

internal sealed class VerifyCommand : XvdCommand<VerifyCommand.Settings>
Expand Down
56 changes: 43 additions & 13 deletions XvdTool.Streaming/StreamedXvdFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ public bool VerifyDataHashes()
return LocalVerifyDataHashes();
}

public void ExtractFiles(string outputPath, in KeyEntry key, bool skipHashCheck = false, uint[]? skippedRegionList = null)
public void ExtractFiles(string outputPath, in KeyEntry key, bool skipHashCheck = false, uint[]? skippedRegionList = null, uint[]? downloadRegionList = null)
{
if (!_hasXvcInfo)
{
Expand Down Expand Up @@ -340,12 +340,24 @@ public void ExtractFiles(string outputPath, in KeyEntry key, bool skipHashCheck

var firstSegmentOffset = XvdMath.PageNumberToOffset(_xvcUpdateSegments[0].PageNum);

var extractableRegionList =
_xvcRegions
.Where(region =>
(skippedRegionList == null || !skippedRegionList.Contains((uint)region.Id))
XvcRegionHeader[] extractableRegionList;

if (downloadRegionList != null)
{
extractableRegionList = _xvcRegions
.Where(region => downloadRegionList.Contains((uint)region.Id)
&& (region.FirstSegmentIndex != 0 || firstSegmentOffset == region.Offset))
.ToArray();
.ToArray();
}
else
{
extractableRegionList =
_xvcRegions
.Where(region =>
(skippedRegionList == null || !skippedRegionList.Contains((uint)region.Id))
&& (region.FirstSegmentIndex != 0 || firstSegmentOffset == region.Offset))
.ToArray();
}

// Fancy console version
AnsiConsole.Progress()
Expand Down Expand Up @@ -553,7 +565,7 @@ private void ExtractRegion(
}
}

public string PrintInfo()
public string PrintInfo(bool showAllFiles = false)
{
AnsiConsole.Record();

Expand Down Expand Up @@ -665,6 +677,7 @@ static Rows StringToRows(string text)
.AddColumns(
new TableColumn("Offset"),
new TableColumn("Size"),
new TableColumn("Size in Bytes"),
new TableColumn("File Path")
)
.RoundedBorder()
Expand All @@ -675,6 +688,7 @@ static Rows StringToRows(string text)
packageFilesTable.AddRow(
new Markup($"[green bold]0x{entry.Offset:x8}[/]"),
new Markup($"[green bold]0x{entry.Size:x8}[/]"),
new Markup($"[green bold]{ToFileSize(entry.Size)}[/]"),
new Markup($"[aqua underline]{entry.FilePath}[/]")
);
}
Expand All @@ -701,38 +715,54 @@ static Rows StringToRows(string text)
.AddColumns(
new TableColumn("Start Page"),
new TableColumn("File Size"),
new TableColumn("Size in Bytes"),
new TableColumn("Hash"),
new TableColumn("Flags"),
new TableColumn("File Path")
)
.RoundedBorder()
.Expand();

for (int i = 0; i < Math.Min(_segments.Length, 0x1000); i++)
for (int i = 0; i < (showAllFiles ? _segments.Length : Math.Min(_segments.Length, 0x1000)); i++)
{
var segment = _segments[i];
var updateSegment = _xvcUpdateSegments[i];

segmentTable.AddRow(
new Markup($"[green]0x{updateSegment.PageNum:x8}[/]"),
new Markup($"[green]0x{segment.FileSize:x16}[/]"),
new Markup($"[green]{ToFileSize(segment.FileSize)}[/]"),
new Markup($"[green]0x{updateSegment.Hash:x16}[/]"),
new Markup(segment.Flags != 0x0 ? $"[fuchsia]0x{(byte)segment.Flags:x2}[/]" : $"0x{segment.Flags}"),
new Markup($"[aqua underline]{_segmentPaths[i]}[/]")
);
}

if (_segments.Length > 0x1000)
{
segmentTable.AddEmptyRow();
segmentTable.AddRow(new Markup("[red bold]<Too many segment files to print>[/]"));
}
if (!showAllFiles && _segments.Length > 0x1000)
{
segmentTable.AddEmptyRow();
segmentTable.AddRow(new Markup("[red bold]<Too many segment files to print>[/]"));
}

AnsiConsole.Write(segmentTable);
}
}

return AnsiConsole.ExportText();

string ToFileSize(ulong size)
{
if (size < 1024)
return $"{size} B";

if (size < 1024 * 1024)
return $"{Math.Round(size / 1024.0, 2)} KB";

if (size < 1024 * 1024 * 1024)
return $"{Math.Round(size / (1024.0 * 1024.0), 2)} MB";

return $"{Math.Round(size / (1024.0 * 1024.0 * 1024.0), 2)} KB";
}
}

public void Dispose()
Expand Down

0 comments on commit 53e27d0

Please sign in to comment.