#!/usr/bin/env bash # build.sh - compile a demo C source into a GS/OS-loadable OMF. # # Usage: bash demos/build.sh # where demos/.c is the source. Output is # demos/.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] " >&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" # 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 0x1000 --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/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 0x1000 --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/.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"