@echo off
rem ===========================================================================
rem  MSHvsSF four-player Cross Fever msh-four-human-background-03
rem  *** EXPERIMENTAL PREVIEW -- see included scope and evidence ***
rem  Generated from a patch spec by gen_cmd.py -- do not hand-edit.
rem  Required base: Verified stock MSHvsSF USA 970827 (mshvsfu). Drag your mshvsfu.zip onto this file, or run:
rem      mshvsf-cross-four-human-preview.cmd "C:\path\to\mshvsfu.zip"
rem  This installer contains patch deltas and integrity metadata, not a ROM.
rem  It makes no network requests, never overwrites the clean input, and
rem  refuses patched/noncanonical sets.
rem ===========================================================================
setlocal
set "ROMPATH=%~f1"
set "SELFPATH=%~f0"
where powershell.exe >nul 2>&1
if errorlevel 1 (
  echo.
  echo   ERROR: Windows PowerShell was not found.
  echo.
  exit /b 1
)
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "$t=[IO.File]::ReadAllText($env:SELFPATH);$m='#=PS'+'BEGIN=#';$i=$t.IndexOf($m);if($i -lt 0){Write-Host 'ERROR: installer marker missing.' -ForegroundColor Red;exit 9};& ([ScriptBlock]::Create($t.Substring($i+$m.Length)))"
set "RC=%errorlevel%"
endlocal & exit /b %RC%

#=PSBEGIN=#
$ErrorActionPreference = 'Stop'

function Pause-IfConsole {
    if ($Host.Name -eq 'ConsoleHost' -and -not $env:MVSC_DHC_NOPAUSE) {
        try { Read-Host '  Press Enter to close' | Out-Null } catch {}
    }
}

function Fail([string]$Message, [int]$Code = 1) {
    Write-Host ''
    Write-Host "  ERROR: $Message" -ForegroundColor Red
    Write-Host ''
    Pause-IfConsole
    exit $Code
}

function ConvertFrom-Hex([string]$Hex) {
    if (($Hex.Length % 2) -ne 0) { Fail 'internal hex string has odd length.' 8 }
    $Bytes = New-Object byte[] ($Hex.Length / 2)
    for ($i = 0; $i -lt $Bytes.Length; $i++) {
        $Bytes[$i] = [Convert]::ToByte($Hex.Substring($i * 2, 2), 16)
    }
    return ,$Bytes
}

function Get-Sha256([byte[]]$Bytes) {
    $Hash = [System.Security.Cryptography.SHA256]::Create()
    try {
        return (([BitConverter]::ToString($Hash.ComputeHash($Bytes))).Replace('-', '').ToLowerInvariant())
    } finally {
        $Hash.Dispose()
    }
}

function Test-Bytes([byte[]]$Buffer, [int]$Offset, [byte[]]$Expected) {
    if ($Offset -lt 0 -or $Offset + $Expected.Length -gt $Buffer.Length) { return $false }
    for ($i = 0; $i -lt $Expected.Length; $i++) {
        if ($Buffer[$Offset + $i] -ne $Expected[$i]) { return $false }
    }
    return $true
}

function Read-ZipMembers([string]$Path) {
    $Entries = New-Object 'System.Collections.Generic.Dictionary[string,byte[]]'
    $Metadata = New-Object 'System.Collections.Generic.Dictionary[string,object]'
    $Order = New-Object 'System.Collections.Generic.List[string]'
    try { $Zip = [System.IO.Compression.ZipFile]::OpenRead($Path) }
    catch { throw "not a readable ZIP archive: $Path" }
    try {
        foreach ($Entry in $Zip.Entries) {
            if ($Entries.ContainsKey($Entry.FullName)) {
                throw "archive has a duplicate member named $($Entry.FullName)."
            }
            $Memory = New-Object System.IO.MemoryStream
            $Stream = $Entry.Open()
            try { $Stream.CopyTo($Memory) } finally { $Stream.Dispose() }
            $Entries.Add($Entry.FullName, $Memory.ToArray())
            $Metadata.Add($Entry.FullName, [pscustomobject]@{
                LastWriteTime = $Entry.LastWriteTime
                ExternalAttributes = $Entry.ExternalAttributes
            })
            [void]$Order.Add($Entry.FullName)
            $Memory.Dispose()
        }
    } finally {
        $Zip.Dispose()
    }
    return [pscustomobject]@{ Entries=$Entries; Metadata=$Metadata; Order=$Order }
}

Write-Host ''
Write-Host '  MSHvsSF four-player Cross Fever msh-four-human-background-03'
Write-Host '  ================================================================'
    Write-Host '  *** EXPERIMENTAL PREVIEW -- not an accepted stable release. ***' -ForegroundColor Yellow
Write-Host '  The clean input is only read. A new patched ZIP is written.'

$Source = $env:ROMPATH
if ([string]::IsNullOrWhiteSpace($Source)) {
    $Candidates = @(
        (Join-Path ([Environment]::CurrentDirectory) 'mshvsfu.zip'),
        (Join-Path (Split-Path -Parent $env:SELFPATH) 'mshvsfu.zip')
    ) | Select-Object -Unique
    $Source = $Candidates | Where-Object {
        Test-Path -LiteralPath $_ -PathType Leaf
    } | Select-Object -First 1
}
if ([string]::IsNullOrWhiteSpace($Source)) {
    Fail 'drag the required mshvsfu.zip onto this CMD or put it beside this file.'
}
try { $Source = (Resolve-Path -LiteralPath $Source -ErrorAction Stop).ProviderPath }
catch { Fail "file not found: $Source" }
if (-not (Test-Path -LiteralPath $Source -PathType Leaf)) {
    Fail "not a file: $Source"
}

Add-Type -AssemblyName System.IO.Compression -ErrorAction SilentlyContinue
Add-Type -AssemblyName System.IO.Compression.FileSystem -ErrorAction SilentlyContinue

