Add global build script and VERSION file

Add build.sh for building all FusionX components: Z80 assembly ROMs,
TZFS ROMs, CP/M variants, kernel modules, user-space apps, and CPLD
bitstreams. Supports selective builds via --asm/--tzfs/--cpm/--drivers/
--cpld flags. Updated rebuilt binaries from build verification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Philip Smart
2026-03-14 15:06:30 +00:00
parent 0a0ed14c6c
commit e3771cdf9c
6 changed files with 441 additions and 0 deletions

1
VERSION vendored Normal file
View File

@@ -0,0 +1 @@
1.00

440
build.sh Executable file
View File

@@ -0,0 +1,440 @@
#!/bin/bash
#########################################################################################################
##
## Name: build.sh
## Created: March 2026
## Author(s): Philip Smart
## Description: FusionX global build script
## Builds all software components for the FusionX tranZPUter board:
## - Z80 assembly ROMs (monitor, MS BASIC, CP/M, TZFS)
## - Linux kernel modules (z80drv, ttymzdrv) for each target machine
## - User-space applications (sharpbiter, k64fcpu, z80ctrl)
## - SPI tools (mspi_main)
## - CPLD bitstreams for each target machine (requires Quartus Docker)
##
## Credits:
## Copyright: (c) 2019-2026 Philip Smart <philip.smart@net2net.org>
##
## History: March 2026 - Initial global build script.
##
#########################################################################################################
## This source file is free software: you can redistribute it and#or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This source file is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see <http://www.gnu.org/licenses/>.
#########################################################################################################
set -e
# Root directory of the FusionX project.
ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
# Directories.
SOFTDIR="${ROOT_DIR}/software"
ASMDIR="${SOFTDIR}/asm"
INCDIR="${ASMDIR}/include"
TMPDIR="${SOFTDIR}/tmp"
ROMDIR="${SOFTDIR}/roms"
TOOLDIR="${SOFTDIR}/tools"
CPLDDIR="${ROOT_DIR}/CPLD/v1.0"
DRVDIR="${SOFTDIR}/FusionX/src/z80drv"
TTYDIR="${SOFTDIR}/FusionX/src/ttymz"
SPIDIR="${SOFTDIR}/FusionX/src/spitools"
BINDIR="${SOFTDIR}/FusionX/bin"
MODDIR="${SOFTDIR}/FusionX/modules"
# Tools.
ASM_JAR="${TOOLDIR}/glass-0.5.1.jar"
CROSS_PREFIX="arm-linux-gnueabihf-"
# Build targets.
SOFTWARE_TARGETS="MZ80A MZ700 MZ2000"
CPLD_TARGETS="MZ80A MZ700 MZ2000 PCW8256"
# Assembly build lists.
BUILDROMLIST="mz2000_mon_1z001m mz2000_ipl_original mz2000_ipl_tzpu mz2000_ipl_fusionx mz800_1z_013b mz800_9z_504m mz800_iocs mz80afi monitor_sa1510 monitor_80c_sa1510 monitor_1z-013a monitor_80c_1z-013a monitor_1z-013a-km monitor_80c_1z-013a-km mz80b_ipl"
BUILDMZFLIST="5z009-1b sa-5510_tzfs msbasic_mz80a msbasic_mz700 msbasic_tz40 msbasic_tz80 sharpmz-test"
BUILDTZFSROMLIST="tzfs"
BUILDTZFSMZFLIST="testtz"
CPMVERSIONS="mz700_80c:0 mz80a_80c:1 mz80a_std:2"
# Counters for summary.
PASS=0
FAIL=0
SKIP=0
#-------------------------------------------------------------------------------------------------------
# Helper functions.
#-------------------------------------------------------------------------------------------------------
log_info() { echo "==> $*"; }
log_ok() { echo " [OK] $*"; PASS=$((PASS + 1)); }
log_fail() { echo " [FAIL] $*"; FAIL=$((FAIL + 1)); }
log_skip() { echo " [SKIP] $*"; SKIP=$((SKIP + 1)); }
usage() {
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Build all or selected FusionX components."
echo ""
echo "Options:"
echo " --all Build everything (default)"
echo " --asm Build Z80 assembly ROMs only"
echo " --tzfs Build TZFS ROM only"
echo " --cpm Build CP/M only"
echo " --drivers Build kernel modules and user-space apps only"
echo " --spi Build SPI tools only"
echo " --cpld Build CPLD bitstreams only (requires Quartus Docker)"
echo " --clean Clean all build artifacts"
echo " --help Show this help"
echo ""
echo "Software targets: ${SOFTWARE_TARGETS}"
echo "CPLD targets: ${CPLD_TARGETS}"
exit 0
}
#-------------------------------------------------------------------------------------------------------
# Build Z80 Assembly ROMs and MZF files.
#-------------------------------------------------------------------------------------------------------
build_asm_roms() {
log_info "Building Z80 Assembly ROMs and MZF files..."
if ! command -v java &>/dev/null; then
log_skip "Java not found - cannot assemble Z80 ROMs"
return
fi
if [ ! -f "${ASM_JAR}" ]; then
log_skip "GLASS assembler not found at ${ASM_JAR}"
return
fi
mkdir -p "${TMPDIR}" "${ROMDIR}"
for f in ${BUILDROMLIST} ${BUILDMZFLIST}; do
SRCNAME="${f}"
ASMNAME="${f}.asm"
OBJNAME="${f}.obj"
SYMNAME="${f}.sym"
ROMNAME="${f}.rom"
MZFNAME="${f}.mzf"
# MS BASIC variant handling.
case "${SRCNAME}" in
msbasic_mz80a)
ASMNAME="msbasic.asm"
echo "BUILD_VERSION EQU 0" > "${INCDIR}/MSBASIC_BuildVersion.asm"
;;
msbasic_mz700)
ASMNAME="msbasic.asm"
echo "BUILD_VERSION EQU 1" > "${INCDIR}/MSBASIC_BuildVersion.asm"
;;
msbasic_tz40)
ASMNAME="msbasic.asm"
echo "BUILD_VERSION EQU 2" > "${INCDIR}/MSBASIC_BuildVersion.asm"
;;
msbasic_tz80)
ASMNAME="msbasic.asm"
echo "BUILD_VERSION EQU 3" > "${INCDIR}/MSBASIC_BuildVersion.asm"
;;
esac
if java -jar "${ASM_JAR}" "${ASMDIR}/${ASMNAME}" "${TMPDIR}/${OBJNAME}" "${TMPDIR}/${SYMNAME}" -I "${INCDIR}" -I "${ASMDIR}" 2>&1; then
if echo "${BUILDROMLIST}" | grep -qw "${SRCNAME}"; then
cp "${TMPDIR}/${OBJNAME}" "${ROMDIR}/${ROMNAME}"
log_ok "ROM: ${ROMNAME}"
else
cp "${TMPDIR}/${OBJNAME}" "${ROMDIR}/${MZFNAME}"
log_ok "MZF: ${MZFNAME}"
fi
else
log_fail "${SRCNAME}"
fi
done
# Composite MZ-800 ROM.
if [ -f "${ROMDIR}/mz800_1z_013b.rom" ] && [ -f "${ROMDIR}/mz800_cgrom.ori" ] && \
[ -f "${ROMDIR}/mz800_9z_504m.rom" ] && [ -f "${ROMDIR}/mz800_iocs.rom" ]; then
cat "${ROMDIR}/mz800_1z_013b.rom" "${ROMDIR}/mz800_cgrom.ori" \
"${ROMDIR}/mz800_9z_504m.rom" "${ROMDIR}/mz800_iocs.rom" > "${ROMDIR}/mz800_ipl.rom"
log_ok "ROM: mz800_ipl.rom (composite)"
fi
}
#-------------------------------------------------------------------------------------------------------
# Build TZFS ROM for each machine+board combination.
#-------------------------------------------------------------------------------------------------------
build_tzfs() {
log_info "Building TZFS ROMs..."
if ! command -v java &>/dev/null; then
log_skip "Java not found - cannot assemble TZFS"
return
fi
mkdir -p "${TMPDIR}" "${ROMDIR}"
local DEFSFILE="${INCDIR}/tzfs_definitions.asm"
local MACHINES="MZ80A MZ700 MZ2000"
for machine in ${MACHINES}; do
# Set machine target in definitions.
for m in MZ80A MZ700 MZ1500 MZ2000; do
local val=0
[ "${m}" = "${machine}" ] && val=1
sed -i "s/^BUILD_${m}\s\+EQU\s\+[01]/BUILD_${m} EQU ${val}/" "${DEFSFILE}"
done
# Set board to FusionX.
sed -i "s/^BUILD_FUSIONX\s\+EQU\s\+[01]/BUILD_FUSIONX EQU 1/" "${DEFSFILE}"
sed -i "s/^BUILD_PICOZ80\s\+EQU\s\+[01]/BUILD_PICOZ80 EQU 0/" "${DEFSFILE}"
for f in ${BUILDTZFSROMLIST} ${BUILDTZFSMZFLIST}; do
if java -jar "${ASM_JAR}" "${ASMDIR}/${f}.asm" "${TMPDIR}/${f}.obj" "${TMPDIR}/${f}.sym" -I "${INCDIR}" -I "${ASMDIR}" 2>&1; then
local lower_machine=$(echo "${machine}" | tr '[:upper:]' '[:lower:]')
if echo "${BUILDTZFSROMLIST}" | grep -qw "${f}"; then
cp "${TMPDIR}/${f}.obj" "${ROMDIR}/${f}_${lower_machine}_fusionx.rom"
log_ok "TZFS ROM: ${f}_${lower_machine}_fusionx.rom"
else
cp "${TMPDIR}/${f}.obj" "${ROMDIR}/${f}_${lower_machine}_fusionx.mzf"
log_ok "TZFS MZF: ${f}_${lower_machine}_fusionx.mzf"
fi
else
log_fail "TZFS: ${f} (${machine})"
fi
done
done
}
#-------------------------------------------------------------------------------------------------------
# Build CP/M for each version.
#-------------------------------------------------------------------------------------------------------
build_cpm() {
log_info "Building CP/M variants..."
if ! command -v java &>/dev/null; then
log_skip "Java not found - cannot assemble CP/M"
return
fi
mkdir -p "${TMPDIR}" "${ROMDIR}"
for ver in ${CPMVERSIONS}; do
local FILEEXT=$(echo "${ver}" | cut -d: -f1)
local BUILDVER=$(echo "${ver}" | cut -d: -f2)
echo "BUILD_VERSION EQU ${BUILDVER}" > "${INCDIR}/cpm_buildversion.asm"
local all_ok=true
for f in cbios cpm22; do
if java -jar "${ASM_JAR}" "${ASMDIR}/${f}.asm" "${TMPDIR}/${f}.obj" "${TMPDIR}/${f}.sym" -I "${INCDIR}" -I "${ASMDIR}" 2>&1; then
cp "${TMPDIR}/${f}.obj" "${ROMDIR}/${f}.bin"
else
log_fail "CP/M: ${f} (${FILEEXT})"
all_ok=false
fi
done
if ${all_ok}; then
cat "${ROMDIR}/cpm22.bin" "${ROMDIR}/cbios.bin" > "${ROMDIR}/cpm223_${FILEEXT}.bin"
log_ok "CP/M: cpm223_${FILEEXT}.bin"
fi
done
}
#-------------------------------------------------------------------------------------------------------
# Build kernel modules and user-space applications for each target machine.
#-------------------------------------------------------------------------------------------------------
build_drivers() {
log_info "Building kernel modules and user-space applications..."
if ! command -v ${CROSS_PREFIX}gcc &>/dev/null; then
log_skip "ARM cross-compiler (${CROSS_PREFIX}gcc) not found"
return
fi
local KERNEL_DIR="${SOFTDIR}/linux/kernel"
if [ ! -f "${KERNEL_DIR}/Makefile" ]; then
log_skip "Kernel source tree not found at ${KERNEL_DIR}"
return
fi
for target in ${SOFTWARE_TARGETS}; do
log_info " Target: ${target}"
# Build z80drv kernel module + user-space tools.
# Must cd into directory because Makefile uses $(PWD) for kernel path.
if [ -f "${DRVDIR}/Makefile" ]; then
if (cd "${DRVDIR}" && make "${target}" 2>&1); then
(cd "${DRVDIR}" && make install 2>&1) || true
log_ok "z80drv + apps (${target})"
else
log_fail "z80drv (${target})"
fi
(cd "${DRVDIR}" && make clean 2>&1) || true
fi
# Build ttymzdrv kernel module.
if [ -f "${TTYDIR}/Makefile" ]; then
if (cd "${TTYDIR}" && make "${target}" 2>&1); then
(cd "${TTYDIR}" && make install 2>&1) || true
log_ok "ttymzdrv (${target})"
else
log_fail "ttymzdrv (${target})"
fi
(cd "${TTYDIR}" && make clean 2>&1) || true
fi
done
}
#-------------------------------------------------------------------------------------------------------
# Build SPI tools.
#-------------------------------------------------------------------------------------------------------
build_spi() {
log_info "Building SPI tools..."
if ! command -v ${CROSS_PREFIX}gcc &>/dev/null; then
log_skip "ARM cross-compiler (${CROSS_PREFIX}gcc) not found"
return
fi
if [ -f "${SPIDIR}/Makefile" ]; then
if (cd "${SPIDIR}" && make all 2>&1); then
log_ok "SPI tools (mspi_main)"
else
log_fail "SPI tools"
fi
else
log_skip "SPI tools Makefile not found"
fi
}
#-------------------------------------------------------------------------------------------------------
# Build CPLD bitstreams for each target machine.
#-------------------------------------------------------------------------------------------------------
build_cpld() {
log_info "Building CPLD bitstreams..."
if ! command -v quartus_sh &>/dev/null; then
log_skip "Quartus not found in PATH (use Quartus Docker: qp130)"
return
fi
for target in ${CPLD_TARGETS}; do
local BUILDDIR="${CPLDDIR}/${target}/build"
local PROJECT="tzpuFusionX_${target}"
if [ ! -f "${BUILDDIR}/${PROJECT}.qpf" ]; then
log_skip "CPLD: No Quartus project for ${target}"
continue
fi
log_info " Compiling CPLD: ${target}"
if (cd "${BUILDDIR}" && quartus_sh --flow compile "${PROJECT}" 2>&1); then
if [ -f "${BUILDDIR}/output_files/${PROJECT}.pof" ]; then
log_ok "CPLD: ${PROJECT}.pof"
else
log_fail "CPLD: ${target} (no .pof output)"
fi
else
log_fail "CPLD: ${target}"
fi
done
}
#-------------------------------------------------------------------------------------------------------
# Clean all build artifacts.
#-------------------------------------------------------------------------------------------------------
do_clean() {
log_info "Cleaning build artifacts..."
# Assembly temporaries.
rm -f "${TMPDIR}"/*.obj "${TMPDIR}"/*.sym 2>/dev/null
# Driver build artifacts.
if [ -f "${DRVDIR}/Makefile" ]; then
(cd "${DRVDIR}" && make clean 2>/dev/null) || true
fi
if [ -f "${TTYDIR}/Makefile" ]; then
(cd "${TTYDIR}" && make clean 2>/dev/null) || true
fi
if [ -f "${SPIDIR}/Makefile" ]; then
(cd "${SPIDIR}" && make clean 2>/dev/null) || true
fi
log_ok "Clean complete"
}
#-------------------------------------------------------------------------------------------------------
# Main.
#-------------------------------------------------------------------------------------------------------
BUILD_ASM=false
BUILD_TZFS=false
BUILD_CPM=false
BUILD_DRIVERS=false
BUILD_SPI=false
BUILD_CPLD=false
BUILD_ALL=false
DO_CLEAN=false
if [ $# -eq 0 ]; then
BUILD_ALL=true
fi
while [ $# -gt 0 ]; do
case "$1" in
--all) BUILD_ALL=true ;;
--asm) BUILD_ASM=true ;;
--tzfs) BUILD_TZFS=true ;;
--cpm) BUILD_CPM=true ;;
--drivers) BUILD_DRIVERS=true ;;
--spi) BUILD_SPI=true ;;
--cpld) BUILD_CPLD=true ;;
--clean) DO_CLEAN=true ;;
--help|-h) usage ;;
*) echo "Unknown option: $1"; usage ;;
esac
shift
done
echo "========================================"
echo " FusionX Build System"
echo "========================================"
echo ""
if ${DO_CLEAN}; then
do_clean
exit 0
fi
if ${BUILD_ALL} || ${BUILD_ASM}; then build_asm_roms; fi
if ${BUILD_ALL} || ${BUILD_TZFS}; then build_tzfs; fi
if ${BUILD_ALL} || ${BUILD_CPM}; then build_cpm; fi
if ${BUILD_ALL} || ${BUILD_DRIVERS}; then build_drivers; fi
if ${BUILD_ALL} || ${BUILD_SPI}; then build_spi; fi
if ${BUILD_ALL} || ${BUILD_CPLD}; then build_cpld; fi
echo ""
echo "========================================"
echo " Build Summary"
echo " Passed: ${PASS} Failed: ${FAIL} Skipped: ${SKIP}"
echo "========================================"
if [ ${FAIL} -gt 0 ]; then
exit 1
fi
exit 0

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.