25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
8.0KB

  1. # E07-S03: create a Nova128 source in the Vim clone, prove the bytes on the disk
  2. # are the expected PETSCII/CR file, reopen it in a second Vim session, and
  3. # tokenize the disk file on C128 without a host conversion.
  4. [CmdletBinding()]
  5. param([int]$Port = 6541, [int]$SessionTimeoutSeconds = 300, [int]$MailboxSeconds = 180)
  6. $ErrorActionPreference = "Stop"
  7. $project = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent
  8. $repository = Split-Path $project -Parent
  9. Import-Module (Join-Path $project "scripts\lib\Nova128Test.psm1") -Force
  10. . (Join-Path $project "tests\lexer\reference-lexer.ps1")
  11. $root = Join-Path $project "build\vim-roundtrip"
  12. New-Item -ItemType Directory -Force -Path $root | Out-Null
  13. & (Join-Path $project "scripts\build-tokenize-seq.ps1") | Out-Host
  14. $x128 = Get-ViceTool "x128"
  15. $c1541 = Get-ViceTool "c1541"
  16. $sourceImage = Join-Path $repository "vim\vim-improved.d81"
  17. $editorPrg = Join-Path $repository "vim\vim128.prg"
  18. $work = Join-Path $root "work.d81"
  19. $roundtrip = Join-Path $root "roundtrip.pet"
  20. $copy = Join-Path $root "copy.pet"
  21. if (-not (Test-Path -LiteralPath $sourceImage -PathType Leaf)) {
  22. throw "editor image not found: $sourceImage"
  23. }
  24. if (-not (Test-Path -LiteralPath $editorPrg -PathType Leaf)) {
  25. throw "C128 editor program not found: $editorPrg"
  26. }
  27. $sourceHashBefore = (Get-FileHash -LiteralPath $sourceImage -Algorithm SHA256).Hash
  28. Copy-Item -LiteralPath $sourceImage -Destination $work -Force
  29. # The session's disk carries the C128 editor as well, so the machine can
  30. # reload it without the host.
  31. $injected = (& $c1541 $work -write $editorPrg "vim128" 2>&1) -join "`n"
  32. if ($LASTEXITCODE -ne 0) { throw "could not inject vim128 into the session disk:`n$injected" }
  33. # Both PETSCII letter ranges appear: lowercase identifiers and uppercase ones.
  34. $text = @(
  35. "program RoundTrip",
  36. "var alpha as byte",
  37. "var BETA as byte",
  38. "alpha = 1",
  39. "BETA = 2",
  40. "print alpha",
  41. "print BETA",
  42. "end program") -join "`n"
  43. # VICE keybuf uses a literal backslash-n for RETURN; \x03 is RUN/STOP, which
  44. # leaves the editor's insert mode.
  45. $typed = $text -split "`n"
  46. $insert = ($typed -join "\n")
  47. function Invoke-EditorSession {
  48. param(
  49. [Parameter(Mandatory = $true)][string]$Keys,
  50. [Parameter(Mandatory = $true)][string]$Screenshot
  51. )
  52. if (Test-Path -LiteralPath $Screenshot) { Remove-Item -LiteralPath $Screenshot -Force }
  53. $psi = [Diagnostics.ProcessStartInfo]::new()
  54. $psi.FileName = $x128
  55. # The C128 editor is an 80-column program, so the process starts in 80col
  56. # mode and the exit screenshot must be the plain option (VDC screen). It
  57. # is autostarted from the session disk: a host-loaded program gets no
  58. # device number, and vim128 then reports `written` without touching the
  59. # image. The machine runs at 1 MHz apart from autostart, so the wall-clock
  60. # key delay is also a cycle delay.
  61. $psi.WorkingDirectory = $root
  62. $psi.Arguments = @(
  63. "-80col",
  64. "-autostart", '"work.d81:vim128"',
  65. # A D81 needs a 1581 as drive 8, otherwise :wq fails with "cannot write".
  66. "-drive8type", "1581",
  67. "-8", "work.d81",
  68. "-autostart-warp",
  69. "-keybuf", ('"' + $Keys + '"'),
  70. "-keybuf-delay", "300",
  71. "-limitcycles", "120000000",
  72. "-exitscreenshot", ('"' + $Screenshot + '"'),
  73. "-sounddev", "dummy"
  74. ) -join ' '
  75. $psi.UseShellExecute = $false
  76. $psi.CreateNoWindow = $true
  77. $process = [Diagnostics.Process]::Start($psi)
  78. if (-not $process.WaitForExit($SessionTimeoutSeconds * 1000)) {
  79. $process.Kill()
  80. throw "x64sc session exceeded $SessionTimeoutSeconds s"
  81. }
  82. if (-not (Test-Path -LiteralPath $Screenshot)) {
  83. throw "x64sc produced no exit screenshot; the session did not run"
  84. }
  85. }
  86. function Read-DiskSeq {
  87. param(
  88. [Parameter(Mandatory = $true)][string]$DiskName,
  89. [Parameter(Mandatory = $true)][string]$HostPath
  90. )
  91. if (Test-Path -LiteralPath $HostPath) { Remove-Item -LiteralPath $HostPath -Force }
  92. $output = (& $c1541 $work -read "$DiskName,s" $HostPath 2>&1) -join "`n"
  93. if (-not (Test-Path -LiteralPath $HostPath -PathType Leaf)) {
  94. throw "could not read $DiskName from the session disk:`n$output"
  95. }
  96. return ,([IO.File]::ReadAllBytes($HostPath))
  97. }
  98. function Compare-Bytes {
  99. param(
  100. [Parameter(Mandatory = $true)][byte[]]$Actual,
  101. [Parameter(Mandatory = $true)][byte[]]$Expected,
  102. [Parameter(Mandatory = $true)][string]$What
  103. )
  104. $common = [Math]::Min($Actual.Length, $Expected.Length)
  105. for ($i = 0; $i -lt $common; $i++) {
  106. if ($Actual[$i] -ne $Expected[$i]) {
  107. throw ("{0}: byte {1} is `${2:X2}, expected `${3:X2} (actual {4} bytes, expected {5})" -f
  108. $What, $i, $Actual[$i], $Expected[$i], $Actual.Length, $Expected.Length)
  109. }
  110. }
  111. if ($Actual.Length -ne $Expected.Length) {
  112. throw ("{0}: length {1}, expected {2}" -f $What, $Actual.Length, $Expected.Length)
  113. }
  114. }
  115. # 1: create the file entirely in the editor. The name, the create answer, the
  116. # insert-mode text, RUN/STOP, and :wq all come from one keybuf string.
  117. Invoke-EditorSession -Keys ("roundtrip.n8\n" + "y" + "i" + $insert + "\x03:wq\n") `
  118. -Screenshot (Join-Path $root "edit.png")
  119. $written = Read-DiskSeq -DiskName "roundtrip.n8" -HostPath $roundtrip
  120. $expected = ConvertTo-Nova128Petscii ($text + "`n")
  121. Compare-Bytes -Actual $written -Expected $expected -What "editor-written ROUNDTRIP.N8"
  122. $hasLow = @($written | Where-Object { $_ -ge 0x41 -and $_ -le 0x5A })
  123. $hasHigh = @($written | Where-Object { $_ -ge 0xC1 -and $_ -le 0xDA })
  124. if (-not $hasLow -or -not $hasHigh) {
  125. throw "the written file does not exercise both PETSCII letter ranges"
  126. }
  127. Write-Host ("editor file: {0} bytes, PETSCII ``$41-``$5A and ``$C1-``$DA both present" -f $written.Length)
  128. # 2: reopen the same file in a second session and write the buffer to another
  129. # name, which proves the editor restored the content it had saved.
  130. Invoke-EditorSession -Keys ("roundtrip.n8\n" + ":w copy.n8\n" + ":q\n") `
  131. -Screenshot (Join-Path $root "reopen.png")
  132. $rewritten = Read-DiskSeq -DiskName "copy.n8" -HostPath $copy
  133. Compare-Bytes -Actual $rewritten -Expected $written -What "reopened COPY.N8"
  134. Write-Host "reopened in Vim and rewritten byte-identical"
  135. # 3: tokenize the editor-written file on C128 in x128.
  136. $disk = Join-Path $root "tokenize-seq.d81"
  137. $add = (& $c1541 $disk -write $roundtrip "roundtrip.n8,s" 2>&1) -join "`n"
  138. if ($LASTEXITCODE -ne 0) { throw "could not add the editor file to the test disk:`n$add" }
  139. $screenshot = Join-Path $root "tokenize.png"
  140. $session = Start-Nova128X128 -Autostart $disk -Drive8Image $disk -Port $Port -Screenshot $screenshot
  141. try {
  142. $mb = Wait-Nova128Mailbox $session -TimeoutSeconds $MailboxSeconds
  143. $address = $mb[8] + 256 * $mb[9]
  144. $length = $mb[10] + 256 * $mb[11]
  145. $dump = Read-Nova128Memory $session $address $length
  146. } finally {
  147. Stop-Nova128X128 $session
  148. }
  149. [IO.File]::WriteAllBytes((Join-Path $root "token-dump.bin"), $dump)
  150. if ($mb[3] -ne 0xA5) { throw ("C128 reported FAIL (code `${0:X2})" -f $mb[4]) }
  151. $entries = ConvertFrom-TokenDump $dump
  152. if ($entries.Count -ne 1) { throw "token dump holds $($entries.Count) fixtures, expected 1" }
  153. if ($entries[0].Load -ne 0) { throw "src_load returned $($entries[0].Load) for the editor file" }
  154. $wanted = @((Get-ReferenceTokens $written) | ForEach-Object { $_ })
  155. $got = @($entries[0].Tokens)
  156. if ($wanted.Count -ne $got.Count) {
  157. throw "C128 produced $($got.Count) tokens, the reference lexer $($wanted.Count)"
  158. }
  159. for ($i = 0; $i -lt $wanted.Count; $i++) {
  160. if ($wanted[$i] -ne $got[$i]) {
  161. throw ("token {0} differs: reference '{1}' vs C128 '{2}'" -f ($i + 1), $wanted[$i], $got[$i])
  162. }
  163. }
  164. $sourceHashAfter = (Get-FileHash -LiteralPath $sourceImage -Algorithm SHA256).Hash
  165. if ($sourceHashAfter -ne $sourceHashBefore) { throw "the Vim source image changed during the round-trip" }
  166. Write-Host ("tokenized on C128: {0} tokens, no host conversion" -f $got.Count)
  167. Write-Host ("source image SHA-256 unchanged: {0}" -f $sourceHashAfter)
  168. Write-Host "vim source round-trip passed"

Powered by TurnKey Linux.