$Vanilla = @(
    @{ Name='mvsu.03g'; Size=524288; Sha256='40273bbd99c8458d9e14d53e7a28b3ff6c8da557f600619e272138ad6136a771' }
    @{ Name='mvsu.04g'; Size=524288; Sha256='b9ff71cf7fe7d05d09127e05d33789da584a38c1100904de8a297d839fd77b51' }
    @{ Name='mvs.05d'; Size=524288; Sha256='d5e78638bd0fa5210a9fbecbe5d378fe024094f0a5ad0550515932e3979698d1' }
    @{ Name='mvs.06a'; Size=524288; Sha256='4fa6c17b5a63f031854865c0777f7f3ef16124101506c98298d3dbaa756730a7' }
    @{ Name='mvs.07b'; Size=524288; Sha256='c2375e11acd8a726e7f92d766322228052011a3738f76024fcdda8b1bba9711d' }
    @{ Name='mvs.08a'; Size=524288; Sha256='d00efcfbeed2f4302b1172cc4bbd78b55135b7f7f15e776fe3cb820a8d45668a' }
    @{ Name='mvs.09b'; Size=524288; Sha256='c262d7ed4e01b033435c1e83804e007251ac3cea2b00e4d6d5f792cd8394b42a' }
    @{ Name='mvs.10b'; Size=524288; Sha256='e2605d7c744565615eecad8ae6852fe96f2eec8478e4f8eaeebc79f184ad446e' }
    @{ Name='mvs.13m'; Size=4194304; Sha256='fd4ed6d5474fcdccbfd9bdd238cacba132e71f7521b5adc58166a5b94ce52e31' }
    @{ Name='mvs.15m'; Size=4194304; Sha256='5709e9790ed9719a0633aedd4641829012c44aa37c44dccb1f8489208c4cb2cf' }
    @{ Name='mvs.17m'; Size=4194304; Sha256='345f5eb13765e1c703481c87045820ce0e0c5a2e8d502c3e1843fb7b672718f3' }
    @{ Name='mvs.19m'; Size=4194304; Sha256='8b6ad4f39f90cec2380f8dec09aab57e5d47833e9e5b282d2384a969079daf36' }
    @{ Name='mvs.14m'; Size=4194304; Sha256='0ac719e09a64cfee86017c20a6e4b0f6575a91fc7b2859ddf573a15a19dfd3f6' }
    @{ Name='mvs.16m'; Size=4194304; Sha256='d7076dab85ed83c8c77723ec00e30982079ab51c77bb06b06bddf1ff60dfbf46' }
    @{ Name='mvs.18m'; Size=4194304; Sha256='8e706ff8e12c250a2f830502fd03c6186651defc0c7a0236a4959ef7a0e8fda3' }
    @{ Name='mvs.20m'; Size=4194304; Sha256='615f278514851ed5e0da6ff8fb103c2d418735a49eacf9a38ef90551c0e5aac4' }
    @{ Name='mvs.01'; Size=131072; Sha256='2914e05c2266350de0ef28af5bb99690a80933bb76800fd38e27d1ee622ad665' }
    @{ Name='mvs.02'; Size=131072; Sha256='9939e61cf5dd99477fdf4cb1b505516da8b68512da4f10aa7680eae8d6b5abe7' }
    @{ Name='mvs.11m'; Size=4194304; Sha256='7c36217c0cec1075d2a5dbd1bdc310fd79c8ac3b3795a586d6aad0bc04668d85' }
    @{ Name='mvs.12m'; Size=4194304; Sha256='332edc4527fc1a7aa307a6c5cf824e423462607d853ce6665859c82ab5a7a4a3' }
    @{ Name='mshvsfu.key'; Size=20; Sha256='838fc71e642c4f9a84e6c2bf9fbec202625683df9c00b9c3674941c756586b48' }
)
$VanillaLookup = New-Object 'System.Collections.Generic.Dictionary[string,object]'
foreach ($Record in $Vanilla) {
    $VanillaLookup.Add([string]$Record.Name, $Record)
}

try { $Read = Read-ZipMembers $Source }
catch { Fail $_.Exception.Message }
$Entries = $Read.Entries
$Metadata = $Read.Metadata
$Order = $Read.Order

$OptionalMembers = @('mshvsfu.key')
$Required = @($Vanilla | Where-Object { $OptionalMembers -notcontains [string]$_.Name })
$PresentOptional = @($OptionalMembers | Where-Object { $Entries.ContainsKey($_) })
$ExpectedCount = $Required.Count + $PresentOptional.Count
if ($Entries.Count -ne $ExpectedCount) {
    Fail "wrong archive member count: got $($Entries.Count), expected $($Required.Count) (FBNeo/Fightcade set without $($OptionalMembers -join ', ')) or $($Vanilla.Count) (MAME set)."
}
for ($i = 0; $i -lt $Order.Count; $i++) {
    $Name = [string]$Order[$i]
    if (-not $VanillaLookup.ContainsKey($Name)) {
        Fail "archive contains unexpected member '$Name'."
    }
}
foreach ($Record in $Vanilla) {
    $Name = [string]$Record.Name
    if (-not $Entries.ContainsKey($Name)) {
        if ($OptionalMembers -contains $Name) { continue }
        Fail "required member '$Name' is missing."
    }
    $Bytes = [byte[]]$Entries[$Name]
    if ($Bytes.Length -ne [int]$Record.Size) { Fail "$Name size is $($Bytes.Length), expected $($Record.Size)." }
    $Got = Get-Sha256 $Bytes
    if ($Got -ne [string]$Record.Sha256) {
        Fail "$Name SHA-256 mismatch. Required base: Verified stock MSHvsSF USA 970827 (mshvsfu). Patched and wrong-revision sets are rejected."
    }
}

Write-Host ''
Write-Host "  Input : $Source"
Write-Host '  Base  : Verified stock MSHvsSF USA 970827 (mshvsfu)'
Write-Host "  Set   : $($Entries.Count) exact members present"

