Last active
July 18, 2024 23:57
-
-
Save Still34/a1e34f24ff0a26deed52fddc60999435 to your computer and use it in GitHub Desktop.
PowerShell script for generating template for submission info for NX titles
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Requires -Version 7 | |
$Config = [PSCustomObject]@{ | |
NXGameInfoPath = "E:\tools\NXGameInfo-CLI\nxgameinfo_cli.exe" | |
HashMyFiles = "hashmyfiles.exe" | |
HacToolNet = "E:\tools\hactoolnet\hactoolnet.exe" | |
} | |
if ("NXNativeWin32" -as [type]) {}else { | |
Add-Type -TypeDefinition @" | |
using System; | |
using System.Runtime.InteropServices; | |
public class NXNativeWin32 { | |
[DllImport("ntdll.dll", SetLastError = true)] | |
public static extern uint RtlComputeCrc32(uint initialCrc, byte[] buffer, int length); | |
} | |
"@ | |
} | |
function Get-FileCRC32 { | |
# works well for items smaller than int32 size - not so much after that, especially for large XCIs | |
param ( | |
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] | |
[ValidateNotNullOrEmpty()] | |
[Alias('PSPath', 'LP')] | |
[string]$LiteralPath | |
) | |
begin { | |
if (-Not (Test-Path -LiteralPath $LiteralPath)) { | |
throw [System.IO.FileNotFoundException]::new("File not found ($LiteralPath).") | |
} | |
} | |
process { | |
$item = Get-Item -LiteralPath $LiteralPath | |
$bytes = [System.IO.File]::ReadAllBytes($item.FullName) | |
$crc32 = [NXNativeWin32]::RtlComputeCrc32(0, $bytes, $bytes.Length) | |
return $crc32.ToString("X8") | |
} | |
} | |
function Split-StringIntoChunks { | |
param ( | |
[string]$InputString, | |
[int]$ChunkSize | |
) | |
$chunks = @() | |
for ($i = 0; $i -lt $InputString.Length; $i += $ChunkSize) { | |
$chunks += $InputString.Substring($i, [Math]::Min($ChunkSize, $InputString.Length - $i)) | |
} | |
return $chunks | |
} | |
function Get-CardIDSet { | |
param ( | |
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] | |
[ValidateNotNullOrEmpty()] | |
[Alias('PSPath', 'LP')] | |
[string]$LiteralPath | |
) | |
begin { | |
if (-Not (Test-Path -LiteralPath $LiteralPath)) { | |
throw [System.IO.FileNotFoundException]::new("File not found ($LiteralPath).") | |
} | |
if (((Get-Item -LiteralPath $LiteralPath).Length) -ne 12) { | |
throw [System.InvalidOperationException]::new("File is abnormally large for Card ID Set.") | |
} | |
} | |
process { | |
$sb = [System.Text.StringBuilder]::new() | |
[void]$sb.AppendLine("Format: Card ID Sets") | |
$content = Get-Content -LiteralPath $LiteralPath -AsByteStream | |
$hexString = [System.Convert]::ToHexString($content) | |
$sets = Split-StringIntoChunks -InputString $hexString -ChunkSize 8 | |
$i = 1 | |
foreach ($set in $sets) { | |
[void]$sb.AppendLine("Card ID $($i): $set") | |
$i++ | |
} | |
$crc32 = Get-FileCRC32 -LiteralPath $LiteralPath | |
[void]$sb.AppendLine("CRC32: $crc32") | |
} | |
end { | |
return $sb.ToString() | |
} | |
} | |
function Get-NXGameInfo { | |
param ( | |
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] | |
[ValidateNotNullOrEmpty()] | |
[Alias('PSPath', 'LP')] | |
[string]$LiteralPath | |
) | |
begin { | |
if (-Not (Test-Path -LiteralPath $LiteralPath)) { | |
throw [System.IO.FileNotFoundException]::new("File not found ($LiteralPath).") | |
} | |
} | |
process { | |
return Invoke-Command -ScriptBlock { . $Config.NXGameInfoPath $args[0] } -ArgumentList (gi -LiteralPath $LiteralPath).FullName | |
} | |
} | |
function Get-HacToolNetInfo { | |
param ( | |
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] | |
[ValidateNotNullOrEmpty()] | |
[Alias('PSPath', 'LP')] | |
[string]$LiteralPath | |
) | |
begin { | |
if (-Not (Test-Path -LiteralPath $LiteralPath)) { | |
throw [System.IO.FileNotFoundException]::new("File not found ($LiteralPath).") | |
} | |
} | |
process { | |
return Invoke-Command -ScriptBlock {. $Config.HacToolNet -t xci $args[0]} -ArgumentList (gi -LiteralPath $LiteralPath).FullName | |
} | |
} | |
function Get-FileMetadata { | |
param ( | |
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] | |
[ValidateNotNullOrEmpty()] | |
[Alias('PSPath', 'LP')] | |
[string]$LiteralPath | |
) | |
begin { | |
if (-Not (Test-Path -LiteralPath $LiteralPath)) { | |
throw [System.IO.FileNotFoundException]::new("File not found ($LiteralPath).") | |
} | |
} | |
process { | |
$item = gi -LiteralPath $LiteralPath | |
$tempFile = [System.IO.Path]::GetTempFileName() | |
[void](Start-Process -FilePath $Config.HashMyFiles -NoNewWindow -Wait -PassThru -ArgumentList "/file","`"$($item.Fullname)`"", "/md5", "1", "/sha1", "1", "/sha256", "1", "/sha512", "0", "/sha384", "0", "/crc32", "1", "/stext", $tempFile) | |
} | |
end { | |
return (Get-Content $tempFile) | |
} | |
} | |
function Get-ContentBase64 { | |
param ( | |
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] | |
[ValidateNotNullOrEmpty()] | |
[Alias('PSPath', 'LP')] | |
[string]$LiteralPath | |
) | |
begin { | |
if (-Not (Test-Path -LiteralPath $LiteralPath)) { | |
throw [System.IO.FileNotFoundException]::new("File not found ($LiteralPath).") | |
} | |
} | |
process{ | |
$item = gi -LiteralPath $LiteralPath | |
$bytes = [System.IO.File]::ReadAllBytes($item.FullName) | |
return [System.Convert]::ToBase64String($bytes) | |
} | |
} | |
function New-NXMetadata { | |
param ( | |
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] | |
[ValidateNotNullOrEmpty()] | |
[Alias('PSPath', 'LP')] | |
[string]$LiteralPath | |
) | |
begin { | |
if (-Not (Test-Path -LiteralPath $LiteralPath -PathType Container)) { | |
throw [System.IO.FileNotFoundException]::new("Directory not found or path is not a directory ($LiteralPath).") | |
} | |
$items = gci -LiteralPath $LiteralPath | |
$initialData = $items| ? { $_.Name -like "*Initial Data*"} | |
$cardIdSet = $items| ? { $_.Name -like "*Card ID Set*"} | |
$xci = $items| ? { $_.Extension-match"xci"} | |
$sb = [System.Text.StringBuilder]::new() | |
$activity = "Generating metadata for $($LiteralPath.Name)..." | |
} | |
process{ | |
[void]$sb.AppendLine("[size=150]Game & Cart Info:[/size]") | |
[void]$sb.AppendLine("Game Name: ") | |
[void]$sb.AppendLine("Region: ") | |
[void]$sb.AppendLine("Card Code: LA-H-") | |
[void]$sb.AppendLine("Dump Tool: nxdt_rw_poc v2.0.0 (rewrite-[CHANGEME]-dirty)") | |
[void]$sb.AppendLine() | |
[void]$sb.AppendLine("Barcode: ") | |
[void]$sb.AppendLine("Cart Back Serial Code: ") | |
[void]$sb.AppendLine("Box Serials: ") | |
[void]$sb.AppendLine() | |
[void]$sb.AppendLine("[size=150]Card ID Set:[/size]") | |
[void]$sb.AppendLine("[code]") | |
Write-Progress -Activity $activity -Status "Generating Card ID Set data..." -PercentComplete 20 | |
[void]$sb.AppendJoin([System.Environment]::NewLine, (Get-CardIDSet $cardIdSet)) | |
[void]$sb.AppendLine("[/code]") | |
[void]$sb.AppendLine() | |
[void]$sb.AppendLine("[size=150]Hash Info for Card:[/size]") | |
[void]$sb.AppendLine("[code]") | |
Write-Progress -Activity $activity -Status "Generating XCI hash..." -PercentComplete 30 | |
[void]$sb.AppendJoin([System.Environment]::NewLine, (Get-FileMetadata $xci)) | |
Write-Progress -Activity $activity -Status "Generating initial data hash..." -PercentComplete 40 | |
[void]$sb.AppendJoin([System.Environment]::NewLine, (Get-FileMetadata $initialData)) | |
[void]$sb.AppendLine("[/code]") | |
[void]$sb.AppendLine() | |
[void]$sb.AppendLine("[size=150]Initial Area Base64 Dump:[/size]") | |
[void]$sb.AppendLine("[code]") | |
Write-Progress -Activity $activity -Status "Generating initial data Base64..." -PercentComplete 50 | |
[void]$sb.AppendJoin([System.Environment]::NewLine, (Get-ContentBase64 $initialData)) | |
[void]$sb.AppendLine("[/code]") | |
[void]$sb.AppendLine() | |
[void]$sb.AppendLine("[size=150]Hactoolnet Info:[/size]") | |
[void]$sb.AppendLine("[code]") | |
Write-Progress -Activity $activity -Status "Generating HacToolNet data..." -PercentComplete 70 | |
[void]$sb.AppendJoin([System.Environment]::NewLine, (Get-HacToolNetInfo $xci)) | |
[void]$sb.AppendLine("[/code]") | |
[void]$sb.AppendLine() | |
[void]$sb.AppendLine("[size=150]NX Game Info:[/size]") | |
[void]$sb.AppendLine("[code]") | |
Write-Progress -Activity $activity -Status "Generating NXGameInfo data..." -PercentComplete 90 | |
[void]$sb.AppendJoin([System.Environment]::NewLine, (Get-NXGameInfo $xci)) | |
[void]$sb.AppendLine("[/code]") | |
} | |
end { | |
$output = $sb.ToString() | |
Set-Content -LiteralPath (Join-Path $LiteralPath "submissioninfo.txt") -Value $output | |
Write-Progress -Activity $activity -Completed | |
return $output | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment