src/Public/Parse/ConvertFrom-FotonPrefetch.ps1

function ConvertFrom-FotonPrefetch {
    <#
    .SYNOPSIS
        Parse a Prefetch file already copied off the host (bytes on disk).
 
    .DESCRIPTION
        Pure function over a file path. Does not read %SystemRoot%\Prefetch live.
        Windows 10+ MAM-compressed prefetch is recorded as unsupported rather than
        guessed. Uncompressed SCCA v17/v23: executable name from the header.
 
    .PARAMETER Path
        Prefetch .pf file (or a fixture).
 
    .EXAMPLE
        ConvertFrom-FotonPrefetch -Path D:\Cases\...\NOTEPAD.EXE-*.pf
 
    .OUTPUTS
        Prefetch summary object. Format Unsupported* when the layout is not parsed.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)][string]$Path
    )

    if (-not (Test-Path -LiteralPath $Path)) {
        throw "Prefetch file not found: $Path"
    }
    $item = Get-Item -LiteralPath $Path
    $bytes = [IO.File]::ReadAllBytes($item.FullName)
    $sha = Get-FotonSha256Hex -LiteralPath $item.FullName
    $base = [PSCustomObject]@{
        SourcePath     = $item.FullName
        SizeBytes      = $bytes.Length
        SHA256         = $sha
        Format         = 'Unknown'
        Supported      = $false
        Version        = $null
        ExecutableName = ''
        Note           = ''
    }
    if ($bytes.Length -lt 8) {
        $base.Format = 'Unsupported-TooSmall'
        $base.Note = 'File is shorter than a Prefetch header. Do not invent timestamps.'
        return $base
    }
    $magic = [Text.Encoding]::ASCII.GetString($bytes, 0, 4)
    if ($magic -eq 'MAM' -or ($bytes[0] -eq 0x4D -and $bytes[1] -eq 0x41 -and $bytes[2] -eq 0x4D)) {
        $base.Format = 'MAM-compressed'
        $base.Note = 'Win10+ Prefetch is compressed. This parser does not inflate MAM; use an offline decompressor then re-run. Absence of a parsed name is a format limit, not evidence the file is empty.'
        return $base
    }
    if ($magic -ne 'SCCA') {
        $base.Format = 'Unsupported-NotPrefetch'
        $base.Note = 'Header is not SCCA or MAM. Wrong fields would be worse than this record.'
        return $base
    }
    $version = [BitConverter]::ToInt32($bytes, 4)
    $base.Version = $version
    $base.Format = 'SCCA'
    $name = ''
    if ($bytes.Length -ge 0x4C -and $version -in @(17, 23, 26, 30)) {
        $name = [Text.Encoding]::Unicode.GetString($bytes, 0x10, 60).Trim([char]0)
    }
    if ($name) {
        $base.Supported = $true
        $base.ExecutableName = $name
        $base.Note = 'Name from uncompressed SCCA header. Run count and timestamps are not parsed in this version.'
    }
    else {
        $base.Note = ("SCCA version {0} name layout is not implemented. Recorded as unsupported rather than guessed." -f $version)
    }
    return $base
}