$Patches = @(
    @{ File='mvsu.03g'; Offset=0x000D92; After='80184afc4de8' }
    @{ File='mvsu.03g'; Offset=0x005DF6; After='8b14665cc610' }
    @{ File='mvsu.03g'; Offset=0x00BCCC; After='ed5d902d3a0d' }
    @{ File='mvsu.03g'; Offset=0x00C15C; After='ec6c9f146e2e' }
    @{ File='mvsu.03g'; Offset=0x00DA34; After='e75c8ac3' }
    @{ File='mvsu.03g'; Offset=0x010420; After='e93cb5027c24' }
    @{ File='mvsu.03g'; Offset=0x0117F4; After='d68e572683000d0df2241082f6ba69a3' }
    @{ File='mvsu.03g'; Offset=0x01296E; After='926e4bf0d493e42a' }
    @{ File='mvsu.03g'; Offset=0x0129B0; After='dd4a53ee9cc383da' }
    @{ File='mvsu.03g'; Offset=0x0129DE; After='bb872c3f751e62e2' }
    @{ File='mvsu.03g'; Offset=0x013630; After='a59152b386288997' }
    @{ File='mvsu.03g'; Offset=0x01364A; After='b82d63ec0743320f' }
    @{ File='mvsu.03g'; Offset=0x015EBE; After='a14a65d3a060' }
    @{ File='mvsu.03g'; Offset=0x01992C; After='14c1eada41e9bc9e346b' }
    @{ File='mvsu.03g'; Offset=0x021404; After='3ce2672e4c78' }
    @{ File='mvsu.04g'; Offset=0x02D978; After='4f81' }
    @{ File='mvs.10b'; Offset=0x071400; After='0e208004' }
    @{ File='mvs.10b'; Offset=0x071405; After='00003888e088e44002030000611c05002f00702e10020040d0f941' }
    @{ File='mvs.10b'; Offset=0x071421; After='002a4cc0d01f20f94e01000418e7488070003600344ae24ae9f94180000140c2d040020100c09000701010004600324102800049e340027f0041803932800020404146033442060800010504674000000242580105046740000004df4c0e01754e390c0800' }
    @{ File='mvs.10b'; Offset=0x071487; After='000048006646002e4a030000673e0000702e1002003901' }
    @{ File='mvs.10b'; Offset=0x07149F; After='00384800672e00164a006728006e4a5002006720006e206402284a030000671400104a00670e00684a5002006706000170754e0070754e2e4a610200670a000061a2' }
    @{ File='mvs.10b'; Offset=0x0714E2; After='00670800f94e00008ac1f94e000062c1e748f0f00061560000615a01004a0667df4c0f0f754edf4c0f0f006174' }
    @{ File='mvs.10b'; Offset=0x071510; After='00672e002e0c4000a000006722007c1d03005402b94e0100c45e2e4254026e4252026e2064022842540268425202754e2e4a61020066f8' }
    @{ File='mvs.10b'; Offset=0x071548; After='f94e0100c45e390c0800' }
    @{ File='mvs.10b'; Offset=0x071553; After='0000480066fc002e4a03000067f4002e4a61020066ec0000702e1002003901' }
    @{ File='mvs.10b'; Offset=0x071573; After='0038480066dc000e208004' }
    @{ File='mvs.10b'; Offset=0x07157F; After='00003888e088e440020300f943' }
    @{ File='mvs.10b'; Offset=0x07158D; After='003a48c0d200721112010cc0000067b800013442023f00046711530460114200724102c0002e34c60042020f00420c04000666bc125000754e420c05000c66410c40000666bc129000754e420c010000667600410c800000666e002e34c00042024004420c400400665e002e34c400420240040067520011422e4a0a02006648002e4a0702006640002e0c0400a400006436002e0c0200540200652c006e206402684a500200672000104a00661a0000702e1002003901' }
    @{ File='mvs.10b'; Offset=0x071645; After='00504800660a00bc12c00000616000754e0e208004' }
    @{ File='mvs.10b'; Offset=0x07165B; After='00003888e088e440020300f943' }
    @{ File='mvs.10b'; Offset=0x071669; After='003a48c0d2110cc0003a662e30c000400240042e676e02bffbc0006e02bffbc2006e02bffbc4006e02bffbc6006e02bffbc8006e02bffbca006e02bffbd0000170754e11420070754e00722e125402fcc2c0002e3452024ae242d200702e100200f901' }
    @{ File='mvs.10b'; Offset=0x0716CD; After='00384840d0f943' }
    @{ File='mvs.10b'; Offset=0x0716D5; After='003448813300006e4252022e4254026842520228425402bc1001007c11010001006e114b004b006e11a300a3007c310200040068420600a84208006811a000a1007c114000a0007c1104000b0228420602284209022e4206022e4209026e02bffbc4006e02bffbca0000617805754e00613cfd006712002e420b022e420c020070f94e0100564df94e0100103b390c0800' }
    @{ File='mvs.10b'; Offset=0x071767; After='0000481c67b942' }
    @{ File='mvs.10b'; Offset=0x07176F; After='003448b942' }
    @{ File='mvs.10b'; Offset=0x071775; After='0038487942' }
    @{ File='mvs.10b'; Offset=0x07177B; After='003c48390c0a00' }
    @{ File='mvs.10b'; Offset=0x071783; After='0000480664f94e01003836754e00702e1002003901' }
    @{ File='mvs.10b'; Offset=0x071799; After='003848006722000061e0fc0267754e00702e100200b901' }
    @{ File='mvs.10b'; Offset=0x0717B1; After='00384840d0f941' }
    @{ File='mvs.10b'; Offset=0x0717B9; After='003448704200002e1002003901' }
    @{ File='mvs.10b'; Offset=0x0717C7; After='0025480666f94e01005436754eb94e0100340ee748e0f0390a0100' }
    @{ File='mvs.10b'; Offset=0x0717E3; After='003948394a' }
    @{ File='mvs.10b'; Offset=0x0717E9; After='00394800672a00f945' }
    @{ File='mvs.10b'; Offset=0x0717F3; After='00344800763907' }
    @{ File='mvs.10b'; Offset=0x0717FB; After='0038480e67524a046752530666b907' }
    @{ File='mvs.10b'; Offset=0x07180B; After='0038488a544352430c0200e065df4c0f07f94e01002604e748808000615afc08676e4252022e425402df4c01016e2064026e3152025202f94e01003699e7488080006134fcdf4c0101754e0061f0' }
    @{ File='mvs.10b'; Offset=0x07185A; After='0267754e0074b94e0600149ef94e010076290061da' }
    @{ File='mvs.10b'; Offset=0x071870; After='0267754e0074b94e0600149ef94e0100b8290061c4' }
    @{ File='mvs.10b'; Offset=0x071886; After='0267754e0074b94e0600149ef94e0100e629e74880400032410240041066f941' }
    @{ File='mvs.10b'; Offset=0x0718A7; After='003a48c3d0100cc00002661042df4c0201754ee748003f2d422ecc2d4234cc2d4236cc791b800021402fcc2d462fcc0070006154000038017000614c00003a027000614400003c037000613c00003e790c0400' }
    @{ File='mvs.10b'; Offset=0x0718FB; After='0004491866390c0100' }
    @{ File='mvs.10b'; Offset=0x071905; After='00834902660638390c0100' }
    @{ File='mvs.10b'; Offset=0x071911; After='00a3490266073a443b2acc453b2ccc6d1b2ecc36ccdf4cfc00f84ef00de748807000360061f8fa00615e' }
    @{ File='mvs.10b'; Offset=0x07193C; After='0072390c0800' }
    @{ File='mvs.10b'; Offset=0x071943; After='0000481666394a' }
    @{ File='mvs.10b'; Offset=0x07194B; After='0000490e673912' }
    @{ File='mvs.10b'; Offset=0x071953; After='000149410203000267017239080700' }
    @{ File='mvs.10b'; Offset=0x071963; After='003f481266fc130f00' }
    @{ File='mvs.10b'; Offset=0x07196D; After='003e48fc138000' }
    @{ File='mvs.10b'; Offset=0x071975; After='003f4816603914' }
    @{ File='mvs.10b'; Offset=0x07197D; After='003f484202010041b4166739000f00' }
    @{ File='mvs.10b'; Offset=0x07198D; After='003e483902fe00' }
    @{ File='mvs.10b'; Offset=0x071995; After='003f483983' }
    @{ File='mvs.10b'; Offset=0x07199B; After='003f480032410240043907' }
    @{ File='mvs.10b'; Offset=0x0719A7; After='003e480c67414a3e66b907' }
    @{ File='mvs.10b'; Offset=0x0719B3; After='003e483a60410c40043466394a' }
    @{ File='mvs.10b'; Offset=0x0719C1; After='00774c2c6739080000' }
    @{ File='mvs.10b'; Offset=0x0719CB; After='003f480e670334420201003905' }
    @{ File='mvs.10b'; Offset=0x0719D9; After='0001491466f907' }
    @{ File='mvs.10b'; Offset=0x0719E1; After='003e48033442020100ed052ecc4002bffbdf4c0e01754ee740e748fe' }
    @{ File='mvs.10b'; Offset=0x0719FE; After='393e9200245f393c9200265f470c30' }
    @{ File='mvs.10b'; Offset=0x071A0E; After='0c67393e9200745f393c9200765ff9419200205f27709842c851fc' }
    @{ File='mvs.10b'; Offset=0x071A2A; After='470c30' }
    @{ File='mvs.10b'; Offset=0x071A2E; After='0c66c7339200245fc6339200265f390c0800' }
    @{ File='mvs.10b'; Offset=0x071A41; After='0000480066ae00007e390f' }
    @{ File='mvs.10b'; Offset=0x071A4D; After='00384800679800073844d8f943' }
    @{ File='mvs.10b'; Offset=0x071A5B; After='003448313a004000678600450c400204633c3a40024de4454445069000f9419200205f3c305000474a0867e84150003c3000013c32d000b84e146a3c3430' }
    @{ File='mvs.10b'; Offset=0x071A9A; After='3c36020a90480f00e84108004006100010782276474a086740068000f0780276087c3c344f' }
    @{ File='mvs.10b'; Offset=0x071AC0; After='450c10000e623c342d' }
    @{ File='mvs.10b'; Offset=0x071ACA; After='454a06673c343f' }
    @{ File='mvs.10b'; Offset=0x071AD2; After='45d490480f00e841080044d045041000026a007ace51d4' }
    @{ File='mvs.10b'; Offset=0x071AEA; After='4752470c0200006658' }
    @{ File='mvs.10b'; Offset=0x071AF4; After='df4c' }
    @{ File='mvs.10b'; Offset=0x071AF7; After='7fdf442e0a01001400754e790c30' }
    @{ File='mvs.10b'; Offset=0x071B06; After='9200245f0a67790c30' }
    @{ File='mvs.10b'; Offset=0x071B10; After='9200745f1c66f94391004040f9459200c05f1061f943920040e0f9459200e05f0261754efa4762010f70007619321b3441b54102' }
    @{ File='mvs.10b'; Offset=0x071B45; After='0f4186c851f2' }
    @{ File='mvs.10b'; Offset=0x071B4C; After='e943e0' }
    @{ File='mvs.10b'; Offset=0x071B50; After='434a16660f701132410200f01a344202' }
    @{ File='mvs.10b'; Offset=0x071B61; After='0f4282c132c851ee' }
    @{ File='mvs.10b'; Offset=0x071B6A; After='754ee740e748f0' }
    @{ File='mvs.10b'; Offset=0x071B72; After='0061cc00074a0066b400006184' }
    @{ File='mvs.10b'; Offset=0x071B80; After='b94a9200205f066679429200245f390c0800' }
    @{ File='mvs.10b'; Offset=0x071B93; After='00004800669600394a' }
    @{ File='mvs.10b'; Offset=0x071B9D; After='00384800678c00fcb97000589f00627400f94170000080ccb116642830060040021f00400c020000675a00e8410800e660f94391004040f945920040e0f9419200c05ffa47b6000770d12052211c001122810200f000f09382c1221b22810000f000f0c124c851e2' }
    @{ File='mvs.10b'; Offset=0x071C06; After='f9419200205f1370d84c0600814a0467c128c228c851f2' }
    @{ File='mvs.10b'; Offset=0x071C1E; After='0e60f9419200205f27709842c851fc' }
    @{ File='mvs.10b'; Offset=0x071C2E; After='df4c' }
    @{ File='mvs.10b'; Offset=0x071C31; After='0fdf44fc2800800080f94e02000a14007e390c0800' }
    @{ File='mvs.10b'; Offset=0x071C47; After='0000480866394a' }
    @{ File='mvs.10b'; Offset=0x071C4F; After='0038484266790c30' }
    @{ File='mvs.10b'; Offset=0x071C58; After='9200245f3866f94170000080ccb114642830060040021f00400c02002067e8410800e86039309200265f1267400c0200026302704053c0339200265f017e754e6f0f' }
    @{ File='mvs.10b'; Offset=0x071C9B; After='0f88084404df0fbe0f9d0f7c0fc30f000ff000' }
    @{ File='mvs.10b'; Offset=0x071CAF; After='05df02bf0000070200e740e748fe' }
    @{ File='mvs.10b'; Offset=0x071CBE; After='394a' }
    @{ File='mvs.10b'; Offset=0x071CC1; After='00224c0e662e3f0c02b94e0100fa2c5f3d0c0239000200' }
    @{ File='mvs.10b'; Offset=0x071CD9; After='00194cdf4c' }
    @{ File='mvs.10b'; Offset=0x071CDF; After='7fdf44754ee740390c0800' }
    @{ File='mvs.10b'; Offset=0x071CEB; After='0000481e66394a' }
    @{ File='mvs.10b'; Offset=0x071CF3; After='0038481667df44002f00000200401b19ccdf4c0100f94e0000f2bcdf44401b19cc0666f94e0000d2bcf94e0000f2bc' }
    @{ File='mvs.13m'; Offset=0x3FCC5F; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCC67; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCC6B; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCC6F; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCC77; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCC9F; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCCA7; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCCAB; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCCAF; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCCB7; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCCDF; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCCE7; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCCEB; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCCEF; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCCF7; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCD1F; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCD27; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCD2B; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCD2F; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCD37; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCD4A; After='cccc' }
    @{ File='mvs.13m'; Offset=0x3FCD4E; After='cccc' }
    @{ File='mvs.13m'; Offset=0x3FCD53; After='cc' }
    @{ File='mvs.13m'; Offset=0x3FCD57; After='cc' }
    @{ File='mvs.13m'; Offset=0x3FCD5F; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCD67; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCD6B; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCD6F; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCD77; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCD8A; After='7f7f' }
    @{ File='mvs.13m'; Offset=0x3FCD8E; After='0f0f' }
    @{ File='mvs.13m'; Offset=0x3FCD93; After='7f' }
    @{ File='mvs.13m'; Offset=0x3FCD97; After='07' }
    @{ File='mvs.13m'; Offset=0x3FCD9F; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCDA7; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCDAB; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCDAF; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCDB7; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCDDF; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCDE7; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCDEB; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCDEF; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCDF7; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCE1F; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCE27; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCE2B; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCE2F; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCE37; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCE5F; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCE67; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCE6B; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCE6F; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCE77; After='00' }
    @{ File='mvs.13m'; Offset=0x3FCE9F; After='3f' }
    @{ File='mvs.13m'; Offset=0x3FCEA3; After='9f' }
    @{ File='mvs.13m'; Offset=0x3FCEA7; After='9f' }
    @{ File='mvs.13m'; Offset=0x3FCEAB; After='9f' }
    @{ File='mvs.13m'; Offset=0x3FCEAF; After='9f' }
    @{ File='mvs.13m'; Offset=0x3FCEB3; After='9f' }
    @{ File='mvs.13m'; Offset=0x3FCEB7; After='3f' }
    @{ File='mvs.13m'; Offset=0x3FD226; After='fe' }
    @{ File='mvs.13m'; Offset=0x3FD22A; After='fe' }
    @{ File='mvs.13m'; Offset=0x3FD22E; After='fe' }
    @{ File='mvs.13m'; Offset=0x3FD266; After='fc' }
    @{ File='mvs.13m'; Offset=0x3FD26A; After='fc' }
    @{ File='mvs.13m'; Offset=0x3FD26E; After='fc' }
    @{ File='mvs.13m'; Offset=0x3FD2A6; After='f8' }
    @{ File='mvs.13m'; Offset=0x3FD2AA; After='f8' }
    @{ File='mvs.13m'; Offset=0x3FD2AE; After='f8' }
    @{ File='mvs.13m'; Offset=0x3FD2E6; After='f0' }
    @{ File='mvs.13m'; Offset=0x3FD2EA; After='f0' }
    @{ File='mvs.13m'; Offset=0x3FD2EE; After='f0' }
    @{ File='mvs.13m'; Offset=0x3FD326; After='e0' }
    @{ File='mvs.13m'; Offset=0x3FD32A; After='e0' }
    @{ File='mvs.13m'; Offset=0x3FD32E; After='e0' }
    @{ File='mvs.13m'; Offset=0x3FD366; After='c0' }
    @{ File='mvs.13m'; Offset=0x3FD36A; After='c0' }
    @{ File='mvs.13m'; Offset=0x3FD36E; After='c0' }
    @{ File='mvs.13m'; Offset=0x3FD3A6; After='80' }
    @{ File='mvs.13m'; Offset=0x3FD3AA; After='80' }
    @{ File='mvs.13m'; Offset=0x3FD3AE; After='80' }
    @{ File='mvs.13m'; Offset=0x3FD3E6; After='00' }
    @{ File='mvs.13m'; Offset=0x3FD3EA; After='00' }
    @{ File='mvs.13m'; Offset=0x3FD3EE; After='00' }
    @{ File='mvs.15m'; Offset=0x3FCC5E; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCC62; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCC72; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCC76; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCC9E; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCCA2; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCCB2; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCCB6; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCCDE; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCCE2; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCCF2; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCCF6; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCD1E; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCD22; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCD32; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCD36; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCD46; After='cc' }
    @{ File='mvs.15m'; Offset=0x3FCD5A; After='cccc' }
    @{ File='mvs.15m'; Offset=0x3FCD5E; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCD62; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCD72; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCD76; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCD86; After='07' }
    @{ File='mvs.15m'; Offset=0x3FCD8A; After='8787' }
    @{ File='mvs.15m'; Offset=0x3FCD92; After='8f8f' }
    @{ File='mvs.15m'; Offset=0x3FCD9A; After='0707' }
    @{ File='mvs.15m'; Offset=0x3FCD9E; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCDA2; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCDB2; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCDB6; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCDDE; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCDE2; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCDF2; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCDF6; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCE1E; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCE22; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCE32; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCE36; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCE5E; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCE62; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCE72; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCE76; After='0000' }
    @{ File='mvs.15m'; Offset=0x3FCE9E; After='3f3f' }
    @{ File='mvs.15m'; Offset=0x3FCEA2; After='1f1f' }
    @{ File='mvs.15m'; Offset=0x3FCEA6; After='1f1f' }
    @{ File='mvs.15m'; Offset=0x3FCEAA; After='1f1f' }
    @{ File='mvs.15m'; Offset=0x3FCEAE; After='1f1f' }
    @{ File='mvs.15m'; Offset=0x3FCEB2; After='1f1f' }
    @{ File='mvs.15m'; Offset=0x3FCEB6; After='3f3f' }
    @{ File='mvs.17m'; Offset=0x3FCC1F; After='fc' }
    @{ File='mvs.17m'; Offset=0x3FCC23; After='f9' }
    @{ File='mvs.17m'; Offset=0x3FCC27; After='f9' }
    @{ File='mvs.17m'; Offset=0x3FCC2B; After='f9' }
    @{ File='mvs.17m'; Offset=0x3FCC2F; After='f9' }
    @{ File='mvs.17m'; Offset=0x3FCC33; After='f9' }
    @{ File='mvs.17m'; Offset=0x3FCC37; After='fc' }
    @{ File='mvs.17m'; Offset=0x3FCC5F; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCC67; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCC6B; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCC6F; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCC77; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCC9F; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCCA7; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCCAB; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCCAF; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCCB7; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCCDF; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCCE7; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCCEB; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCCEF; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCCF7; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCD0A; After='f3f3' }
    @{ File='mvs.17m'; Offset=0x3FCD0E; After='f3f3' }
    @{ File='mvs.17m'; Offset=0x3FCD13; After='f3' }
    @{ File='mvs.17m'; Offset=0x3FCD17; After='f3' }
    @{ File='mvs.17m'; Offset=0x3FCD1F; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCD27; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCD2B; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCD2F; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCD37; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCD4A; After='4646' }
    @{ File='mvs.17m'; Offset=0x3FCD4E; After='0606' }
    @{ File='mvs.17m'; Offset=0x3FCD53; After='a6' }
    @{ File='mvs.17m'; Offset=0x3FCD57; After='e6' }
    @{ File='mvs.17m'; Offset=0x3FCD5F; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCD67; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCD6B; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCD6F; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCD77; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCD9F; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCDA7; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCDAB; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCDAF; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCDB7; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCDDF; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCDE7; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCDEB; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCDEF; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCDF7; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCE1F; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCE27; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCE2B; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCE2F; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCE37; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCE5F; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCE67; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCE6B; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCE6F; After='00' }
    @{ File='mvs.17m'; Offset=0x3FCE77; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD026; After='fe' }
    @{ File='mvs.17m'; Offset=0x3FD02A; After='fe' }
    @{ File='mvs.17m'; Offset=0x3FD02E; After='fe' }
    @{ File='mvs.17m'; Offset=0x3FD066; After='fc' }
    @{ File='mvs.17m'; Offset=0x3FD06A; After='fc' }
    @{ File='mvs.17m'; Offset=0x3FD06E; After='fc' }
    @{ File='mvs.17m'; Offset=0x3FD0A6; After='f8' }
    @{ File='mvs.17m'; Offset=0x3FD0AA; After='f8' }
    @{ File='mvs.17m'; Offset=0x3FD0AE; After='f8' }
    @{ File='mvs.17m'; Offset=0x3FD0E6; After='f0' }
    @{ File='mvs.17m'; Offset=0x3FD0EA; After='f0' }
    @{ File='mvs.17m'; Offset=0x3FD0EE; After='f0' }
    @{ File='mvs.17m'; Offset=0x3FD126; After='e0' }
    @{ File='mvs.17m'; Offset=0x3FD12A; After='e0' }
    @{ File='mvs.17m'; Offset=0x3FD12E; After='e0' }
    @{ File='mvs.17m'; Offset=0x3FD166; After='c0' }
    @{ File='mvs.17m'; Offset=0x3FD16A; After='c0' }
    @{ File='mvs.17m'; Offset=0x3FD16E; After='c0' }
    @{ File='mvs.17m'; Offset=0x3FD1A6; After='80' }
    @{ File='mvs.17m'; Offset=0x3FD1AA; After='80' }
    @{ File='mvs.17m'; Offset=0x3FD1AE; After='80' }
    @{ File='mvs.17m'; Offset=0x3FD1E6; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD1EA; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD1EE; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD226; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD22A; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD22E; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD266; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD26A; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD26E; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD2A6; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD2AA; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD2AE; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD2E6; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD2EA; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD2EE; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD326; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD32A; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD32E; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD366; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD36A; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD36E; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD3A6; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD3AA; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD3AE; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD3E6; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD3EA; After='00' }
    @{ File='mvs.17m'; Offset=0x3FD3EE; After='00' }
    @{ File='mvs.19m'; Offset=0x3FCC1E; After='fcfc' }
    @{ File='mvs.19m'; Offset=0x3FCC22; After='f8f8' }
    @{ File='mvs.19m'; Offset=0x3FCC26; After='f8f8' }
    @{ File='mvs.19m'; Offset=0x3FCC2A; After='f8f8' }
    @{ File='mvs.19m'; Offset=0x3FCC2E; After='f8f8' }
    @{ File='mvs.19m'; Offset=0x3FCC32; After='f8f8' }
    @{ File='mvs.19m'; Offset=0x3FCC36; After='fcfc' }
    @{ File='mvs.19m'; Offset=0x3FCC5E; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCC62; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCC72; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCC76; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCC9E; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCCA2; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCCB2; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCCB6; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCCDE; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCCE2; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCCF2; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCCF6; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCD06; After='c0' }
    @{ File='mvs.19m'; Offset=0x3FCD0A; After='cccc' }
    @{ File='mvs.19m'; Offset=0x3FCD1A; After='f3f3' }
    @{ File='mvs.19m'; Offset=0x3FCD1E; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCD22; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCD32; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCD36; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCD46; After='e6' }
    @{ File='mvs.19m'; Offset=0x3FCD52; After='5f5f' }
    @{ File='mvs.19m'; Offset=0x3FCD56; After='bfbf' }
    @{ File='mvs.19m'; Offset=0x3FCD5A; After='e6e6' }
    @{ File='mvs.19m'; Offset=0x3FCD5E; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCD62; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCD72; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCD76; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCD9E; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCDA2; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCDB2; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCDB6; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCDDE; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCDE2; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCDF2; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCDF6; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCE1E; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCE22; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCE32; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCE36; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCE5E; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCE62; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCE72; After='0000' }
    @{ File='mvs.19m'; Offset=0x3FCE76; After='0000' }
)
$HasBeforeProof = $false

