Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

207 lignes
7.0KB

  1. # E07-S01: create a disposable Nova128 development D81 from the Vim work disk.
  2. [CmdletBinding()]
  3. param(
  4. [string]$SourceImage = "",
  5. [string]$OutputImage = "",
  6. [string]$C1541Path = "",
  7. [string]$CompilerPrg = "",
  8. [string]$ProbePrg = "",
  9. [string]$ExamplesDirectory = "",
  10. [switch]$RequireCompiler
  11. )
  12. $ErrorActionPreference = "Stop"
  13. $project = Split-Path $PSScriptRoot -Parent
  14. $repository = Split-Path $project -Parent
  15. $build = Join-Path $project "build"
  16. if ($SourceImage -eq "") {
  17. $SourceImage = Join-Path $repository "vim\work.d81"
  18. }
  19. if ($OutputImage -eq "") {
  20. $OutputImage = Join-Path $build "newlang-dev.d81"
  21. }
  22. if ($C1541Path -eq "") {
  23. $C1541Path = "C:\Program Files\GTK3VICE-3.10-win64\bin\c1541.exe"
  24. }
  25. if ($CompilerPrg -eq "") {
  26. $CompilerPrg = Join-Path $build "n128c.prg"
  27. }
  28. if ($ProbePrg -eq "") {
  29. $ProbePrg = Join-Path $build "minimal.prg"
  30. }
  31. if ($ExamplesDirectory -eq "") {
  32. $ExamplesDirectory = Join-Path $project "examples"
  33. }
  34. $SourceImage = [IO.Path]::GetFullPath($SourceImage)
  35. $OutputImage = [IO.Path]::GetFullPath($OutputImage)
  36. $C1541Path = [IO.Path]::GetFullPath($C1541Path)
  37. $CompilerPrg = [IO.Path]::GetFullPath($CompilerPrg)
  38. $ProbePrg = [IO.Path]::GetFullPath($ProbePrg)
  39. $ExamplesDirectory = [IO.Path]::GetFullPath($ExamplesDirectory)
  40. if (-not (Test-Path -LiteralPath $SourceImage -PathType Leaf)) {
  41. throw "source D81 not found: $SourceImage"
  42. }
  43. if (-not (Test-Path -LiteralPath $C1541Path -PathType Leaf)) {
  44. throw "c1541 tool not found: $C1541Path"
  45. }
  46. if ([IO.Path]::GetExtension($OutputImage) -ine ".d81") {
  47. throw "output image must use the .d81 extension: $OutputImage"
  48. }
  49. if ([string]::Equals($SourceImage, $OutputImage,
  50. [StringComparison]::OrdinalIgnoreCase)) {
  51. throw "output image must not be the source D81"
  52. }
  53. $sourceHashBefore = (Get-FileHash -LiteralPath $SourceImage -Algorithm SHA256).Hash
  54. $outputDirectory = Split-Path $OutputImage -Parent
  55. New-Item -ItemType Directory -Force -Path $outputDirectory | Out-Null
  56. # Only the exact generated output is removed. The source image and its folder
  57. # are never used as deletion targets.
  58. if (Test-Path -LiteralPath $OutputImage) {
  59. Remove-Item -LiteralPath $OutputImage -Force
  60. }
  61. Copy-Item -LiteralPath $SourceImage -Destination $OutputImage
  62. $staging = Join-Path $build "disk-staging"
  63. New-Item -ItemType Directory -Force -Path $staging | Out-Null
  64. $injected = New-Object System.Collections.Generic.List[string]
  65. function Get-DiskDirectory {
  66. $listing = (& $C1541Path $OutputImage -list 2>&1) -join "`n"
  67. if ($LASTEXITCODE -ne 0) {
  68. throw "c1541 could not list the copied D81:`n$listing"
  69. }
  70. return $listing
  71. }
  72. function Add-DiskFile {
  73. param(
  74. [Parameter(Mandatory = $true)][string]$HostPath,
  75. [Parameter(Mandatory = $true)][string]$DiskName,
  76. [Parameter(Mandatory = $true)][ValidateSet("prg", "seq")][string]$Type
  77. )
  78. if (-not (Test-Path -LiteralPath $HostPath -PathType Leaf)) {
  79. throw "artifact disappeared before injection: $HostPath"
  80. }
  81. $destination = if ($Type -eq "seq") { "$DiskName,s" } else { $DiskName }
  82. $writeOutput = (& $C1541Path $OutputImage -write $HostPath $destination 2>&1) -join "`n"
  83. if ($LASTEXITCODE -ne 0) {
  84. throw "c1541 failed to inject '$DiskName':`n$writeOutput"
  85. }
  86. $listing = Get-DiskDirectory
  87. $pattern = '(?im)"' + [regex]::Escape($DiskName) + '"\s+' + $Type + '\s*$'
  88. if ($listing -notmatch $pattern) {
  89. throw "c1541 reported success but '$DiskName' ($Type) is absent from the D81"
  90. }
  91. $injected.Add("$DiskName ($Type)")
  92. }
  93. function ConvertTo-PetsciiSeq {
  94. param(
  95. [Parameter(Mandatory = $true)][string]$InputPath,
  96. [Parameter(Mandatory = $true)][string]$OutputPath
  97. )
  98. $bytes = [IO.File]::ReadAllBytes($InputPath)
  99. $start = 0
  100. if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and
  101. $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) {
  102. $start = 3
  103. }
  104. $converted = New-Object System.Collections.Generic.List[byte]
  105. for ($i = $start; $i -lt $bytes.Length; $i++) {
  106. $value = $bytes[$i]
  107. if ($value -eq 13) {
  108. if ($i + 1 -lt $bytes.Length -and $bytes[$i + 1] -eq 10) {
  109. continue
  110. }
  111. $converted.Add([byte]13)
  112. continue
  113. }
  114. if ($value -eq 10) {
  115. $converted.Add([byte]13)
  116. continue
  117. }
  118. if ($value -gt 0x7F) {
  119. throw "example source is not ASCII/UTF-8 text: $InputPath at byte $i"
  120. }
  121. if ($value -ge 0x61 -and $value -le 0x7A) {
  122. $converted.Add([byte]($value - 0x20))
  123. continue
  124. }
  125. if ($value -ge 0x41 -and $value -le 0x5A) {
  126. $converted.Add([byte]($value + 0x80))
  127. continue
  128. }
  129. $converted.Add([byte]$value)
  130. }
  131. [IO.File]::WriteAllBytes($OutputPath, $converted.ToArray())
  132. }
  133. if (Test-Path -LiteralPath $CompilerPrg -PathType Leaf) {
  134. Add-DiskFile -HostPath $CompilerPrg -DiskName "n128c" -Type prg
  135. } elseif ($RequireCompiler) {
  136. throw "required Nova128 compiler PRG not found: $CompilerPrg"
  137. } else {
  138. Write-Warning "Nova128 compiler is not built yet; skipped $CompilerPrg"
  139. }
  140. if (Test-Path -LiteralPath $ProbePrg -PathType Leaf) {
  141. Add-DiskFile -HostPath $ProbePrg -DiskName "n128probe" -Type prg
  142. } else {
  143. Write-Warning "optional native C128 probe is absent; skipped $ProbePrg"
  144. }
  145. if (Test-Path -LiteralPath $ExamplesDirectory -PathType Container) {
  146. $examples = @(Get-ChildItem -LiteralPath $ExamplesDirectory -Filter "*.n8" -File |
  147. Sort-Object Name)
  148. foreach ($example in $examples) {
  149. if ($example.BaseName.Length -gt 12) {
  150. throw "example base name exceeds the 12-character source profile: $($example.Name)"
  151. }
  152. $diskName = $example.BaseName.ToLowerInvariant() + ".n8"
  153. $petscii = Join-Path $staging ($example.BaseName + ".pet")
  154. ConvertTo-PetsciiSeq -InputPath $example.FullName -OutputPath $petscii
  155. Add-DiskFile -HostPath $petscii -DiskName $diskName -Type seq
  156. }
  157. if ($examples.Count -eq 0) {
  158. Write-Warning "examples directory contains no .n8 files: $ExamplesDirectory"
  159. }
  160. } else {
  161. Write-Warning "examples directory does not exist yet; skipped $ExamplesDirectory"
  162. }
  163. $sourceHashAfter = (Get-FileHash -LiteralPath $SourceImage -Algorithm SHA256).Hash
  164. if ($sourceHashAfter -ne $sourceHashBefore) {
  165. throw "source D81 changed while preparing the disposable image"
  166. }
  167. # A final listing proves the resulting image is readable after all writes.
  168. $null = Get-DiskDirectory
  169. $outputHash = (Get-FileHash -LiteralPath $OutputImage -Algorithm SHA256).Hash
  170. Write-Host "prepared disposable D81: $OutputImage"
  171. Write-Host "source SHA-256 unchanged: $sourceHashAfter"
  172. if ($injected.Count -eq 0) {
  173. Write-Host "injected: no optional Nova128 artifacts are built yet"
  174. } else {
  175. Write-Host ("injected: " + ($injected -join ", "))
  176. }
  177. [pscustomobject]@{
  178. SourceImage = $SourceImage
  179. OutputImage = $OutputImage
  180. SourceHash = $sourceHashAfter
  181. OutputHash = $outputHash
  182. Injected = @($injected)
  183. }

Powered by TurnKey Linux.