65816-llvm-mos/demos/build.sh
2026-06-25 17:13:50 -05:00

127 lines
4.7 KiB
Bash
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# build.sh - compile a demo C source into a GS/OS-loadable OMF.
#
# Usage: bash demos/build.sh <basename>
# where demos/<basename>.c is the source. Output is
# demos/<basename>.omf in the same directory.
#
# Uses crt0Gsos (the GS/OS-aware crt) and ExpressLoad-wrapped multi-
# seg OMF so the slow-Loader rejection path is avoided. The OMF
# launches via runViaFinder.sh after cadius-injection onto the GS/OS
# data disk.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
# --debug appends `_dbg` to the output basename so the release and debug
# artifacts can coexist on disk. It adds `-g` to clang, requests a DWARF
# sidecar (`--debug-out`) from link816, and keeps the .map (always emitted
# regardless of mode — pc2line.py and scripts/mameDebug.py need it for
# function-name lookup). Phase 3.1 (debugger front-end).
DEBUG=0
ARGS=()
while [ $# -gt 0 ]; do
case "$1" in
--debug) DEBUG=1; shift;;
*) ARGS+=("$1"); shift;;
esac
done
set -- "${ARGS[@]+"${ARGS[@]}"}"
[ $# -ge 1 ] || { echo "usage: $0 [--debug] <basename>" >&2; exit 2; }
BASE="$1"
SRC="$SCRIPT_DIR/$BASE.c"
[ -f "$SRC" ] || { echo "no source: $SRC" >&2; exit 2; }
CLANG="$PROJECT_ROOT/tools/llvm-mos-build/bin/clang"
LINK="$PROJECT_ROOT/tools/link816"
OMF="$PROJECT_ROOT/tools/omfEmit"
# Debug builds get a `_dbg` suffix so they coexist with the release
# build. All intermediate + final paths share the suffix so a stale
# release .o isn't reused for a debug link.
if [ "$DEBUG" = 1 ]; then
OUTBASE="${BASE}_dbg"
DBGFLAGS="-g"
else
OUTBASE="$BASE"
DBGFLAGS=""
fi
OBJ="$SCRIPT_DIR/$OUTBASE.o"
BIN="$SCRIPT_DIR/$OUTBASE.bin"
MAP="$SCRIPT_DIR/$OUTBASE.map"
RELOC="$SCRIPT_DIR/$OUTBASE.reloc"
OUT="$SCRIPT_DIR/$OUTBASE.omf"
DWARF="$SCRIPT_DIR/$OUTBASE.dwarf"
echo "compile: $BASE.c -> $OUTBASE.o"
"$CLANG" --target=w65816 -I"$PROJECT_ROOT/runtime/include" \
$DBGFLAGS \
-O2 -ffunction-sections -c "$SRC" -o "$OBJ"
echo "link: -> $OUTBASE.bin"
# text-base 0: under the GS/OS Loader our segment lands at some bank
# the Loader picks (KIND=0x1000), so link-time addresses can start at
# offset 0 in the segment. With text-base=0 the link-time-baked IMM16
# operand for `lda gFoo` already equals gFoo's runtime offset within
# the segment (no segPlacedBase adjustment needed since the Loader
# places at bank-aligned bases), so the linker can skip emitting
# cRELOC entries for every IMM16 site — 6090% reduction in cRELOC
# count, proportional speed-up in the Loader's per-reloc walk.
# Bare-metal builds keep text-base=0x1000 (runInMame.sh loads at
# bank-0:1000 and link-time addresses must match).
#
# bss-base 0xA000 keeps BSS above the SHR shadow region ($2000-$9FFF
# in bank 0 mirrors to bank E1 SHR memory). Without this, the smaller
# section-gc'd demos place BSS at e.g. $2300 and global writes scribble
# on the screen.
LINKER_ARGS=(-o "$BIN" --text-base 0 --bss-base 0xA000 \
--map "$MAP" --reloc-out "$RELOC")
if [ "$DEBUG" = 1 ]; then
LINKER_ARGS+=(--debug-out "$DWARF")
fi
"$LINK" "${LINKER_ARGS[@]}" \
"$PROJECT_ROOT/runtime/crt0Gsos.o" "$OBJ" \
"$PROJECT_ROOT/runtime/libc.o" \
"$PROJECT_ROOT/runtime/snprintf.o" \
"$PROJECT_ROOT/runtime/extras.o" \
"$PROJECT_ROOT/runtime/softFloat.o" \
"$PROJECT_ROOT/runtime/softDouble.o" \
"$PROJECT_ROOT/runtime/iigsGsos.o" \
"$PROJECT_ROOT/runtime/iigsToolbox.o" \
"$PROJECT_ROOT/runtime/iigsToolboxExtra.o" \
"$PROJECT_ROOT/runtime/desktop.o" \
"$PROJECT_ROOT/runtime/sound.o" \
"$PROJECT_ROOT/runtime/cursor.o" \
"$PROJECT_ROOT/runtime/eventLoop.o" \
"$PROJECT_ROOT/runtime/uiBuilder.o" \
"$PROJECT_ROOT/runtime/resource.o" \
"$PROJECT_ROOT/runtime/libgcc.o"
echo "OMF: -> $OUTBASE.omf"
"$OMF" --input "$BIN" --map "$MAP" \
--base 0 --entry __start --output "$OUT" \
--name "$(echo "$OUTBASE" | tr '[:lower:]' '[:upper:]' | cut -c1-8)" \
--expressload --relocs "$RELOC"
ls -la "$OUT"
if [ "$DEBUG" = 1 ]; then
echo "debug sidecar: $DWARF"
echo "map: $MAP"
fi
# Phase 3.4 (rsrcBundle): if demos/<basename>.rsrc/ exists, run the
# bundler to produce an AppleSingle blob (out.apl) AND the cadius
# sidecar (out.apl_ResourceFork.bin). We pass --sidecar because
# cadius v1.4.6's AppleSingle parser drops resource_fork entries
# silently; runViaFinder.sh uses ADDFILE which picks up the sidecar.
RSRC_DIR="$SCRIPT_DIR/$BASE.rsrc"
if [ -d "$RSRC_DIR" ]; then
APL="$SCRIPT_DIR/$OUTBASE.apl"
echo "rsrcBundle: $RSRC_DIR -> $OUTBASE.apl (+ sidecar)"
python3 "$PROJECT_ROOT/tools/rsrcBundle/rsrcBundle.py" \
--data "$OUT" --rsrc-dir "$RSRC_DIR" --out "$APL" --sidecar
fi
echo "done: $OUT"