$FingerprintBuilder = New-Object System.Text.StringBuilder
foreach ($Patch in $Patches) {
    if ($HasBeforeProof) {
        [void]$FingerprintBuilder.Append(('{0}|{1:x6}|{2}|{3}' -f [string]$Patch.File, [int]$Patch.Offset, [string]$Patch.Before, [string]$Patch.After))
    } else {
        [void]$FingerprintBuilder.Append(('{0}|{1:x6}|{2}' -f [string]$Patch.File, [int]$Patch.Offset, [string]$Patch.After))
    }
    [void]$FingerprintBuilder.Append([char]10)
}
$Fingerprint = Get-Sha256 ([System.Text.Encoding]::ASCII.GetBytes($FingerprintBuilder.ToString()))
if ($Fingerprint -ne '853d517d1f9c19ce8d5a3e430f2baae9c889d6a69094f7c75806f9487e87fc9d') {
    Fail 'internal patch fingerprint mismatch; re-download this installer.' 8
}

$ByFile = New-Object 'System.Collections.Generic.Dictionary[string,object]'
foreach ($Patch in $Patches) {
    $Name = [string]$Patch.File
    if (-not $Entries.ContainsKey($Name)) { Fail "internal patch references unknown member '$Name'." 8 }
    $Buffer = [byte[]]$Entries[$Name]
    $After = ConvertFrom-Hex ([string]$Patch.After)
    if ([int]$Patch.Offset -lt 0 -or [int]$Patch.Offset + $After.Length -gt $Buffer.Length) {
        Fail 'internal patch range is outside its member.' 8
    }
    if ($HasBeforeProof) {
        $Before = ConvertFrom-Hex ([string]$Patch.Before)
        if ($Before.Length -ne $After.Length) { Fail 'internal patch length mismatch.' 8 }
        if (-not (Test-Bytes $Buffer ([int]$Patch.Offset) $Before)) {
            Fail ("{0} stock-byte proof failed at +0x{1:X6}; nothing was written." -f $Name,[int]$Patch.Offset)
        }
    }
    [Array]::Copy($After, 0, $Buffer, [int]$Patch.Offset, $After.Length)
    if (-not $ByFile.ContainsKey($Name)) { $ByFile[$Name] = [pscustomobject]@{ Hunks=0; Bytes=0 } }
    $ByFile[$Name].Hunks = $ByFile[$Name].Hunks + 1
    $ByFile[$Name].Bytes = $ByFile[$Name].Bytes + $After.Length
}
foreach ($Name in ($ByFile.Keys | Sort-Object)) {
    Write-Host ("  patch : {0,-9} {1,4} hunks, {2,6} embedded bytes" -f $Name,$ByFile[$Name].Hunks,$ByFile[$Name].Bytes)
}

