Files
tranZPUter/setup_tranZPUter_windows_native.ps1
Philip Smart 79f36091b2 Fix build.sh project/revision + add Quartus Dockerfiles and setup scripts
* build.sh: compile as `quartus_sh --flow compile <project> -c <revision>`
    (the .qpf is the project, each .qsf a revision) - matching the Jenkins CI.
    coreMZ has revisions coreMZ_E115/E75[_emuMZ|_SoftCPU]; CPLDs have one
    revision == project. Validated: CPLD builds 0 errors.
  * docker/QuartusPrime/Dockerfile.{13.0.1,13.1} - self-contained Web-Edition
    images (from the MZ80A ones) for the MAX7000 CPLDs and the SW-700 v1.2
    Cyclone III FPGA. Dockerfile.17.1 - Quartus 17.1 **Lite** (free, no licence
    - the Jenkins CI uses the licensed Standard edition) for the SW-700 v1.3 /
    Fusion Cyclone IV EP4CE115/EP4CE75, installed under xvfb with libglib2.0-0.
  * setup_tranZPUter.sh + Windows .ps1/.cmd - install Docker + Java, clone
    --recurse-submodules (pulls TZFS/zSoft/ZPU transparently), build the three
    Quartus images, then build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 18:33:04 +01:00

120 lines
7.6 KiB
PowerShell

