Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

190 řádky
7.0KB

  1. # E01-S03: run the KERNAL wrapper probe from a true-drive D64 in VICE x128 and
  2. # verify its machine-readable result block over the remote monitor.
  3. [CmdletBinding()]
  4. param(
  5. [int]$RemotePort = 6512,
  6. [int]$TimeoutSeconds = 60
  7. )
  8. $ErrorActionPreference = "Stop"
  9. $project = Split-Path $PSScriptRoot -Parent
  10. $build = Join-Path $project "build"
  11. $disk = Join-Path $build "kernal-probe.d64"
  12. $labelsPath = Join-Path $build "kernal-probe.lbl"
  13. $traceCommands = Join-Path $project "monitor\kernal-probe-trace.txt"
  14. $monitorLog = Join-Path $build "kernal-probe-monitor.log"
  15. $screenshot = Join-Path $build "kernal-probe-vicii.png"
  16. $x128 = "C:\Program Files\GTK3VICE-3.10-win64\bin\x128.exe"
  17. & (Join-Path $PSScriptRoot "build-kernal-probe.ps1")
  18. if ($LASTEXITCODE -ne 0) { throw "KERNAL probe build failed" }
  19. if (-not (Test-Path -LiteralPath $x128)) { throw "x128.exe not found at $x128" }
  20. foreach ($path in @($monitorLog, $screenshot)) {
  21. if (Test-Path -LiteralPath $path) { Remove-Item -LiteralPath $path -Force }
  22. }
  23. $labelText = Get-Content -Raw -LiteralPath $labelsPath
  24. function Get-LabelAddress([string]$name) {
  25. $match = [regex]::Match($labelText,
  26. "(?im)^al\s+([0-9a-f]+)\s+\." + [regex]::Escape($name) + "\s*$")
  27. if (-not $match.Success) { throw "missing label $name" }
  28. return [Convert]::ToInt32($match.Groups[1].Value, 16)
  29. }
  30. $resultAddress = Get-LabelAddress "kprobe_result"
  31. $completeAddress = Get-LabelAddress "kprobe_complete"
  32. $stateAddress = Get-LabelAddress "kprobe_state_result"
  33. $failAAddress = Get-LabelAddress "kprobe_fail_a"
  34. $failPAddress = Get-LabelAddress "kprobe_fail_p"
  35. $failStAddress = Get-LabelAddress "kprobe_fail_st"
  36. $statusAddress = Get-LabelAddress "kprobe_status_buf"
  37. $statusMax = 32
  38. $blockEnd = $statusAddress + 2 * $statusMax - 1
  39. $arguments = @(
  40. "-drive8type", "1541", "-drive8truedrive", "-8", ('"' + $disk + '"'),
  41. "-autostart", ('"' + $disk + '"'),
  42. "-autostart-warp", "-warp", "-sounddev", "dummy",
  43. "-exitscreenshotvicii", ('"' + $screenshot + '"'),
  44. "-moncommands", ('"' + $traceCommands + '"'),
  45. "-monlog", "-monlogname", ('"' + $monitorLog + '"'),
  46. "-remotemonitor", "-remotemonitoraddress", ("ip4://127.0.0.1:{0}" -f $RemotePort)
  47. ) -join ' '
  48. $psi = [Diagnostics.ProcessStartInfo]::new()
  49. $psi.FileName = $x128
  50. $psi.Arguments = $arguments
  51. $psi.UseShellExecute = $true
  52. $psi.WindowStyle = [Diagnostics.ProcessWindowStyle]::Hidden
  53. $process = [Diagnostics.Process]::Start($psi)
  54. $client = $null
  55. function Read-Available($stream) {
  56. $buffer = New-Object byte[] 16384
  57. $text = ""
  58. Start-Sleep -Milliseconds 300
  59. while ($stream.DataAvailable) {
  60. $count = $stream.Read($buffer, 0, $buffer.Length)
  61. if ($count -le 0) { break }
  62. $text += [Text.Encoding]::ASCII.GetString($buffer, 0, $count)
  63. Start-Sleep -Milliseconds 50
  64. }
  65. return $text
  66. }
  67. function Convert-Dump([string]$text) {
  68. $memory = @{}
  69. $rows = [regex]::Matches($text, "(?i)C:([0-9a-f]{4})((?:[ ]{1,2}[0-9a-f]{2}){1,16})")
  70. foreach ($row in $rows) {
  71. $address = [Convert]::ToInt32($row.Groups[1].Value, 16)
  72. foreach ($hex in ($row.Groups[2].Value.Trim() -split '\s+')) {
  73. $memory[$address] = [Convert]::ToInt32($hex, 16)
  74. $address++
  75. }
  76. }
  77. return $memory
  78. }
  79. try {
  80. $deadline = [DateTime]::UtcNow.AddSeconds(10)
  81. while ([DateTime]::UtcNow -lt $deadline) {
  82. if ($process.HasExited) { throw "x128 exited before remote verification" }
  83. try {
  84. $client = [Net.Sockets.TcpClient]::new()
  85. $client.Connect("127.0.0.1", $RemotePort)
  86. break
  87. } catch {
  88. if ($client) { $client.Dispose(); $client = $null }
  89. Start-Sleep -Milliseconds 200
  90. }
  91. }
  92. if (-not $client -or -not $client.Connected) {
  93. throw "could not connect to VICE remote monitor"
  94. }
  95. $stream = $client.GetStream()
  96. $writer = [IO.StreamWriter]::new($stream, [Text.Encoding]::ASCII, 1024, $true)
  97. $writer.NewLine = "`n"
  98. $writer.AutoFlush = $true
  99. # True-drive loading takes several emulated seconds; poll completion.
  100. $transcript = ""
  101. $memory = @{}
  102. $deadline = [DateTime]::UtcNow.AddSeconds($TimeoutSeconds)
  103. while ($true) {
  104. Start-Sleep -Seconds 1
  105. $writer.WriteLine(("m `${0:X4} `${1:X4}" -f $resultAddress, $blockEnd))
  106. $chunk = Read-Available $stream
  107. $transcript += $chunk
  108. $memory = Convert-Dump $chunk
  109. if ($memory[$completeAddress] -eq 0xA5) { break }
  110. if ([DateTime]::UtcNow -ge $deadline) {
  111. throw "probe did not complete within $TimeoutSeconds s; last response: $chunk"
  112. }
  113. $writer.WriteLine("x")
  114. $transcript += Read-Available $stream
  115. }
  116. # Let the post-done summary finish printing; x128 writes the VIC-II
  117. # screenshot when the monitor quits it below.
  118. $writer.WriteLine("x")
  119. Start-Sleep -Seconds 2
  120. $writer.WriteLine("m 0000 0000")
  121. $transcript += Read-Available $stream
  122. [IO.File]::WriteAllText((Join-Path $build "kernal-probe-remote.txt"), $transcript)
  123. $failures = @()
  124. function Expect([string]$name, [int]$address, [int]$value) {
  125. if ($memory[$address] -ne $value) {
  126. $script:failures += ("{0} at `${1:X4} = `${2:X2}, expected `${3:X2}" -f
  127. $name, $address, $memory[$address], $value)
  128. }
  129. }
  130. Expect "result" $resultAddress 0xFF
  131. Expect "complete" $completeAddress 0xA5
  132. foreach ($state in 0, 1) {
  133. Expect "state$state result" ($stateAddress + $state) 0xFF
  134. Expect "state$state CHKIN error" ($failAAddress + $state) 0x05
  135. if (($memory[$failPAddress + $state] -band 0x01) -ne 0x01) {
  136. $failures += "state$state CHKIN carry was clear"
  137. }
  138. if (($memory[$failStAddress + $state] -band 0x80) -ne 0x80) {
  139. $failures += ("state{0} READST `${1:X2} lacks device-not-present bit 7" -f
  140. $state, $memory[$failStAddress + $state])
  141. }
  142. }
  143. $statusText = @()
  144. foreach ($state in 0, 1) {
  145. $chars = @()
  146. for ($i = 0; $i -lt $statusMax; $i++) {
  147. $byte = $memory[$statusAddress + $state * $statusMax + $i]
  148. if ($byte -eq 0x0D) { break }
  149. $chars += [char]$byte
  150. }
  151. $statusText += (-join $chars)
  152. }
  153. $writer.WriteLine("quit")
  154. $writer.Dispose()
  155. $client.Dispose()
  156. $client = $null
  157. if (-not $process.WaitForExit(10000)) { throw "x128 did not exit after monitor quit" }
  158. if ($failures.Count -gt 0) {
  159. throw ("KERNAL probe verification failed:`n " + ($failures -join "`n "))
  160. }
  161. Write-Host ("verified state results `$FF/`$FF, CHKIN(30) error 5 with C=1, " +
  162. "READST `${0:X2}/`${1:X2}" -f $memory[$failStAddress], $memory[$failStAddress + 1])
  163. Write-Host ("drive 8 status from bank 0: '{0}'" -f $statusText[0])
  164. Write-Host ("drive 8 status from bank 1: '{0}'" -f $statusText[1])
  165. if (Test-Path -LiteralPath $screenshot) { Write-Host ("screenshot: {0}" -f $screenshot) }
  166. } finally {
  167. if ($client) { $client.Dispose() }
  168. if ($process -and -not $process.HasExited) {
  169. $process.Kill()
  170. $process.WaitForExit()
  171. }
  172. }

Powered by TurnKey Linux.