$Patched = New-Object 'System.Collections.Generic.Dictionary[string,string]'
$Patched['mvsu.03g'] = '1c5bca329365734b934d1a317b2900363911d489995c8a6c803636d11eca5cb5'
$Patched['mvsu.04g'] = 'ba7494c7a2586251fcdb1ba60674c6e035ea93b14e5d84d40e57330b6c5bf2e8'
$Patched['mvs.05d'] = 'd5e78638bd0fa5210a9fbecbe5d378fe024094f0a5ad0550515932e3979698d1'
$Patched['mvs.06a'] = '4fa6c17b5a63f031854865c0777f7f3ef16124101506c98298d3dbaa756730a7'
$Patched['mvs.07b'] = 'c2375e11acd8a726e7f92d766322228052011a3738f76024fcdda8b1bba9711d'
$Patched['mvs.08a'] = 'd00efcfbeed2f4302b1172cc4bbd78b55135b7f7f15e776fe3cb820a8d45668a'
$Patched['mvs.09b'] = 'c262d7ed4e01b033435c1e83804e007251ac3cea2b00e4d6d5f792cd8394b42a'
$Patched['mvs.10b'] = 'c95e411cd5f5df9b01b09b008f43071d59e37cd08a7f2e0a2f8cf92f13ded641'
$Patched['mvs.13m'] = '03fe9d719dc5e23f2cd1866364ab8914b41f79613dc528ba295916ce22927af9'
$Patched['mvs.15m'] = '4b292a35a159a0032835ac88c735818d59a713b6528c7a7e5fab77660024f302'
$Patched['mvs.17m'] = '1b50e90e012d29bc5865bc4966f7d3ed1dc451b7295cdba0b480287aa3a3c7b7'
$Patched['mvs.19m'] = '9b9f7a227d0139572c3946d5101b16093045f4439418ae643dfea883ec66c1a6'
$Patched['mvs.14m'] = '0ac719e09a64cfee86017c20a6e4b0f6575a91fc7b2859ddf573a15a19dfd3f6'
$Patched['mvs.16m'] = 'd7076dab85ed83c8c77723ec00e30982079ab51c77bb06b06bddf1ff60dfbf46'
$Patched['mvs.18m'] = '8e706ff8e12c250a2f830502fd03c6186651defc0c7a0236a4959ef7a0e8fda3'
$Patched['mvs.20m'] = '615f278514851ed5e0da6ff8fb103c2d418735a49eacf9a38ef90551c0e5aac4'
$Patched['mvs.01'] = '2914e05c2266350de0ef28af5bb99690a80933bb76800fd38e27d1ee622ad665'
$Patched['mvs.02'] = '9939e61cf5dd99477fdf4cb1b505516da8b68512da4f10aa7680eae8d6b5abe7'
$Patched['mvs.11m'] = '7c36217c0cec1075d2a5dbd1bdc310fd79c8ac3b3795a586d6aad0bc04668d85'
$Patched['mvs.12m'] = '332edc4527fc1a7aa307a6c5cf824e423462607d853ce6665859c82ab5a7a4a3'
$Patched['mshvsfu.key'] = '838fc71e642c4f9a84e6c2bf9fbec202625683df9c00b9c3674941c756586b48'
foreach ($Record in $Vanilla) {
    $Name = [string]$Record.Name
    if (-not $Entries.ContainsKey($Name)) { continue }
    $Got = Get-Sha256 ([byte[]]$Entries[$Name])
    if ($Got -ne $Patched[$Name]) {
        Fail "internal patched-member proof failed for $Name; nothing was written." 8
    }
}