#########################################################################################################
## tranZPUter 80-Column Colour - Build Environment Setup for Windows 10/11 (Docker Desktop)
## Copyright (c) 2019-2026 Philip Smart <philip.smart@net2net.org>. GPL v3. See license.txt.
##
## The two Quartus versions (13.0.1 for the CPLD, 13.1 for the FPGA) run inside self-contained Linux
## Docker images - the free Web Edition, no licence file. On Windows they run under Docker Desktop.
## NOTE: each image is large (Quartus adds several GB); allow plenty of disk for Docker Desktop.
##
## Usage - EASIEST (window stays open, logged): double-click setup_tranZPUter_windows.cmd
## Usage - from PowerShell: powershell -NoProfile -ExecutionPolicy Bypass -File .\setup_tranZPUter_windows_native.ps1
## Private repo: $env:tranZPUter_REPO_URL = "https://git.eaw.app/pdsmart/tranZPUter-private.git"
#########################################################################################################
$ErrorActionPreference = "Stop"
$LogFile = Join-Path $env:TEMP ("setup_tranZPUter_" + (Get-Date -Format "yyyyMMdd_HHmmss") + ".log")
try { Start-Transcript -Path $LogFile -Force | Out-Null } catch {}
function Pause-Exit ($code) {
try { Stop-Transcript | Out-Null } catch {}
Write-Host ""; Write-Host "Full log saved to: $LogFile" -ForegroundColor DarkGray
if ($env:tranZPUter_ASSUME_YES -ne '1') { Read-Host "Press Enter to close this window" }
exit $code
}
trap { Write-Host ""; Write-Host "[ERROR] $($_ | Out-String)" -ForegroundColor Red; Pause-Exit 1 }
function Write-Info ($m) { Write-Host "[INFO] $m" -ForegroundColor Cyan }
function Write-Ok ($m) { Write-Host "[OK] $m" -ForegroundColor Green }
function Write-Warn ($m) { Write-Host "[WARN] $m" -ForegroundColor Yellow }
function Write-Fail ($m) { Write-Host "[FAIL] $m" -ForegroundColor Red; Pause-Exit 1 }
function Confirm-Yes ($p) { if ($env:tranZPUter_ASSUME_YES -eq '1') { return $true }; $a = Read-Host $p; return ($a -notmatch '^[Nn]') }
function Test-Cmd ($n) { return [bool](Get-Command $n -ErrorAction SilentlyContinue) }
function Refresh-Path { $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") }
function Find-Winget {
$w = Get-Command winget -ErrorAction SilentlyContinue; if ($w) { return $w.Source }
$c = Get-ChildItem 'C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*\winget.exe' -ErrorAction SilentlyContinue
if ($c) { return ($c | Sort-Object FullName)[-1].FullName }; return $null
}
$RepoUrl = if ($env:tranZPUter_REPO_URL) { $env:tranZPUter_REPO_URL } else { "https://git.eaw.app/eaw/tranZPUter.git" }
$CpldImage = if ($env:tranZPUter_CPLD_IMAGE) { $env:tranZPUter_CPLD_IMAGE } else { "tzpu-quartus:13.0.1" }
$FpgaImage = if ($env:tranZPUter_FPGA_IMAGE) { $env:tranZPUter_FPGA_IMAGE } else { "tzpu-quartus:13.1" }
Write-Host ""
Write-Host "===========================================================================" -ForegroundColor White
Write-Host " tranZPUter 80-Column Colour - Windows setup (Docker Desktop)" -ForegroundColor White
Write-Host "===========================================================================" -ForegroundColor White
# --- winget + Git ---
$WinGet = Find-Winget
if (-not $WinGet) { Write-Warn "winget not found - install Git + Docker Desktop manually if missing." }
if (-not (Test-Cmd git)) {
if (-not $WinGet) { Write-Fail "Git not found and winget unavailable. Install Git for Windows, then re-run." }
Write-Info "Installing Git for Windows..."
& $WinGet install --id Git.Git -e --source winget --accept-package-agreements --accept-source-agreements
Refresh-Path
if (-not (Test-Cmd git)) { Write-Fail "Git install did not complete. Open a new PowerShell and re-run." }
}
Write-Ok "Git: $((git --version))"
# --- Docker Desktop ---
if (-not (Test-Cmd docker)) {
if (-not $WinGet) { Write-Fail "Docker not found and winget unavailable. Install Docker Desktop, then re-run." }
Write-Info "Installing Docker Desktop..."
& $WinGet install --id Docker.DockerDesktop -e --source winget --accept-package-agreements --accept-source-agreements
Refresh-Path
Write-Warn "Docker Desktop installed - START IT (system tray), wait until it reports Running, then re-run this script."
Pause-Exit 0
}
try { & docker info *> $null; if ($LASTEXITCODE -ne 0) { throw } } catch { Write-Fail "Docker is installed but not running - start Docker Desktop (wait for 'Running'), then re-run." }
Write-Ok "Docker is available and running."
# --- Repository ---
$DefaultProj = if ($env:tranZPUter_DIR) { $env:tranZPUter_DIR.TrimEnd('\') } else { Join-Path $HOME "tranZPUter" }
if ($env:tranZPUter_DIR) { $ProjDir = $DefaultProj }
else { $inp = Read-Host " Checkout directory [$DefaultProj]"; $ProjDir = if ([string]::IsNullOrWhiteSpace($inp)) { $DefaultProj } else { $inp.Trim() } }
function Is-Checkout ($d) { return ((Test-Path (Join-Path $d "build.sh")) -and (Test-Path (Join-Path $d "docker\QuartusPrime"))) }
if (Is-Checkout $ProjDir) {
Write-Ok "Existing checkout at $ProjDir - updating."
Push-Location $ProjDir; try { & git pull --ff-only 2>&1 | Out-Null } finally { Pop-Location }
} else {
if ((Test-Path $ProjDir) -and (Get-ChildItem $ProjDir -Force -ErrorAction SilentlyContinue)) { Write-Fail "$ProjDir exists and is not an tranZPUter checkout." }
$cloned = $false
for ($i=1; $i -le 5; $i++) {
Write-Info "Cloning $RepoUrl into $ProjDir (attempt $i of 5)..."
& git clone --recurse-submodules $RepoUrl $ProjDir; if (($LASTEXITCODE -eq 0) -and (Is-Checkout $ProjDir)) { $cloned=$true; break }
if (Test-Path $ProjDir) { Remove-Item -Recurse -Force $ProjDir -ErrorAction SilentlyContinue }; Start-Sleep 3
}
if (-not $cloned) { Write-Fail "git clone failed after 5 attempts." }
Write-Ok "Cloned into $ProjDir."
}
# --- Build the two Quartus Docker images ---
function Build-Image ($dockerfile, $tag, $name) {
& docker image inspect $tag *> $null
if ($LASTEXITCODE -eq 0) { Write-Ok "$name image ($tag) already built."; return }
Write-Info "Building the $name Quartus image ($tag) - downloads ~1.5 GB + installs Quartus (~20-40 min)..."
& docker build -f (Join-Path $ProjDir "docker\QuartusPrime\$dockerfile") -t $tag (Join-Path $ProjDir "docker\QuartusPrime")
if ($LASTEXITCODE -ne 0) { Write-Fail "Failed to build the $name image." }
Write-Ok "$name image built ($tag)."
}
Build-Image "Dockerfile.13.0.1" $CpldImage "CPLD (Quartus 13.0.1)"
Build-Image "Dockerfile.13.1" "tzpu-quartus:13.1" "FPGA SW-700 v1.2 (Quartus 13.1)"
Build-Image "Dockerfile.17.1" "tzpu-quartus:17.1" "FPGA SW-700 v1.3 (Quartus 17.1)"
$bashProj = ($ProjDir -replace '\\','/')
Write-Host ""
if (Confirm-Yes "Build everything now (ROMs + CPLD + FPGA)? [Y/n]") {
$Bash = "C:\Program Files\Git\bin\bash.exe"
if (Test-Path $Bash) {
& $Bash -lc "cd '$bashProj' && tranZPUter_CPLD_IMAGE='$CpldImage' tranZPUter_FPGA_IMAGE='$FpgaImage' ./build.sh -t all"
} else { Write-Warn "Git Bash not found; run './build.sh -t all' from Git Bash manually." }
}
Write-Host ""
Write-Host "===========================================================================" -ForegroundColor White
Write-Host " Ready. In Git Bash: cd $bashProj && ./build.sh -t all" -ForegroundColor White
Write-Host " Outputs: CPLD/build/output_files/VideoInterface.pof," -ForegroundColor White
Write-Host " FPGA/build/output_files/VideoController.sof (+ .jic EPCS16 boot flash)." -ForegroundColor White
Write-Host "===========================================================================" -ForegroundColor White
Pause-Exit 0