Param (
        [String]$SourcePath,
        [String]$DestinationPath
)

function GetBits {
Param (
        $RequestedBitCount
)

        if ($Script:BufferBitCount -lt $RequestedBitCount) {
                $Script:BitBuffer = $Script:BitBuffer * 256 + $Script:SourceBytes[$Script:SourcePosition]
                $Script:BufferBitCount += 8
                $Script:SourcePosition += 1
        }
        $GetBits = $Script:BitBuffer -shr ($Script:BufferBitCount - $RequestedBitCount)
        $Script:BitBuffer = $Script:BitBuffer -band ([Math]::Pow(2, $Script:BufferBitCount - $RequestedBitCount) - 1)
        $Script:BufferBitCount -= $RequestedBitCount
        return $GetBits
}

$SourceBytes = Get-Content -Encoding Byte -Path $SourcePath
$WordCount = ($SourceBytes[0] * 256 + $SourceBytes[1]) * 65536 + ($SourceBytes[2] * 256 + $SourceBytes[3]) - 14
$DestinationBytes = New-Object Byte[] ($WordCount * 2)

$BitBuffer = 0      # The bit buffer is empty
$BufferBitCount = 0 # So there are no bits stored in the buffer
$SourcePosition = 3872
$DestinationPosition = 0

while ($WordCount--) {
        $ControlValue = (GetBits -RequestedBitCount 4)
        if ($ControlValue -eq 15) { # Get word directly from compressed input
                $DestinationBytes[$DestinationPosition++] = [Byte](GetBits -RequestedBitCount 8)
                $DestinationBytes[$DestinationPosition++] = [Byte](GetBits -RequestedBitCount 8)
        } else { # Get word from array of most frequent words
                if ($ControlValue -ge 8) {
                        $FrequentWordIndex = $ControlValue * 256 + (GetBits -RequestedBitCount 8) - 1920    # 12 bit index value, range 128 to 1919
                } else {
                        $FrequentWordIndex = $ControlValue * 16 + (GetBits -RequestedBitCount 4)            # 7 bit index value, range 0 to 127
                }
                $DestinationBytes[$DestinationPosition++] = [Byte]($SourceBytes[32 + $FrequentWordIndex * 2])
                $DestinationBytes[$DestinationPosition++] = [Byte]($SourceBytes[33 + $FrequentWordIndex * 2])
        }
}

$DestinationBytes = [Byte[]]$SourceBytes[4..31] + $DestinationBytes
Set-Content -Encoding Byte -Path $DestinationPath -Value $DestinationBytes
