diff options
Diffstat (limited to 'tools')
37 files changed, 0 insertions, 1419 deletions
diff --git a/tools/capture-ai-init.ps1 b/tools/capture-ai-init.ps1 deleted file mode 100644 index 3ee91c7..0000000 --- a/tools/capture-ai-init.ps1 +++ /dev/null @@ -1,111 +0,0 @@ -[CmdletBinding()] -param([Parameter(Mandatory = $true)][int]$ProcessId) - -Set-StrictMode -Version Latest -$ErrorActionPreference = 'Stop' - -# Read-only observer for ai.dll's `GetSuperAI` singleton array. It never sends -# input, writes memory, suspends, injects, or calls into the original process. -Add-Type -TypeDefinition @' -using System; -using System.Runtime.InteropServices; -public static class FparkanAiInitCapture { - public const uint TH32CS_SNAPMODULE = 0x00000008; - public const uint TH32CS_SNAPMODULE32 = 0x00000010; - public const uint PROCESS_QUERY_INFORMATION = 0x00000400; - public const uint PROCESS_VM_READ = 0x00000010; - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct MODULEENTRY32 { - public uint dwSize, th32ModuleID, th32ProcessID, GlblcntUsage, ProccntUsage; - public IntPtr modBaseAddr; - public uint modBaseSize; - public IntPtr hModule; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string szModule; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szExePath; - } - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr CreateToolhelp32Snapshot(uint flags, uint processId); - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool Module32First(IntPtr snapshot, ref MODULEENTRY32 entry); - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool Module32Next(IntPtr snapshot, ref MODULEENTRY32 entry); - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr OpenProcess(uint access, bool inheritHandle, uint processId); - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool ReadProcessMemory(IntPtr process, IntPtr address, - [Out] byte[] buffer, IntPtr size, out IntPtr bytesRead); - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool CloseHandle(IntPtr handle); -} -'@ - -function Read-Bytes([IntPtr]$Process, [Int64]$Address, [int]$Length) { - $bytes = [byte[]]::new($Length); $read = [IntPtr]::Zero - if (-not [FparkanAiInitCapture]::ReadProcessMemory($Process, [IntPtr]$Address, - $bytes, [IntPtr]$Length, [ref]$read) -or $read.ToInt64() -ne $Length) { - throw "ReadProcessMemory failed at 0x$('{0:X8}' -f $Address)" - } - $bytes -} - -$snapshot = [FparkanAiInitCapture]::CreateToolhelp32Snapshot( - [FparkanAiInitCapture]::TH32CS_SNAPMODULE -bor [FparkanAiInitCapture]::TH32CS_SNAPMODULE32, - [uint32]$ProcessId) -$aiBase = $null -$modules = @() -try { - $entry = [FparkanAiInitCapture+MODULEENTRY32]::new() - $entry.dwSize = [Runtime.InteropServices.Marshal]::SizeOf([type][FparkanAiInitCapture+MODULEENTRY32]) - if ([FparkanAiInitCapture]::Module32First($snapshot, [ref]$entry)) { - do { - $modules += [ordered]@{ - name = $entry.szModule - base = $entry.modBaseAddr.ToInt64() - size = [int64]$entry.modBaseSize - } - if ($entry.szModule -ieq 'ai.dll') { $aiBase = $entry.modBaseAddr.ToInt64() } - $entry = [FparkanAiInitCapture+MODULEENTRY32]::new() - $entry.dwSize = [Runtime.InteropServices.Marshal]::SizeOf([type][FparkanAiInitCapture+MODULEENTRY32]) - } while ([FparkanAiInitCapture]::Module32Next($snapshot, [ref]$entry)) - } -} finally { [void][FparkanAiInitCapture]::CloseHandle($snapshot) } -if ($null -eq $aiBase) { throw "ai.dll is not loaded by process $ProcessId" } - -$process = [FparkanAiInitCapture]::OpenProcess( - [FparkanAiInitCapture]::PROCESS_QUERY_INFORMATION -bor [FparkanAiInitCapture]::PROCESS_VM_READ, - $false, [uint32]$ProcessId) -if ($process -eq [IntPtr]::Zero) { throw "OpenProcess read-only failed" } -try { - # CreateSuperAI stores its tenth host-callback argument at DAT_100555e4. - $callbackBytes = Read-Bytes $process ($aiBase + 0x555e4) 4 - $callback = [BitConverter]::ToUInt32($callbackBytes, 0) - $callbackModule = $modules | Where-Object { - $callback -ge $_.base -and [int64]$callback -lt ($_.base + $_.size) - } | Select-Object -First 1 - # GetSuperAI(i) returns (&DAT_10055398)[i], with ai.dll preferred base 0x10000000. - $entries = Read-Bytes $process ($aiBase + 0x55398) (64 * 4) - $samples = for ($index = 0; $index -lt 64; $index++) { - $pointer = [BitConverter]::ToUInt32($entries, $index * 4) - if ($pointer -le 0x10000) { continue } - try { - $fields = Read-Bytes $process ([int64]$pointer) 0x88 - [ordered]@{ - index = $index - super_ai = ('0x{0:X8}' -f $pointer) - word_7c = [BitConverter]::ToUInt32($fields, 0x7c) - float_80 = [BitConverter]::ToSingle($fields, 0x80) - float_84 = [BitConverter]::ToSingle($fields, 0x84) - } - } catch { } - } - [ordered]@{ - schema = 'fparkan-ai-init-v1' - process_id = $ProcessId - ai_module_base = ('0x{0:X8}' -f $aiBase) - handler30_callback = ('0x{0:X8}' -f $callback) - handler30_callback_module = if ($null -eq $callbackModule) { $null } else { $callbackModule.name } - handler30_callback_rva = if ($null -eq $callbackModule) { $null } else { ('0x{0:X}' -f ([int64]$callback - $callbackModule.base)) } - entries = @($samples) - } | - ConvertTo-Json -Depth 4 -Compress -} finally { [void][FparkanAiInitCapture]::CloseHandle($process) } diff --git a/tools/capture-original-camera.ps1 b/tools/capture-original-camera.ps1 deleted file mode 100644 index 9e95d91..0000000 --- a/tools/capture-original-camera.ps1 +++ /dev/null @@ -1,213 +0,0 @@ -[CmdletBinding()] -param( - [Parameter(Mandatory = $true)] - [int]$ProcessId, - [ValidateRange(1, 16384)] - [int]$ViewportWidth = 1024, - [ValidateRange(1, 16384)] - [int]$ViewportHeight = 768, - [ValidateRange(0.001, 1000.0)] - [double]$NearPlane = 0.5, - [ValidateRange(0.01, 100000.0)] - [double]$FarPlane = 700.0, - [ValidateRange(0.01, 3.13)] - [double]$FieldOfViewRadians = 1.3, - [ValidateRange(1, 600)] - [int]$CaptureAttempts = 60, - [ValidateRange(0, 1000000.0)] - [double]$MinimumWorldTranslation = 100.0, - [ValidateRange(0, 1000)] - [int]$RetryIntervalMilliseconds = 100 -) - -Set-StrictMode -Version Latest -$ErrorActionPreference = 'Stop' - -# This observer deliberately opens only PROCESS_QUERY_INFORMATION | PROCESS_VM_READ. -# It neither sends input nor writes, suspends, injects into, or calls the original game. -Add-Type -TypeDefinition @' -using System; -using System.Runtime.InteropServices; - -public static class FparkanOriginalCamera { - public const uint TH32CS_SNAPMODULE = 0x00000008; - public const uint TH32CS_SNAPMODULE32 = 0x00000010; - public const uint PROCESS_QUERY_INFORMATION = 0x00000400; - public const uint PROCESS_VM_READ = 0x00000010; - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct MODULEENTRY32 { - public uint dwSize; - public uint th32ModuleID; - public uint th32ProcessID; - public uint GlblcntUsage; - public uint ProccntUsage; - public IntPtr modBaseAddr; - public uint modBaseSize; - public IntPtr hModule; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string szModule; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szExePath; - } - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr CreateToolhelp32Snapshot(uint flags, uint processId); - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool Module32First(IntPtr snapshot, ref MODULEENTRY32 entry); - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool Module32Next(IntPtr snapshot, ref MODULEENTRY32 entry); - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr OpenProcess(uint access, bool inheritHandle, uint processId); - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool ReadProcessMemory( - IntPtr process, - IntPtr address, - [Out] byte[] buffer, - IntPtr size, - out IntPtr bytesRead); - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool CloseHandle(IntPtr handle); -} -'@ - -function Get-LastWin32ErrorText { - $code = [Runtime.InteropServices.Marshal]::GetLastWin32Error() - "$code ($([ComponentModel.Win32Exception]::new($code).Message))" -} - -function Read-OriginalBytes { - param( - [IntPtr]$Process, - [Int64]$Address, - [int]$Length - ) - $buffer = [byte[]]::new($Length) - $read = [IntPtr]::Zero - if (-not [FparkanOriginalCamera]::ReadProcessMemory( - $Process, - [IntPtr]$Address, - $buffer, - [IntPtr]$Length, - [ref]$read)) { - throw "ReadProcessMemory at 0x$('{0:X8}' -f $Address) failed: $(Get-LastWin32ErrorText)" - } - if ($read.ToInt64() -ne $Length) { - throw "ReadProcessMemory at 0x$('{0:X8}' -f $Address) returned $($read.ToInt64()) of $Length bytes" - } - $buffer -} - -$snapshot = [FparkanOriginalCamera]::CreateToolhelp32Snapshot( - [FparkanOriginalCamera]::TH32CS_SNAPMODULE -bor [FparkanOriginalCamera]::TH32CS_SNAPMODULE32, - [uint32]$ProcessId -) -if ($snapshot -eq [IntPtr]::Zero -or $snapshot.ToInt64() -eq -1) { - throw "CreateToolhelp32Snapshot failed: $(Get-LastWin32ErrorText)" -} - -$terrainBase = $null -try { - $module = [FparkanOriginalCamera+MODULEENTRY32]::new() - $module.dwSize = [Runtime.InteropServices.Marshal]::SizeOf([type][FparkanOriginalCamera+MODULEENTRY32]) - if (-not [FparkanOriginalCamera]::Module32First($snapshot, [ref]$module)) { - throw "Module32First failed: $(Get-LastWin32ErrorText)" - } - do { - if ($module.szModule -ieq 'Terrain.dll') { - $terrainBase = $module.modBaseAddr.ToInt64() - break - } - $module = [FparkanOriginalCamera+MODULEENTRY32]::new() - $module.dwSize = [Runtime.InteropServices.Marshal]::SizeOf([type][FparkanOriginalCamera+MODULEENTRY32]) - } while ([FparkanOriginalCamera]::Module32Next($snapshot, [ref]$module)) -} finally { - [void][FparkanOriginalCamera]::CloseHandle($snapshot) -} - -if ($null -eq $terrainBase) { - throw "Terrain.dll is not loaded by process $ProcessId" -} - -$process = [FparkanOriginalCamera]::OpenProcess( - [FparkanOriginalCamera]::PROCESS_QUERY_INFORMATION -bor [FparkanOriginalCamera]::PROCESS_VM_READ, - $false, - [uint32]$ProcessId -) -if ($process -eq [IntPtr]::Zero) { - throw "OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ) failed: $(Get-LastWin32ErrorText)" -} - -try { - # Terrain.dll image RVA 0x7355c -> active 0x1a4-byte outer camera object. - # Its selector-0 affine block begins at outer + 0x20. Words 3/7/11 are - # the proven world-space translation components. AutoDemo also briefly - # selects normalized/reflection-like camera objects; a finite matrix alone - # is not sufficient evidence that it can project the mission world. - $expectedOuterVtable = [uint32]($terrainBase + 0x665b4) - $matrixBytes = $null - $translation = $null - $cameraOuter = $null - $lastObservation = 'camera pointer unavailable' - for ($attempt = 1; $attempt -le $CaptureAttempts; $attempt++) { - $candidateOuter = [BitConverter]::ToUInt32( - (Read-OriginalBytes $process ($terrainBase + 0x7355c) 4), - 0 - ) - if ($candidateOuter -lt 0x10000) { - $lastObservation = "camera pointer 0x$('{0:X8}' -f $candidateOuter)" - continue - } - $outerVtable = [BitConverter]::ToUInt32( - (Read-OriginalBytes $process ([int64]$candidateOuter) 4), - 0 - ) - if ($outerVtable -ne $expectedOuterVtable) { - $lastObservation = "outer vtable 0x$('{0:X8}' -f $outerVtable)" - continue - } - $matrixBytes = Read-OriginalBytes $process ([int64]$candidateOuter + 0x20) 64 - $candidateTranslation = @( - [BitConverter]::ToSingle($matrixBytes, 12), - [BitConverter]::ToSingle($matrixBytes, 28), - [BitConverter]::ToSingle($matrixBytes, 44) - ) - $nonFinite = @($candidateTranslation | Where-Object { - [Single]::IsNaN($_) -or [Single]::IsInfinity($_) - }) - $length = [Math]::Sqrt( - [double]$candidateTranslation[0] * $candidateTranslation[0] + - [double]$candidateTranslation[1] * $candidateTranslation[1] + - [double]$candidateTranslation[2] * $candidateTranslation[2] - ) - if ($nonFinite.Count -eq 0 -and $length -ge $MinimumWorldTranslation) { - $cameraOuter = $candidateOuter - $translation = $candidateTranslation - break - } - $lastObservation = "translation length $length at 0x$('{0:X8}' -f $candidateOuter)" - if ($attempt -lt $CaptureAttempts -and $RetryIntervalMilliseconds -gt 0) { - Start-Sleep -Milliseconds $RetryIntervalMilliseconds - } - } - if ($null -eq $translation) { - throw "No world-space selector-0 transform after $CaptureAttempts samples (minimum translation length $MinimumWorldTranslation; last observation: $lastObservation)" - } - $words = for ($index = 0; $index -lt 16; $index++) { - [BitConverter]::ToUInt32($matrixBytes, $index * 4) - } - [ordered]@{ - schema = 'fparkan-legacy-camera-v1' - process_id = $ProcessId - terrain_module_base = ('0x{0:X8}' -f $terrainBase) - terrain_camera_global_rva = '0x7355c' - terrain_camera_outer = ('0x{0:X8}' -f $cameraOuter) - selector0_words = @($words) - selector0_translation = @($translation) - # LegacyD3d7Projection carries a D3D7 RECT: left, top, right, bottom. - viewport = @(0, 0, $ViewportWidth, $ViewportHeight) - near_plane = $NearPlane - far_plane = $FarPlane - field_of_view_radians = $FieldOfViewRadians - } | ConvertTo-Json -Depth 4 -Compress -} finally { - [void][FparkanOriginalCamera]::CloseHandle($process) -} diff --git a/tools/capture-terrain-shade-cache.ps1 b/tools/capture-terrain-shade-cache.ps1 deleted file mode 100644 index 5c7b10d..0000000 --- a/tools/capture-terrain-shade-cache.ps1 +++ /dev/null @@ -1,272 +0,0 @@ -[CmdletBinding()] -param( - [Parameter(Mandatory = $true)] - [int]$ProcessId, - [ValidateRange(1, 60)] - [int]$CaptureAttempts = 6, - [ValidateRange(0, 1000)] - [int]$RetryIntervalMilliseconds = 100, - [ValidateRange(0x00010000, 0x7fff0000)] - [UInt32]$SearchStart = 0x01000000, - [ValidateRange(0x00010000, 0x7fff0000)] - [UInt32]$SearchEnd = 0x20000000 -) - -Set-StrictMode -Version Latest -$ErrorActionPreference = 'Stop' - -# This observer deliberately opens only PROCESS_QUERY_INFORMATION | PROCESS_VM_READ. -# It neither sends input nor writes, suspends, injects into, or calls the original game. -Add-Type -TypeDefinition @' -using System; -using System.Runtime.InteropServices; - -public static class FparkanTerrainShadeProbe { - public const uint TH32CS_SNAPMODULE = 0x00000008; - public const uint TH32CS_SNAPMODULE32 = 0x00000010; - public const uint PROCESS_QUERY_INFORMATION = 0x00000400; - public const uint PROCESS_VM_READ = 0x00000010; - public const uint MEM_COMMIT = 0x1000; - public const uint PAGE_NOACCESS = 0x01; - public const uint PAGE_GUARD = 0x100; - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct MODULEENTRY32 { - public uint dwSize; - public uint th32ModuleID; - public uint th32ProcessID; - public uint GlblcntUsage; - public uint ProccntUsage; - public IntPtr modBaseAddr; - public uint modBaseSize; - public IntPtr hModule; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string szModule; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szExePath; - } - - [StructLayout(LayoutKind.Sequential)] - public struct MEMORY_BASIC_INFORMATION { - public IntPtr BaseAddress; - public IntPtr AllocationBase; - public uint AllocationProtect; - public IntPtr RegionSize; - public uint State; - public uint Protect; - public uint Type; - } - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr CreateToolhelp32Snapshot(uint flags, uint processId); - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool Module32First(IntPtr snapshot, ref MODULEENTRY32 entry); - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool Module32Next(IntPtr snapshot, ref MODULEENTRY32 entry); - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr OpenProcess(uint access, bool inheritHandle, uint processId); - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool ReadProcessMemory( - IntPtr process, IntPtr address, [Out] byte[] buffer, IntPtr size, out IntPtr bytesRead); - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr VirtualQueryEx( - IntPtr process, IntPtr address, out MEMORY_BASIC_INFORMATION buffer, IntPtr length); - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool CloseHandle(IntPtr handle); - - public static int FindU32(byte[] bytes, uint expected, int start) { - for (int index = start; index <= bytes.Length - 4; index += 4) { - if (BitConverter.ToUInt32(bytes, index) == expected) return index; - } - return -1; - } - - public static ulong Fnv1a64(byte[] bytes, int offset, int length) { - ulong hash = 14695981039346656037UL; - unchecked { - for (int index = offset; index < offset + length; index++) { - hash ^= bytes[index]; - hash *= 1099511628211UL; - } - } - return hash; - } -} -'@ - -function Get-LastWin32ErrorText { - $code = [Runtime.InteropServices.Marshal]::GetLastWin32Error() - "$code ($([ComponentModel.Win32Exception]::new($code).Message))" -} - -function Get-TerrainModuleBase { - param([int]$ProbeProcessId) - $snapshot = [FparkanTerrainShadeProbe]::CreateToolhelp32Snapshot( - [FparkanTerrainShadeProbe]::TH32CS_SNAPMODULE -bor [FparkanTerrainShadeProbe]::TH32CS_SNAPMODULE32, - [uint32]$ProbeProcessId - ) - if ($snapshot -eq [IntPtr]::Zero -or $snapshot.ToInt64() -eq -1) { - throw "CreateToolhelp32Snapshot failed: $(Get-LastWin32ErrorText)" - } - try { - $module = [FparkanTerrainShadeProbe+MODULEENTRY32]::new() - $module.dwSize = [Runtime.InteropServices.Marshal]::SizeOf([type][FparkanTerrainShadeProbe+MODULEENTRY32]) - if (-not [FparkanTerrainShadeProbe]::Module32First($snapshot, [ref]$module)) { - throw "Module32First failed: $(Get-LastWin32ErrorText)" - } - do { - if ($module.szModule -ieq 'Terrain.dll') { - return $module.modBaseAddr.ToInt64() - } - $module = [FparkanTerrainShadeProbe+MODULEENTRY32]::new() - $module.dwSize = [Runtime.InteropServices.Marshal]::SizeOf([type][FparkanTerrainShadeProbe+MODULEENTRY32]) - } while ([FparkanTerrainShadeProbe]::Module32Next($snapshot, [ref]$module)) - } finally { - [void][FparkanTerrainShadeProbe]::CloseHandle($snapshot) - } - throw "Terrain.dll is not loaded by process $ProbeProcessId" -} - -function Read-Bytes { - param([IntPtr]$Process, [Int64]$Address, [int]$Length) - $buffer = [byte[]]::new($Length) - $read = [IntPtr]::Zero - if (-not [FparkanTerrainShadeProbe]::ReadProcessMemory( - $Process, [IntPtr]$Address, $buffer, [IntPtr]$Length, [ref]$read)) { - return $null - } - if ($read.ToInt64() -ne $Length) { - return $null - } - return $buffer -} - -function Find-ShadeCache { - param( - [IntPtr]$Process, - [UInt32]$ExpectedVtable, - [UInt32]$Start, - [UInt32]$End, - [Int64]$ExcludedImageStart, - [Int64]$ExcludedImageEnd - ) - $mbiSize = [Runtime.InteropServices.Marshal]::SizeOf([type][FparkanTerrainShadeProbe+MEMORY_BASIC_INFORMATION]) - [Int64]$cursor = $Start - while ($cursor -lt $End) { - $mbi = [FparkanTerrainShadeProbe+MEMORY_BASIC_INFORMATION]::new() - $queried = [FparkanTerrainShadeProbe]::VirtualQueryEx( - $Process, [IntPtr]$cursor, [ref]$mbi, [IntPtr]$mbiSize - ) - if ($queried -eq [IntPtr]::Zero) { break } - $base = $mbi.BaseAddress.ToInt64() - $size = $mbi.RegionSize.ToInt64() - if ($size -le 0) { break } - $next = $base + $size - if ($mbi.State -eq [FparkanTerrainShadeProbe]::MEM_COMMIT -and - ($mbi.Protect -band [FparkanTerrainShadeProbe]::PAGE_NOACCESS) -eq 0 -and - ($mbi.Protect -band [FparkanTerrainShadeProbe]::PAGE_GUARD) -eq 0) { - $regionStart = [Math]::Max($base, [Int64]$Start) - $regionEnd = [Math]::Min($next, [Int64]$End) - for ([Int64]$offset = $regionStart; $offset -lt $regionEnd; $offset += 65536) { - $length = [int][Math]::Min(65536, $regionEnd - $offset) - $bytes = Read-Bytes $Process $offset $length - if ($null -eq $bytes) { continue } - $searchIndex = 0 - while ($searchIndex -le $bytes.Length - 4) { - $index = [FparkanTerrainShadeProbe]::FindU32($bytes, $ExpectedVtable, $searchIndex) - if ($index -lt 0) { break } - $candidate = $offset + $index - if ($candidate -lt $ExcludedImageStart -or $candidate -ge $ExcludedImageEnd) { - return $candidate - } - $searchIndex = $index + 4 - } - } - } - $cursor = [Math]::Max($next, $cursor + 4096) - } - return $null -} - -function Get-ShadeCacheSummary { - param([IntPtr]$Process, [Int64]$Cache, [byte[]]$Header) - $entryTable = [BitConverter]::ToUInt32($Header, 316) - $entryCount = [BitConverter]::ToUInt32($Header, 320) - $summary = [ordered]@{ - materialized_entries = $null - profile_banks = @() - } - # The count field is runtime data. Keep a hard observer bound so a corrupt - # or stale candidate cannot turn a passive sample into an excessive read. - if ($entryTable -lt 0x1000 -or $entryCount -gt 100000) { return $summary } - $entryBytes = Read-Bytes $Process $entryTable ([int]($entryCount * 8)) - if ($null -eq $entryBytes) { return $summary } - $materialized = 0 - $banks = [System.Collections.Generic.SortedSet[int]]::new() - for ($index = 0; $index -lt $entryCount; $index++) { - $offset = $index * 8 - if ([BitConverter]::ToUInt32($entryBytes, $offset) -ge 0x1000) { - $materialized++ - [void]$banks.Add([int]$entryBytes[$offset + 4]) - } - } - $summary.materialized_entries = $materialized - if ($banks.Count -eq 0) { return $summary } - $maxBank = $banks.Max - if ($maxBank -ge 100) { return $summary } - $bankBytes = Read-Bytes $Process ($Cache + 332) (($maxBank + 1) * 212) - if ($null -eq $bankBytes) { return $summary } - $profiles = [System.Collections.Generic.List[object]]::new() - foreach ($bank in $banks) { - $profiles.Add([ordered]@{ - bank = $bank - fnv1a64 = [FparkanTerrainShadeProbe]::Fnv1a64($bankBytes, $bank * 212, 212).ToString() - }) - } - $summary.profile_banks = @($profiles) - return $summary -} - -if ($SearchEnd -le $SearchStart) { throw 'SearchEnd must exceed SearchStart' } -$terrainBase = Get-TerrainModuleBase $ProcessId -$process = [FparkanTerrainShadeProbe]::OpenProcess( - [FparkanTerrainShadeProbe]::PROCESS_QUERY_INFORMATION -bor [FparkanTerrainShadeProbe]::PROCESS_VM_READ, - $false, - [uint32]$ProcessId -) -if ($process -eq [IntPtr]::Zero) { throw "OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ) failed: $(Get-LastWin32ErrorText)" } - -try { - $expectedVtable = [uint32]($terrainBase + 0x643d0) - $last = 'cache vtable was not present in readable scan range' - for ($attempt = 1; $attempt -le $CaptureAttempts; $attempt++) { - # The vtable value itself naturally appears in the Terrain image as - # relocation data; only a heap-resident object is a cache candidate. - $cache = Find-ShadeCache $process $expectedVtable $SearchStart $SearchEnd $terrainBase ($terrainBase + 0x100000) - if ($null -ne $cache) { - $header = Read-Bytes $process $cache 324 - if ($null -ne $header) { - $summary = Get-ShadeCacheSummary $process $cache $header - [ordered]@{ - schema = 'fparkan-terrain-shade-cache-v1' - process_id = $ProcessId - terrain_module_base = ('0x{0:X8}' -f $terrainBase) - cache_vtable_rva = '0x643d0' - cache_object = ('0x{0:X8}' -f $cache) - result_view = ('0x{0:X8}' -f [BitConverter]::ToUInt32($header, 24)) - entry_table = ('0x{0:X8}' -f [BitConverter]::ToUInt32($header, 316)) - entry_count = [BitConverter]::ToUInt32($header, 320) - materialized_entries = $summary.materialized_entries - profile_banks = $summary.profile_banks - scan_attempt = $attempt - } | ConvertTo-Json -Compress - exit 0 - } - $last = "cache candidate 0x$('{0:X8}' -f $cache) became unreadable" - } - if ($attempt -lt $CaptureAttempts -and $RetryIntervalMilliseconds -gt 0) { - Start-Sleep -Milliseconds $RetryIntervalMilliseconds - } - } - throw "No live GetShade cache after $CaptureAttempts scans ($last)" -} finally { - [void][FparkanTerrainShadeProbe]::CloseHandle($process) -} diff --git a/tools/ghidra/ExportAiCreateSuperAi.java b/tools/ghidra/ExportAiCreateSuperAi.java deleted file mode 100644 index 80117cf..0000000 --- a/tools/ghidra/ExportAiCreateSuperAi.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits the GOG CreateSuperAI export to recover the mission-to-SuperAI -// initialization boundary. Run headless; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiCreateSuperAi extends GhidraScript { - private static final long ADDRESS = 0x1000f710L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI CreateSuperAI ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 120, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiExpressionDispatcher.java b/tools/ghidra/ExportAiExpressionDispatcher.java deleted file mode 100644 index 1f3e8fa..0000000 --- a/tools/ghidra/ExportAiExpressionDispatcher.java +++ /dev/null @@ -1,25 +0,0 @@ -// Emits the decompiled AI expression evaluator containing the recovered -// tag 1..5 dispatch. Run through Ghidra headless analysis only; it never -// mutates the original PE image. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiExpressionDispatcher extends GhidraScript { - private static final long ADDRESS = 0x10005180L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionContaining(address); - println("===== AI expression dispatcher ====="); - if (function == null) { println("missing"); return; } - println("entry=" + function.getEntryPoint()); - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiFtol.java b/tools/ghidra/ExportAiFtol.java deleted file mode 100644 index 215dc01..0000000 --- a/tools/ghidra/ExportAiFtol.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits the x87-to-integer helper called by Handler(19). Run headless; the -// original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiFtol extends GhidraScript { - private static final long ADDRESS = 0x1001df70L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI x87 __ftol helper ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiGetSuperAi.java b/tools/ghidra/ExportAiGetSuperAi.java deleted file mode 100644 index 27ea107..0000000 --- a/tools/ghidra/ExportAiGetSuperAi.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits the GOG ai.dll GetSuperAI export to recover the live singleton -// boundary for read-only handler-input capture. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiGetSuperAi extends GhidraScript { - private static final long ADDRESS = 0x1000f780L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI GetSuperAI ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiScriptLoader.java b/tools/ghidra/ExportAiScriptLoader.java deleted file mode 100644 index 1b457d4..0000000 --- a/tools/ghidra/ExportAiScriptLoader.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits the GOG AI script-bundle loader, discovered from references to -// "MISSIONS\\SCRIPTS\\" and ".scr". Run headless; original input stays read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiScriptLoader extends GhidraScript { - private static final long ADDRESS = 0x10001000L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI script loader ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiScriptLoaderStrings.java b/tools/ghidra/ExportAiScriptLoaderStrings.java deleted file mode 100644 index e1443c7..0000000 --- a/tools/ghidra/ExportAiScriptLoaderStrings.java +++ /dev/null @@ -1,27 +0,0 @@ -// Emits path literals used by the GOG AI script loader at 0x10001000. -// Run headless; the original PE remains read only. -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; - -public class ExportAiScriptLoaderStrings extends GhidraScript { - private static final long[] ADDRESSES = { - 0x10038a88L, 0x10038a9cL, 0x10038aa4L, 0x10038aacL, - 0x10038ab4L, 0x10038abcL, 0x10038ad0L, 0x10038ad8L, - 0x10038ae0L - }; - - @Override - public void run() throws Exception { - for (long value : ADDRESSES) { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(value); - byte[] bytes = new byte[256]; - int count = currentProgram.getMemory().getBytes(address, bytes); - StringBuilder text = new StringBuilder(); - for (int index = 0; index < count && bytes[index] != 0; index++) { - text.append((char) (bytes[index] & 0xff)); - } - println(address + " = \"" + text + "\""); - } - } -} diff --git a/tools/ghidra/ExportAiScriptPackageReader.java b/tools/ghidra/ExportAiScriptPackageReader.java deleted file mode 100644 index 9365165..0000000 --- a/tools/ghidra/ExportAiScriptPackageReader.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits the immediate .scr package reader called by the AI script loader. -// Run through Ghidra headless analysis; the original PE is never modified. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiScriptPackageReader extends GhidraScript { - private static final long ADDRESS = 0x10011B20L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI .scr package reader ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiSuperAiConstructor.java b/tools/ghidra/ExportAiSuperAiConstructor.java deleted file mode 100644 index 85799e9..0000000 --- a/tools/ghidra/ExportAiSuperAiConstructor.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits the SuperAI constructor called by CreateSuperAI. Run headless; the -// original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiSuperAiConstructor extends GhidraScript { - private static final long ADDRESS = 0x10001000L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI SuperAI constructor ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 120, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVarSetLoader.java b/tools/ghidra/ExportAiVarSetLoader.java deleted file mode 100644 index 70c6fa4..0000000 --- a/tools/ghidra/ExportAiVarSetLoader.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits the text `.var` loader called after the AI script loader selects a -// bundle-local or shared varset. Run headless; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVarSetLoader extends GhidraScript { - private static final long ADDRESS = 0x10011ea0L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI varset loader ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVarSetParser.java b/tools/ghidra/ExportAiVarSetParser.java deleted file mode 100644 index f425f30..0000000 --- a/tools/ghidra/ExportAiVarSetParser.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits the actual text-to-varset parser called by the AI varset loader. -// Run headless; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVarSetParser extends GhidraScript { - private static final long ADDRESS = 0x100174a0L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI varset parser ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVarSetU32Resolver.java b/tools/ghidra/ExportAiVarSetU32Resolver.java deleted file mode 100644 index 247220d..0000000 --- a/tools/ghidra/ExportAiVarSetU32Resolver.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits the u32 resolver used by corpus-reachable Handler(30) for indexed -// varset records. Run headless; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVarSetU32Resolver extends GhidraScript { - private static final long ADDRESS = 0x10013570L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI varset u32 resolver ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmHandler0.java b/tools/ghidra/ExportAiVmHandler0.java deleted file mode 100644 index 43e8046..0000000 --- a/tools/ghidra/ExportAiVmHandler0.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits the first function in the AI DLL's verified 73-entry VM handler table. -// Run through Ghidra headless analysis; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmHandler0 extends GhidraScript { - private static final long ADDRESS = 0x10008034L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI VM handler 0 ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmHandler1.java b/tools/ghidra/ExportAiVmHandler1.java deleted file mode 100644 index e58c1e9..0000000 --- a/tools/ghidra/ExportAiVmHandler1.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits Handler(1), the second function in the AI DLL's verified 73-entry VM table. -// Run through Ghidra headless analysis; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmHandler1 extends GhidraScript { - private static final long ADDRESS = 0x10007fd0L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI VM Handler(1) ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmHandler15.java b/tools/ghidra/ExportAiVmHandler15.java deleted file mode 100644 index d1756aa..0000000 --- a/tools/ghidra/ExportAiVmHandler15.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits Handler(15), a frequent non-sentinel selector in the GOG compiled -// script corpus. Run headless; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmHandler15 extends GhidraScript { - private static final long ADDRESS = 0x10008054L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI VM Handler(15) ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmHandler19.java b/tools/ghidra/ExportAiVmHandler19.java deleted file mode 100644 index 8729999..0000000 --- a/tools/ghidra/ExportAiVmHandler19.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits Handler(19), the first instruction in both AutoDemo default-script -// Init events. Run headless; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmHandler19 extends GhidraScript { - private static final long ADDRESS = 0x1000aa38L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI VM Handler(19) ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmHandler19Setter.java b/tools/ghidra/ExportAiVmHandler19Setter.java deleted file mode 100644 index 2aa1ce0..0000000 --- a/tools/ghidra/ExportAiVmHandler19Setter.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits Handler(19)'s common x87 varset setter. Run headless; the original PE -// remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmHandler19Setter extends GhidraScript { - private static final long ADDRESS = 0x10013770L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI VM Handler(19) setter ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmHandler19SetterCallee.java b/tools/ghidra/ExportAiVmHandler19SetterCallee.java deleted file mode 100644 index 92cf7d5..0000000 --- a/tools/ghidra/ExportAiVmHandler19SetterCallee.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits the common varset storage helper reached by Handler(19)'s setter. -// Run headless; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmHandler19SetterCallee extends GhidraScript { - private static final long ADDRESS = 0x10012fe0L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI VM Handler(19) setter storage helper ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmHandler1Callees.java b/tools/ghidra/ExportAiVmHandler1Callees.java deleted file mode 100644 index f59e619..0000000 --- a/tools/ghidra/ExportAiVmHandler1Callees.java +++ /dev/null @@ -1,25 +0,0 @@ -// Emits the two direct callees recovered from AI VM Handler(1). -// Run through Ghidra headless analysis; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmHandler1Callees extends GhidraScript { - private static final long[] ADDRESSES = { 0x10002d30L, 0x10013190L }; - - @Override - public void run() throws Exception { - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - for (long value : ADDRESSES) { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(value); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI VM Handler(1) callee " + address + " ====="); - if (function == null) { println("missing"); continue; } - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - } - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmHandler2.java b/tools/ghidra/ExportAiVmHandler2.java deleted file mode 100644 index d4f3469..0000000 --- a/tools/ghidra/ExportAiVmHandler2.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits Handler(2), the third function in the AI DLL's verified 73-entry VM table. -// Run through Ghidra headless analysis; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmHandler2 extends GhidraScript { - private static final long ADDRESS = 0x10009610L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI VM Handler(2) ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmHandler2Callee.java b/tools/ghidra/ExportAiVmHandler2Callee.java deleted file mode 100644 index c4246e8..0000000 --- a/tools/ghidra/ExportAiVmHandler2Callee.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits the opaque direct callee reached by corpus-reachable AI VM Handler(2). -// Run through Ghidra headless analysis; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmHandler2Callee extends GhidraScript { - private static final long ADDRESS = 0x100059f0L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI VM Handler(2) direct callee ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmHandler2Dispatch.java b/tools/ghidra/ExportAiVmHandler2Dispatch.java deleted file mode 100644 index 5762519..0000000 --- a/tools/ghidra/ExportAiVmHandler2Dispatch.java +++ /dev/null @@ -1,27 +0,0 @@ -// Emits the direct post-insertion dispatcher reached by the corpus-reachable -// AI VM Handler(2) scheduler boundary. Run headless; the original PE is read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmHandler2Dispatch extends GhidraScript { - private static final long[] ADDRESSES = { - 0x1000f920L, 0x10004be0L, 0x10004d00L, 0x10004db0L - }; - - @Override - public void run() throws Exception { - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - for (long value : ADDRESSES) { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(value); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI Handler(2) post-insertion helper " + address + " ====="); - if (function == null) { println("missing"); continue; } - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - } - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmHandler2SchedulerHelpers.java b/tools/ghidra/ExportAiVmHandler2SchedulerHelpers.java deleted file mode 100644 index 76b335d..0000000 --- a/tools/ghidra/ExportAiVmHandler2SchedulerHelpers.java +++ /dev/null @@ -1,28 +0,0 @@ -// Emits record construction, equality, refresh and insertion helpers called by -// the corpus-reachable AI VM Handler(2) scheduler boundary. -// Run through Ghidra headless analysis; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmHandler2SchedulerHelpers extends GhidraScript { - private static final long[] ADDRESSES = { - 0x10004e50L, 0x10004c50L, 0x10005070L, 0x100073e0L - }; - - @Override - public void run() throws Exception { - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - for (long value : ADDRESSES) { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(value); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI Handler(2) scheduler helper " + address + " ====="); - if (function == null) { println("missing"); continue; } - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - } - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmHandler30.java b/tools/ghidra/ExportAiVmHandler30.java deleted file mode 100644 index 81918ff..0000000 --- a/tools/ghidra/ExportAiVmHandler30.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits Handler(30), the most frequent non-sentinel selector in the GOG -// compiled-script corpus. Run headless; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmHandler30 extends GhidraScript { - private static final long ADDRESS = 0x1000c266L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI VM Handler(30) ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmHandler8.java b/tools/ghidra/ExportAiVmHandler8.java deleted file mode 100644 index 4539629..0000000 --- a/tools/ghidra/ExportAiVmHandler8.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits Handler(8), a frequent non-sentinel selector in the GOG compiled -// script corpus. Run headless; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmHandler8 extends GhidraScript { - private static final long ADDRESS = 0x10009b0dL; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI VM Handler(8) ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmHandler8Callees.java b/tools/ghidra/ExportAiVmHandler8Callees.java deleted file mode 100644 index 6ddf317..0000000 --- a/tools/ghidra/ExportAiVmHandler8Callees.java +++ /dev/null @@ -1,25 +0,0 @@ -// Emits the two non-trivial local callees reached by Handler(8). Run headless; -// the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmHandler8Callees extends GhidraScript { - private static final long[] ADDRESSES = {0x10002e90L, 0x10005710L}; - - @Override - public void run() throws Exception { - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - for (long value : ADDRESSES) { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(value); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI Handler(8) callee " + address + " ====="); - if (function == null) { println("missing"); continue; } - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - } - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmHandler8Transitions.java b/tools/ghidra/ExportAiVmHandler8Transitions.java deleted file mode 100644 index 2eee9a8..0000000 --- a/tools/ghidra/ExportAiVmHandler8Transitions.java +++ /dev/null @@ -1,25 +0,0 @@ -// Emits the state-transition helpers selected by Handler(8). Run headless; -// the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmHandler8Transitions extends GhidraScript { - private static final long[] ADDRESSES = {0x10005010L, 0x10005040L}; - - @Override - public void run() throws Exception { - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - for (long value : ADDRESSES) { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(value); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI Handler(8) transition " + address + " ====="); - if (function == null) { println("missing"); continue; } - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - } - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAiVmTableInstall.java b/tools/ghidra/ExportAiVmTableInstall.java deleted file mode 100644 index 842e7dc..0000000 --- a/tools/ghidra/ExportAiVmTableInstall.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits the routine that receives the AI VM's verified 73-entry handler table. -// Run through Ghidra headless analysis; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAiVmTableInstall extends GhidraScript { - private static final long ADDRESS = 0x10011E70L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== AI VM handler table install ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportAniMeshControlCaller.java b/tools/ghidra/ExportAniMeshControlCaller.java deleted file mode 100644 index 083d27f..0000000 --- a/tools/ghidra/ExportAniMeshControlCaller.java +++ /dev/null @@ -1,21 +0,0 @@ -// Emits the function containing the observed AniMesh Control-loader sequence. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportAniMeshControlCaller extends GhidraScript { - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(0x100032e7L); - Function function = currentProgram.getFunctionManager().getFunctionContaining(address); - println("===== AniMesh Control caller ====="); - if (function == null) { println("missing"); return; } - println("entry=" + function.getEntryPoint()); - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportControlFunctions.java b/tools/ghidra/ExportControlFunctions.java deleted file mode 100644 index 0a31023..0000000 --- a/tools/ghidra/ExportControlFunctions.java +++ /dev/null @@ -1,35 +0,0 @@ -// Emits decompiled C for the stable public Control.dll exports. -// Run only through Ghidra headless analysis; it does not modify the input PE. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportControlFunctions extends GhidraScript { - private static final String[] NAMES = { - "InitializeSettings", "LoadControlSystem", "LoadPhysicalModel", - "CreateCollManager", "CreateCollObject" - }; - private static final long[] ADDRESSES = { - 0x10032260L, 0x10032280L, 0x10032580L, 0x100325d0L, 0x10032600L - }; - - @Override - public void run() throws Exception { - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - for (int index = 0; index < NAMES.length; index++) { - Address address = currentProgram.getAddressFactory() - .getDefaultAddressSpace().getAddress(ADDRESSES[index]); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("\n===== " + NAMES[index] + " ====="); - if (function == null) { - println("missing"); - continue; - } - println(decompiler.decompileFunction(function, 60, monitor) - .getDecompiledFunction().getC()); - } - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportIron3dAiCallback.java b/tools/ghidra/ExportIron3dAiCallback.java deleted file mode 100644 index 23e9888..0000000 --- a/tools/ghidra/ExportIron3dAiCallback.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits the live CreateSuperAI host callback selected by the GOG AutoDemo. -// Run headless; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportIron3dAiCallback extends GhidraScript { - private static final long ADDRESS = 0x100611d0L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== Iron3D CreateSuperAI callback ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 120, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportIron3dAiCallbackCommand1.java b/tools/ghidra/ExportIron3dAiCallbackCommand1.java deleted file mode 100644 index 08e8d73..0000000 --- a/tools/ghidra/ExportIron3dAiCallbackCommand1.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits the command-one consumer reached from the recovered CreateSuperAI -// host callback. Run headless; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportIron3dAiCallbackCommand1 extends GhidraScript { - private static final long ADDRESS = 0x10095160L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== Iron3D CreateSuperAI callback command 1 ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 120, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/ExportIron3dAiCallbackCommand1Dispatch.java b/tools/ghidra/ExportIron3dAiCallbackCommand1Dispatch.java deleted file mode 100644 index a5712a1..0000000 --- a/tools/ghidra/ExportIron3dAiCallbackCommand1Dispatch.java +++ /dev/null @@ -1,23 +0,0 @@ -// Emits command one's selected-node dispatch callee. Run headless; the -// original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; - -public class ExportIron3dAiCallbackCommand1Dispatch extends GhidraScript { - private static final long ADDRESS = 0x10095600L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - println("===== Iron3D callback command 1 node dispatch ====="); - if (function == null) { println("missing"); return; } - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - println(decompiler.decompileFunction(function, 120, monitor).getDecompiledFunction().getC()); - decompiler.dispose(); - } -} diff --git a/tools/ghidra/FindAiScriptLoaderReferences.java b/tools/ghidra/FindAiScriptLoaderReferences.java deleted file mode 100644 index 5aae152..0000000 --- a/tools/ghidra/FindAiScriptLoaderReferences.java +++ /dev/null @@ -1,29 +0,0 @@ -// Locates callers that reference the stable AI script-loader literals. -// Run through Ghidra headless analysis; the original PE is read only. -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; -import ghidra.program.model.mem.Memory; -import ghidra.program.model.symbol.Reference; -import ghidra.program.model.symbol.ReferenceManager; - -public class FindAiScriptLoaderReferences extends GhidraScript { - private static final String[] NEEDLES = {".scr", "MISSIONS\\SCRIPTS\\"}; - - @Override - public void run() throws Exception { - Memory memory = currentProgram.getMemory(); - ReferenceManager references = currentProgram.getReferenceManager(); - for (String needle : NEEDLES) { - byte[] bytes = (needle + "\0").getBytes("US-ASCII"); - Address address = memory.findBytes(memory.getMinAddress(), memory.getMaxAddress(), bytes, null, true, monitor); - println("===== " + needle + " ====="); - if (address == null) { println("missing"); continue; } - println("literal=" + address); - for (Reference reference : references.getReferencesTo(address)) { - Function caller = currentProgram.getFunctionManager().getFunctionContaining(reference.getFromAddress()); - println("reference=" + reference.getFromAddress() + " caller=" + (caller == null ? "missing" : caller.getEntryPoint())); - } - } - } -} diff --git a/tools/ghidra/FindAiVmHandler30Callback.java b/tools/ghidra/FindAiVmHandler30Callback.java deleted file mode 100644 index a6da0ad..0000000 --- a/tools/ghidra/FindAiVmHandler30Callback.java +++ /dev/null @@ -1,27 +0,0 @@ -// Finds writers and readers of Handler(30)'s callback pointer, then decompiles -// their containing functions. Run headless; the original PE remains read only. -import ghidra.app.decompiler.DecompInterface; -import ghidra.app.script.GhidraScript; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.Function; -import ghidra.program.model.symbol.Reference; - -public class FindAiVmHandler30Callback extends GhidraScript { - private static final long ADDRESS = 0x100555e4L; - - @Override - public void run() throws Exception { - Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() - .getAddress(ADDRESS); - DecompInterface decompiler = new DecompInterface(); - decompiler.openProgram(currentProgram); - for (Reference reference : currentProgram.getReferenceManager().getReferencesTo(address)) { - Function function = currentProgram.getFunctionManager() - .getFunctionContaining(reference.getFromAddress()); - println("===== callback reference " + reference.getFromAddress() + " ====="); - if (function == null) { println("no containing function"); continue; } - println(decompiler.decompileFunction(function, 60, monitor).getDecompiledFunction().getC()); - } - decompiler.dispose(); - } -} |