$Destination = Join-Path (Split-Path -Parent $Source) 'mshvsf-cross-four-human-preview.zip'
$Destination = [IO.Path]::GetFullPath($Destination)
if ($Destination -eq [IO.Path]::GetFullPath($Source)) { Fail 'refusing to overwrite the input archive.' }
$ReceiptPath = "$Destination.receipt.json"
$Temporary = "$Destination.part"
$ReceiptTemporary = "$ReceiptPath.part"
foreach ($Path in @($Destination,$ReceiptPath,$Temporary,$ReceiptTemporary)) {
    if (Test-Path -LiteralPath $Path) { Fail "refusing to overwrite existing output: $Path" }
}

$File = [IO.File]::Open($Temporary, [IO.FileMode]::CreateNew, [IO.FileAccess]::ReadWrite, [IO.FileShare]::None)
try {
    $Output = New-Object System.IO.Compression.ZipArchive($File, [IO.Compression.ZipArchiveMode]::Create, $true)
    try {
        foreach ($Name in $Order) {
            $NewEntry = $Output.CreateEntry($Name, [IO.Compression.CompressionLevel]::Optimal)
            try {
                $NewEntry.LastWriteTime = $Metadata[$Name].LastWriteTime
                $NewEntry.ExternalAttributes = $Metadata[$Name].ExternalAttributes
            } catch {
                # Member order and bytes are authoritative; metadata is best effort.
            }
            $Stream = $NewEntry.Open()
            try {
                $Bytes = [byte[]]$Entries[$Name]
                $Stream.Write($Bytes, 0, $Bytes.Length)
            } finally { $Stream.Dispose() }
        }
    } finally { $Output.Dispose() }
} catch {
    $WriteError = $_.Exception.Message
    $File.Dispose()
    if (Test-Path -LiteralPath $Temporary) { Remove-Item -LiteralPath $Temporary -Force }
    Fail "could not write output ZIP: $WriteError" 8
} finally {
    $File.Dispose()
}

