# E02-S01: build the source-reader test PRG and a fresh D81 holding it plus # generated PETSCII fixtures. Writes build/source-test/expected.json with the # results the host computes independently of the C128 code. [CmdletBinding()] param() $ErrorActionPreference = "Stop" $project = Split-Path $PSScriptRoot -Parent Import-Module (Join-Path $PSScriptRoot "lib\Nova128Test.psm1") -Force $out = Join-Path $project "build\source-test" New-Item -ItemType Directory -Force -Path $out | Out-Null $link = Invoke-Nova128Link -Name "source-test" -BuildDir $out ` -Config (Join-Path $project "cfg\compiler.cfg") -Sources @( (Join-Path $project "src\compiler\mmu.s"), (Join-Path $project "src\compiler\diskio.s"), (Join-Path $project "src\compiler\source.s"), (Join-Path $project "tests\source\source-test.s")) if ((Get-Nova128Label $link.Labels "test_entry") -ne 0x1C0D) { throw "test_entry is not at `$1C0D" } # ---------------------------------------------------------------- fixtures function Get-Lines([byte[]]$bytes) { # Split exactly as src_next_line does: $0D ends a line; trailing bytes # without $0D form a last line. $lines = New-Object System.Collections.Generic.List[byte[]] $start = 0 for ($i = 0; $i -lt $bytes.Length; $i++) { if ($bytes[$i] -eq 13) { if ($i -gt $start) { $lines.Add([byte[]]$bytes[$start..($i - 1)]) } else { $lines.Add([byte[]]@()) } $start = $i + 1 } } if ($start -lt $bytes.Length) { $lines.Add([byte[]]$bytes[$start..($bytes.Length - 1)]) } return ,$lines } function Get-Fletcher([byte[]]$bytes) { $s1 = 0; $s2 = 0 foreach ($line in (Get-Lines $bytes)) { foreach ($b in (@($line) + 13)) { $s1 = ($s1 + $b) % 255 $s2 = ($s2 + $s1) % 255 } } return @($s1, $s2) } function New-Line([int]$length, [int]$seed) { # Mixed case so both PETSCII letter ranges appear. $alphabet = "abcdefghijKLMNOPQRST0123456789 =+()" $chars = for ($i = 0; $i -lt $length; $i++) { $alphabet[($i + $seed) % $alphabet.Length] } return (-join $chars) } $fixtures = [ordered]@{} $decls = ConvertTo-Nova128Petscii (Get-Content -Raw (Join-Path $project "tests\grammar\accepted\decls.n8")) if ($decls[-1] -ne 13) { throw "decls.n8 should end with a newline" } $fixtures["decls.n8"] = $decls $fixtures["nofinal.n8"] = [byte[]]$decls[0..($decls.Length - 2)] $edge = New-Object System.Text.StringBuilder [void]$edge.Append((New-Line 80 0) + "`n") # exactly the line limit for ($i = 0; $i -lt 598; $i++) { $len = if ($i -lt 380) { 31 } else { 30 } # totals exactly 18,999 bytes [void]$edge.Append((New-Line $len $i) + "`n") } $fixtures["edge.n8"] = ConvertTo-Nova128Petscii $edge.ToString() $long = "a = 1`nb = 2`n" + (New-Line 81 3) + "`nc = 3`n" $fixtures["longln.n8"] = ConvertTo-Nova128Petscii $long $many = (1..600 | ForEach-Object { "x = $_" }) -join "`n" $fixtures["manyln.n8"] = ConvertTo-Nova128Petscii ($many + "`n") $big = (1..500 | ForEach-Object { New-Line 37 $_ }) -join "`n" $fixtures["big.n8"] = ConvertTo-Nova128Petscii ($big + "`n") # Boundary sanity: these are the facts the expectations below rely on. $edgeLines = Get-Lines $fixtures["edge.n8"] if ($fixtures["edge.n8"].Length -ne 18999 -or $edgeLines.Count -ne 599 -or $edgeLines[0].Length -ne 80) { throw "edge.n8 is not at the exact limits" } if ($fixtures["big.n8"].Length -ne 19000) { throw "big.n8 is not 19,000 bytes" } $hasLow = $decls | Where-Object { $_ -ge 0x41 -and $_ -le 0x5A } $hasHigh = $decls | Where-Object { $_ -ge 0xC1 -and $_ -le 0xDA } if (-not $hasLow -or -not $hasHigh) { throw "decls.n8 lacks one PETSCII letter range" } $files = @(@{ Name = "source-test"; Path = $link.Program; Type = "prg" }) foreach ($name in $fixtures.Keys) { $path = Join-Path $out ($name -replace '\.n8$', '.pet') [IO.File]::WriteAllBytes($path, $fixtures[$name]) $files += @{ Name = $name; Path = $path; Type = "seq" } } $disk = Join-Path $out "source-test.d81" New-Nova128Disk -Path $disk -Files $files # ------------------------------------------------------------ expectations function Ok([string]$name) { $b = $fixtures[$name]; $f = Get-Fletcher $b return [ordered]@{ name = $name; code = 0; lines = (Get-Lines $b).Count; len = $b.Length; s1 = $f[0]; s2 = $f[1] } } $expected = @( (Ok "decls.n8"), (Ok "nofinal.n8"), (Ok "edge.n8"), [ordered]@{ name = "longln.n8"; code = 3; line = 3; col = 81 }, [ordered]@{ name = "manyln.n8"; code = 4; line = 600; col = 1 }, [ordered]@{ name = "big.n8"; code = 2; line = 500; col = 38 }, [ordered]@{ name = "missing.n8"; code = 1; dos = 62 }, (Ok "decls.n8") ) $expected | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $out "expected.json") Write-Host ("built {0}" -f $link.Program) Write-Host ("disk {0} ({1} fixtures)" -f $disk, $fixtures.Count)