Files
win-troubleshooting-notes-p…/ori-wotw-troubleshooting/补丁包/ori-wwise-affinity-fix-v1.0.0/Ori-AudioFix.ps1
T

113 lines
4.8 KiB
PowerShell
Raw 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.
#requires -Version 7.0
[CmdletBinding()]
param(
[ValidateSet('Check', 'Install', 'Restore')]
[string]$Action = 'Check',
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string[]]$GameDirectory
)
$ErrorActionPreference = 'Stop'
$originalHash = '8F90A4A3856540CB97D03CA07B4BB10B7A08F7B4AB3C524BE2BEC1AFDD29FECA'
$patchedHash = '62B2079A988D23EB251D4E83366AC04068A6F47E0D38EFE92A76DF022826F9F0'
$offset = 0x115F0
$originalCode = [Convert]::FromHexString('4885C97403895104C3CCCCCCCCCCCCCC')
$patchedCode = [Convert]::FromHexString('4885C97407C7410400000000C3CCCCCC')
function Get-BytesHash([byte[]]$Bytes) {
[Convert]::ToHexString([Security.Cryptography.SHA256]::HashData($Bytes))
}
if ($Action -ne 'Check' -and (Get-Process -Name 'oriwotw' -ErrorAction SilentlyContinue)) {
throw '请先退出所有奥日 2 游戏窗口,再安装或还原补丁。'
}
# Preflight every selected directory before any mutation. Unknown builds,
# unrelated modifications and conflicting backups are never overwritten.
$plans = foreach ($directory in $GameDirectory) {
$root = (Resolve-Path -LiteralPath $directory).Path
$target = Join-Path $root 'oriwotw_Data\Plugins\AkSoundEngine.dll'
$backup = $target + '.before-ori-affinity-fix'
$bytes = [IO.File]::ReadAllBytes($target)
$hash = Get-BytesHash $bytes
if ($hash -notin @($originalHash, $patchedHash)) {
throw "文件版本或内容不匹配,未修改:$target;SHA256=$hash"
}
if (Test-Path -LiteralPath $backup) {
if ((Get-FileHash -LiteralPath $backup -Algorithm SHA256).Hash -ne $originalHash) {
throw "现有备份不匹配,未覆盖:$backup"
}
}
if ($Action -eq 'Restore' -and $hash -eq $patchedHash -and -not (Test-Path -LiteralPath $backup)) {
throw "找不到经过校验的原文件备份,无法还原:$backup"
}
if ($hash -eq $originalHash) {
for ($i = 0; $i -lt $originalCode.Length; $i++) {
if ($bytes[$offset + $i] -ne $originalCode[$i]) { throw '原始指令校验失败。' }
}
$candidate = [byte[]]$bytes.Clone()
[Array]::Copy($patchedCode, 0, $candidate, $offset, $patchedCode.Length)
if ((Get-BytesHash $candidate) -ne $patchedHash) { throw '补丁结果校验失败。' }
} else {
$candidate = $bytes
}
[pscustomobject]@{ Root=$root; Target=$target; Backup=$backup; Hash=$hash; Candidate=$candidate }
}
foreach ($plan in $plans) {
if ($Action -eq 'Check') {
[pscustomobject]@{
Directory=$plan.Root
State=if ($plan.Hash -eq $patchedHash) { '已安装补丁' } else { '原版,符合补丁要求' }
SHA256=$plan.Hash
BackupExists=(Test-Path -LiteralPath $plan.Backup)
}
continue
}
if ($Action -eq 'Install' -and $plan.Hash -eq $patchedHash) {
Write-Host "已安装,无需重复修改:$($plan.Root)"
continue
}
if ($Action -eq 'Restore' -and $plan.Hash -eq $originalHash) {
Write-Host "已经是原文件:$($plan.Root)"
continue
}
if ($Action -eq 'Install') {
if (-not (Test-Path -LiteralPath $plan.Backup)) {
[IO.File]::Copy($plan.Target, $plan.Backup, $false)
}
if ((Get-FileHash -LiteralPath $plan.Backup -Algorithm SHA256).Hash -ne $originalHash) {
throw '备份验证失败;未覆盖游戏 DLL。'
}
$newBytes = $plan.Candidate
$expected = $patchedHash
} else {
$newBytes = [IO.File]::ReadAllBytes($plan.Backup)
$expected = $originalHash
}
# Detect changes made by another program since preflight.
if ((Get-FileHash -LiteralPath $plan.Target -Algorithm SHA256).Hash -ne $plan.Hash) {
throw "检查后文件发生变化,停止修改:$($plan.Target)"
}
if (Get-Process -Name 'oriwotw' -ErrorAction SilentlyContinue) {
throw '游戏刚刚启动,已停止修改;请先退出游戏。'
}
$staging = $plan.Target + '.ori-fix-' + [Guid]::NewGuid().ToString('N') + '.tmp'
try {
$stream = [IO.File]::Open($staging, [IO.FileMode]::CreateNew, [IO.FileAccess]::Write, [IO.FileShare]::None)
try { $stream.Write($newBytes); $stream.Flush($true) } finally { $stream.Dispose() }
if ((Get-FileHash -LiteralPath $staging -Algorithm SHA256).Hash -ne $expected) {
throw '临时文件验证失败,未覆盖游戏 DLL。'
}
[IO.File]::Move($staging, $plan.Target, $true)
if ((Get-FileHash -LiteralPath $plan.Target -Algorithm SHA256).Hash -ne $expected) {
throw '写入后的校验失败,请保留备份并停止启动游戏。'
}
} finally {
if (Test-Path -LiteralPath $staging) { Remove-Item -LiteralPath $staging }
}
Write-Host "${Action} 成功:$($plan.Target)"
Write-Host "原文件备份:$($plan.Backup)"
}