try {
    $Written = Read-ZipMembers $Temporary
    if ($Written.Order.Count -ne $Order.Count) { throw 'output member count changed during write.' }
    for ($i = 0; $i -lt $Order.Count; $i++) {
        if ($Written.Order[$i] -cne $Order[$i]) { throw "output member order changed at index $i." }
    }
    foreach ($Record in $Vanilla) {
        $Name = [string]$Record.Name
        if (-not $Entries.ContainsKey($Name)) { continue }
        if (-not $Written.Entries.ContainsKey($Name)) { throw "output is missing $Name." }
        $Bytes = [byte[]]$Written.Entries[$Name]
        if ($Bytes.Length -ne [int]$Record.Size) { throw "output size check failed for $Name." }
        if ((Get-Sha256 $Bytes) -ne $Patched[$Name]) { throw "output SHA-256 check failed for $Name." }
    }
} catch {
    $VerifyError = $_.Exception.Message
    if (Test-Path -LiteralPath $Temporary) { Remove-Item -LiteralPath $Temporary -Force }
    Fail "output verification failed: $VerifyError" 8
}

$InstallerSha = Get-Sha256 ([IO.File]::ReadAllBytes($env:SELFPATH))
$ChangedMembers = @(
    [pscustomobject][ordered]@{ name='mvsu.03g'; vanillaSha256='40273bbd99c8458d9e14d53e7a28b3ff6c8da557f600619e272138ad6136a771'; patchedSha256='1c5bca329365734b934d1a317b2900363911d489995c8a6c803636d11eca5cb5' }
    [pscustomobject][ordered]@{ name='mvsu.04g'; vanillaSha256='b9ff71cf7fe7d05d09127e05d33789da584a38c1100904de8a297d839fd77b51'; patchedSha256='ba7494c7a2586251fcdb1ba60674c6e035ea93b14e5d84d40e57330b6c5bf2e8' }
    [pscustomobject][ordered]@{ name='mvs.10b'; vanillaSha256='e2605d7c744565615eecad8ae6852fe96f2eec8478e4f8eaeebc79f184ad446e'; patchedSha256='c95e411cd5f5df9b01b09b008f43071d59e37cd08a7f2e0a2f8cf92f13ded641' }
    [pscustomobject][ordered]@{ name='mvs.13m'; vanillaSha256='fd4ed6d5474fcdccbfd9bdd238cacba132e71f7521b5adc58166a5b94ce52e31'; patchedSha256='03fe9d719dc5e23f2cd1866364ab8914b41f79613dc528ba295916ce22927af9' }
    [pscustomobject][ordered]@{ name='mvs.15m'; vanillaSha256='5709e9790ed9719a0633aedd4641829012c44aa37c44dccb1f8489208c4cb2cf'; patchedSha256='4b292a35a159a0032835ac88c735818d59a713b6528c7a7e5fab77660024f302' }
    [pscustomobject][ordered]@{ name='mvs.17m'; vanillaSha256='345f5eb13765e1c703481c87045820ce0e0c5a2e8d502c3e1843fb7b672718f3'; patchedSha256='1b50e90e012d29bc5865bc4966f7d3ed1dc451b7295cdba0b480287aa3a3c7b7' }
    [pscustomobject][ordered]@{ name='mvs.19m'; vanillaSha256='8b6ad4f39f90cec2380f8dec09aab57e5d47833e9e5b282d2384a969079daf36'; patchedSha256='9b9f7a227d0139572c3946d5101b16093045f4439418ae643dfea883ec66c1a6' }
)
$ReceiptPatches = @(
    foreach ($Patch in $Patches) {
        $AfterBytes = ConvertFrom-Hex ([string]$Patch.After)
        [pscustomobject][ordered]@{
            member = [string]$Patch.File
            offset = ('0x{0:X6}' -f [int]$Patch.Offset)
            bytes = $AfterBytes.Length
            afterSha256 = Get-Sha256 $AfterBytes
        }
    }
)
$Receipt = [pscustomobject][ordered]@{
    format = 5
    status = 'installed'
    release = 'MSHvsSF four-player Cross Fever'
    version = 'msh-four-human-background-03'
    draft = $true
    installer = [pscustomobject][ordered]@{ name = [IO.Path]::GetFileName($env:SELFPATH); sha256 = $InstallerSha }
    cleanBaseOnly = $true
    romExpansion = $false
    downloadsRom = $false
    networkAccess = $false
    embedsStockBytes = $HasBeforeProof
    inputArchive = [IO.Path]::GetFileName($Source)
    inputArchiveSha256 = Get-Sha256 ([IO.File]::ReadAllBytes($Source))
    outputArchive = [IO.Path]::GetFileName($Destination)
    outputArchiveSha256 = Get-Sha256 ([IO.File]::ReadAllBytes($Temporary))
    changedMembers = $ChangedMembers
    patches = $ReceiptPatches
    patchFingerprint = $Fingerprint
}
try {
    $ReceiptJson = ($Receipt | ConvertTo-Json -Depth 10) + [Environment]::NewLine
    $Utf8NoBom = New-Object System.Text.UTF8Encoding -ArgumentList $false
    [IO.File]::WriteAllText($ReceiptTemporary, $ReceiptJson, $Utf8NoBom)
    $ReceiptCheck = Get-Content -LiteralPath $ReceiptTemporary -Raw | ConvertFrom-Json
    if ([string]$ReceiptCheck.status -ne 'installed') { throw 'receipt status mismatch.' }
    if ([string]$ReceiptCheck.patchFingerprint -ne '853d517d1f9c19ce8d5a3e430f2baae9c889d6a69094f7c75806f9487e87fc9d') { throw 'receipt patch fingerprint mismatch.' }
} catch {
    $ReceiptError = $_.Exception.Message
    foreach ($Path in @($Temporary,$ReceiptTemporary)) {
        if (Test-Path -LiteralPath $Path) { Remove-Item -LiteralPath $Path -Force }
    }
    Fail "could not write or verify receipt: $ReceiptError" 8
}

