injuu-kangoku-re/ysbin-patch.ps1
2026-05-16 15:06:19 -05:00

274 lines
7.6 KiB
PowerShell
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateSet("unpack", "pack")]
[string]$Command
)
$ErrorActionPreference = "Stop"
$Root = $PSScriptRoot
$PacDir = Join-Path $Root "pac"
$Archive = Join-Path $PacDir "ysbin.ypf"
$ExtractedRoot = Join-Path $PacDir "ysbin"
$ExtractedScripts = Join-Path $ExtractedRoot "ysbin"
$YpfExe = Join-Path $Root "ypf\YPF.exe"
$ToolsDir = Join-Path $Root "VNTranslationTools"
$VNTextPatchExe = Join-Path $ToolsDir "VNTextPatch.exe"
$ToolScripts = Join-Path $ToolsDir "ysbin"
$OutputDir = Join-Path $Root "output"
$ResultDir = Join-Path $Root "res"
$BackupArchive = Join-Path $PacDir "ysbin.ypf.bak"
function Require-File {
param([string]$Path)
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
throw "Required file not found: $Path"
}
}
function Require-Dir {
param([string]$Path)
if (-not (Test-Path -LiteralPath $Path -PathType Container)) {
throw "Required folder not found: $Path"
}
}
function Reset-Dir {
param([string]$Path)
if (Test-Path -LiteralPath $Path) {
Remove-Item -LiteralPath $Path -Recurse -Force
}
New-Item -ItemType Directory -Path $Path | Out-Null
}
function Copy-DirectoryContents {
param(
[string]$Source,
[string]$Destination
)
Require-Dir $Source
Reset-Dir $Destination
Get-ChildItem -LiteralPath $Source -Force | Copy-Item -Destination $Destination -Recurse -Force
}
function Resolve-ExePath {
param([Parameter(Mandatory)][string]$Path)
try {
(Resolve-Path -LiteralPath $Path).Path
}
catch {
throw $_.Exception
}
}
function Set-RunAsInvokerCompatLayer {
param([Parameter(Mandatory)][string]$ExeFullPath)
if ([string]::IsNullOrWhiteSpace($ExeFullPath) -or -not (Test-Path -LiteralPath $ExeFullPath -PathType Leaf)) {
return
}
# Many fan tools ship with requireAdministrator for no real reason. RUNASINVOKER suppresses the UAC prompt.
$layersKey = 'HKCU:\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers'
if (-not (Test-Path -LiteralPath $layersKey)) {
New-Item -Path $layersKey -Force | Out-Null
}
try {
Set-ItemProperty -LiteralPath $layersKey -Name $ExeFullPath -Value 'RUNASINVOKER' -Type String -Force
}
catch {
# Non-Windows hosts, locked-down profiles, etc.
}
}
function Run-Tool {
param(
[string]$WorkingDirectory,
[string]$Executable,
[string[]]$Arguments
)
if (Test-Path -LiteralPath $Executable) {
try {
Unblock-File -LiteralPath $Executable -ErrorAction Stop | Out-Null
}
catch {
}
}
$wdPath = Resolve-ExePath $WorkingDirectory
$exePath = Resolve-ExePath $Executable
Set-RunAsInvokerCompatLayer -ExeFullPath $exePath
function Expand-BlockedHint {
param([Parameter(Mandatory)][string]$Path)
@"
Could not launch the executable (SmartScreen / antivirus blocked the child .exe).
Try:
1. Properties Unblock, or: Unblock-File -LiteralPath "$Path"
2. SmartScreen: More info Run anyway
3. If you use Cursors terminal: open Windows Terminal, cd here, run again (sandboxed shells block some tools).
"@
}
function Interpret-DirectNativeExitCode {
# Calling tools with & frequently leaves LASTEXITCODE empty even on success — don't treat blank as failure.
$gv = Get-Variable -Name LASTEXITCODE -ErrorAction SilentlyContinue
if ($null -eq $gv) {
return 0
}
$tokRaw = $gv.Value
$tok = if ($null -eq $tokRaw) { '' } else { "$tokRaw".Trim() }
if ([string]::IsNullOrWhiteSpace($tok)) {
return 0
}
$parsed = 0
if (-not [int]::TryParse($tok, [ref]$parsed)) {
Write-Warning "ysbin-patch: non-integer LASTEXITCODE '$tok' — assuming success."
return 0
}
return $parsed
}
Push-Location $wdPath
try {
try {
& $exePath @Arguments
}
catch {
$raw = $_.Exception.Message
if ($raw -match 'canceled by the user|OPERATION_ABORTED|The operation has been aborted|800704C7') {
$blockMsg = (Expand-BlockedHint -Path $exePath).TrimEnd()
throw "${blockMsg}`n`nInner: $raw"
}
throw $_
}
$exitCodeDirect = Interpret-DirectNativeExitCode
if ($exitCodeDirect -ne 0) {
throw "Command failed with exit code ${exitCodeDirect}: $exePath $($Arguments -join ' ')"
}
}
finally {
Pop-Location
}
}
function Restore-VanillaArchive {
Require-File $BackupArchive
Copy-Item -LiteralPath $BackupArchive -Destination $Archive -Force
Write-Host "Copied ysbin.ypf.bak -> pac\ysbin.ypf"
}
function Apply-SpacingFix {
$fix = Join-Path $PacDir "yst00042.ybn"
if (-not (Test-Path -LiteralPath $fix)) {
return
}
Require-Dir $ExtractedScripts
Copy-Item -LiteralPath $fix -Destination (Join-Path $ExtractedScripts "yst00042.ybn") -Force
Write-Host "Applied pac\yst00042.ybn (spacing fix)"
}
function Unpack-Archive {
Require-File $YpfExe
Require-File $Archive
Write-Host "Unpacking pac\ysbin.ypf..."
if (Test-Path -LiteralPath $ExtractedRoot) {
Remove-Item -LiteralPath $ExtractedRoot -Recurse -Force
}
Run-Tool -WorkingDirectory $PacDir -Executable $YpfExe -Arguments @("-e", "ysbin.ypf")
Require-Dir $ExtractedScripts
}
function Extract-Json {
Require-File $VNTextPatchExe
Copy-DirectoryContents -Source $ExtractedScripts -Destination $ToolScripts
if (-not (Test-Path -LiteralPath $OutputDir)) {
New-Item -ItemType Directory -Path $OutputDir | Out-Null
}
Write-Host "Extracting JSON to output..."
Run-Tool -WorkingDirectory $ToolsDir -Executable $VNTextPatchExe -Arguments @("extractlocal", "ysbin", $OutputDir)
}
function Insert-Json {
Require-File $VNTextPatchExe
Require-Dir $ToolScripts
Require-Dir $OutputDir
Reset-Dir $ResultDir
Write-Host "Inserting JSON into scripts..."
Run-Tool -WorkingDirectory $ToolsDir -Executable $VNTextPatchExe -Arguments @("insertlocal", "ysbin", $OutputDir, $ResultDir)
}
function Merge-ResultIntoExtractedScripts {
Require-Dir $ResultDir
Write-Host "Merging patched files from res into pac\ysbin\ysbin..."
Get-ChildItem -LiteralPath $ResultDir -Force | Copy-Item -Destination $ExtractedScripts -Recurse -Force
}
function Pack-Ypf {
Require-File $YpfExe
Require-Dir $ExtractedScripts
if ((Test-Path -LiteralPath $Archive) -and -not (Test-Path -LiteralPath $BackupArchive)) {
Copy-Item -LiteralPath $Archive -Destination $BackupArchive
Write-Host "Backed up original archive to pac\ysbin.ypf.bak"
}
Write-Host "Packing pac\ysbin into pac\ysbin.ypf..."
Run-Tool -WorkingDirectory $PacDir -Executable $YpfExe -Arguments @("-c", "ysbin", "-v", "500")
}
function Invoke-PackPipeline {
Require-File $VNTextPatchExe
Require-Dir $OutputDir
Restore-VanillaArchive
Unpack-Archive
Apply-SpacingFix
Copy-DirectoryContents -Source $ExtractedScripts -Destination $ToolScripts
Insert-Json
Merge-ResultIntoExtractedScripts
Pack-Ypf
}
switch ($Command) {
"unpack" {
Restore-VanillaArchive
Unpack-Archive
Apply-SpacingFix
Extract-Json
Write-Host "Done. pac\ysbin.ypf -> pac\ysbin\ ; strings -> output\ (*.json)."
}
"pack" {
Invoke-PackPipeline
Write-Host "Done. output\ JSON -> scripts/ybn in pac\ysbin\ ; -> pac\ysbin.ypf."
}
}