try {
    Move-Item -LiteralPath $Temporary -Destination $Destination
    try {
        Move-Item -LiteralPath $ReceiptTemporary -Destination $ReceiptPath
    } catch {
        if (Test-Path -LiteralPath $Destination) { Remove-Item -LiteralPath $Destination -Force }
        throw
    }
} catch {
    $PromotionError = $_.Exception.Message
    foreach ($Path in @($Temporary,$ReceiptTemporary)) {
        if (Test-Path -LiteralPath $Path) { Remove-Item -LiteralPath $Path -Force }
    }
    Fail "could not promote verified output and receipt: $PromotionError" 8
}

Write-Host ''
Write-Host '  DONE. Wrote and re-verified:' -ForegroundColor Green
Write-Host "    $Destination"
Write-Host "    $ReceiptPath"
Write-Host ''
Write-Host '  Patched members: mvsu.03g, mvsu.04g, mvs.10b, mvs.13m, mvs.15m, mvs.17m, mvs.19m; all present member names, sizes, input order and original key presence are preserved.'
Write-Host '  The original ROM was not changed.'
Write-Host ''
Write-Host '  NETPLAY / CRC NOTE' -ForegroundColor Yellow
Write-Host '  Both peers need byte-identical patched member data and a room/emulator'
Write-Host '  that accepts modified sets. Official Fightcade support is not claimed.'
Write-Host ''
Write-Host ('  patch fingerprint  ' + $Fingerprint)
Write-Host ''
Pause-IfConsole
exit 0
