Files
nyuller/Makefile
T
ballz b7219dccfc Replace src/build.sh with Makefile (GNU make)
New targets:
  help (default)     — show usage (was the -help/--help equivalent)
  compile            — compile main.c → build/nyuller.prg
  run                — compile + run in oscar64 built-in emulator
  run-vice           — compile + run in VICE x64 (foreground)
  run-vice-cycle     — compile + run in VICE x64sc (cycle-exact)
  play               — compile + launch VICE x64 detached
  play-cycle         — compile + launch VICE x64sc detached
  kill               — kill any detached VICE
  clean              — remove build/ artifacts
  build/nyuller.d64  — build the .d64 disk image from the .prg

Optimization: override with 'make OPT=O3' (or O0/O1/O2/Os/g).
Default is -O1 (oscar64 default).

The Makefile builds oscar64 automatically if missing, uses
c1541 to create the .d64 with verification, and passes
-drive8type 1541 to VICE (required for autostart).

Removed src/build.sh and updated all docs (README, tasks.md,
AGENT_CONTEXT.md, GAME.md, helloworld.c) to reference make.
2026-07-18 16:22:38 +02:00

235 lines
10 KiB
Makefile

# nyuller — C64 game (Oscar64 cross-compiler)
# ============================================================
# GNU Make wrapper for building and running via oscar64 / VICE.
#
# Default target: help
# --- paths -------------------------------------------------
ROOT := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
OSCAR64_DIR := $(ROOT)/oscar64
OSCAR64_BIN := $(OSCAR64_DIR)/bin/oscar64
BUILD_DIR := $(ROOT)/build
SRC := main.c
PRG := $(BUILD_DIR)/nyuller.prg
D64 := $(BUILD_DIR)/nyuller.d64
LOG := $(BUILD_DIR)/vice.log
PID_FILE := $(BUILD_DIR)/vice.pid
SRC_DIR := $(ROOT)/src
# --- oscar64 flags ----------------------------------------
# Override with: make OPT=O3 (or O0/O1/O2/Os/g)
OPT ?= O1
OPT_FLAGS := -$(OPT)
# --- VICE flags -------------------------------------------
VICE_FLAGS := +confirmonexit -drive8type 1541
# --- phony targets ----------------------------------------
.PHONY: help compile run run-vice run-vice-cycle-exact \
play play-cycle-exact kill clean ensure-build-dir
# ============================================================
# help (default)
# ============================================================
help:
@echo ""
@echo " nyuller — C64 game (Oscar64 cross-compiler)"
@echo " ──────────────────────────────────────────────"
@echo ""
@echo " Compile"
@echo " make compile main.c → build/nyuller.prg (-O1)"
@echo " make compile same as above"
@echo " make OPT=O3 compile with -O3 (release build)"
@echo " make OPT=O0 compile with -O0 (debug build)"
@echo " make OPT=Os compile with -Os (optimize for size)"
@echo ""
@echo " Run"
@echo " make run compile + run in oscar64 emulator (headless, fast)"
@echo " make run-vice compile + run in VICE x64 (foreground, blocks)"
@echo " make run-vice-cycle compile + run in VICE x64sc (cycle-exact, slow)"
@echo ""
@echo " Play (detached — returns to shell)"
@echo " make play compile + launch VICE x64 in background"
@echo " make play-cycle compile + launch VICE x64sc in background"
@echo " make kill kill any running detached VICE"
@echo ""
@echo " Clean"
@echo " make clean remove build/ artifacts and VICE log/pid files"
@echo ""
@echo " Output (in build/)"
@echo " nyuller.prg loadable C64 program"
@echo " nyuller.d64 disk image wrapping nyuller.prg (for VICE autostart)"
@echo " nyuller.asm full 6502 listing"
@echo " nyuller.map region/section/object placement"
@echo " nyuller.lbl VICE monitor label commands"
@echo ""
@echo " VICE note: -drive8type 1541 is required for autostart to work."
@echo " Without this flag the autostart LOAD\"*\",8,1 fails with ?DEVICE"
@echo " NOT PRESENT. We have the original 1541 ROM installed at:"
@echo " ~/.local/share/vice/DRIVES/dos1541-325302-01+901229-05.bin"
@echo ""
@echo " Default joystick keys in VICE (rebindable under Settings):"
@echo " Port 2 (left, Scoot) W/A/S/D + Left Ctrl (fire)"
@echo " Port 1 (right, Hare) Arrows + Right Shift (fire)"
@echo ""
# ============================================================
# ensure-build-dir
# ============================================================
ensure-build-dir:
@mkdir -p "$(BUILD_DIR)"
# ============================================================
# compile
# ============================================================
compile: ensure-build-dir
@# Build the oscar64 compiler first if it doesn't exist.
@if [ ! -x "$(OSCAR64_BIN)" ]; then \
echo "oscar64 compiler not found at $(OSCAR64_BIN); building it..."; \
cd "$(OSCAR64_DIR)" && make -C make compiler; \
fi
@if [ ! -x "$(OSCAR64_BIN)" ]; then \
echo "error: $(OSCAR64_BIN) is still missing after build" >&2; \
echo " try: cd $(OSCAR64_DIR) && make -C make compiler" >&2; \
exit 1; \
fi
@echo "compiling $(SRC) with $(OSCAR64_BIN) -> $(BUILD_DIR)/"
cd "$(SRC_DIR)" && "$(OSCAR64_BIN)" -i="$(OSCAR64_DIR)/include" -o="$(PRG)" $(OPT_FLAGS) "$(SRC)"
# ============================================================
# run — oscar64 built-in emulator (headless, fast)
# ============================================================
run: ensure-build-dir
@if [ ! -x "$(OSCAR64_BIN)" ]; then \
echo "oscar64 compiler not found at $(OSCAR64_BIN); building it..."; \
cd "$(OSCAR64_DIR)" && make -C make compiler; \
fi
@if [ ! -x "$(OSCAR64_BIN)" ]; then \
echo "error: $(OSCAR64_BIN) is still missing after build" >&2; \
echo " try: cd $(OSCAR64_DIR) && make -C make compiler" >&2; \
exit 1; \
fi
@echo "running $(SRC) in oscar64's built-in emulator"
cd "$(SRC_DIR)" && "$(OSCAR64_BIN)" -i="$(OSCAR64_DIR)/include" -o="$(PRG)" $(OPT_FLAGS) -e "$(SRC)"
# ============================================================
# run-vice — VICE x64 (foreground, blocks terminal)
# ============================================================
run-vice: $(D64)
@echo "running nyuller in VICE x64 (blocking)"
x64 $(VICE_FLAGS) -autostart "$(D64)"
# ============================================================
# run-vice-cycle — VICE x64sc (foreground, cycle-exact, slow)
# ============================================================
run-vice-cycle: $(D64)
@echo "running nyuller in VICE x64sc (cycle-exact, blocking)"
x64sc $(VICE_FLAGS) -autostart "$(D64)"
# ============================================================
# play — VICE x64 detached (returns to shell)
# ============================================================
play: compile $(D64)
@# Kill any previous VICE first.
@existing=$$(pgrep -f 'x64(sc)? \+confirmonexit.*nyuller\.d64' 2>/dev/null || true); \
if [ -n "$$existing" ]; then \
echo "killing previous VICE process(es): $$existing"; \
kill $$existing 2>/dev/null || true; \
sleep 1; \
kill -9 $$existing 2>/dev/null || true; \
fi
@echo "launching VICE x64 in the background with $(D64)..."
@setsid nohup x64 $(VICE_FLAGS) -autostart "$(D64)" \
> "$(LOG)" 2>&1 < /dev/null & echo $$! > "$(PID_FILE)"
@sleep 1
@if kill -0 "$$(cat "$(PID_FILE)")" 2>/dev/null; then \
echo ""; \
echo "VICE launched (PID $$(cat "$(PID_FILE)")). Look for the x64 window on your desktop."; \
echo "Default keys: Port 1 (Hare) = Arrows + Right Shift (fire)"; \
echo " Port 2 (Scoot) = W A S D + Left Ctrl (fire)"; \
echo "Rebind under Settings → Input devices → Joystick settings."; \
echo "To stop VICE later: make kill"; \
echo "Log file: $(LOG)"; \
else \
echo "error: VICE failed to start; see $(LOG) for details" >&2; \
exit 1; \
fi
# ============================================================
# play-cycle — VICE x64sc detached (cycle-exact, returns to shell)
# ============================================================
play-cycle: compile $(D64)
@existing=$$(pgrep -f 'x64(sc)? \+confirmonexit.*nyuller\.d64' 2>/dev/null || true); \
if [ -n "$$existing" ]; then \
echo "killing previous VICE process(es): $$existing"; \
kill $$existing 2>/dev/null || true; \
sleep 1; \
kill -9 $$existing 2>/dev/null || true; \
fi
@echo "launching VICE x64sc in the background with $(D64)..."
@setsid nohup x64sc $(VICE_FLAGS) -autostart "$(D64)" \
> "$(LOG)" 2>&1 < /dev/null & echo $$! > "$(PID_FILE)"
@sleep 1
@if kill -0 "$$(cat "$(PID_FILE)")" 2>/dev/null; then \
echo ""; \
echo "VICE launched (PID $$(cat "$(PID_FILE)")). Look for the x64sc window on your desktop."; \
echo "Default keys: Port 1 (Hare) = Arrows + Right Shift (fire)"; \
echo " Port 2 (Scoot) = W A S D + Left Ctrl (fire)"; \
echo "Rebind under Settings → Input devices → Joystick settings."; \
echo "To stop VICE later: make kill"; \
echo "Log file: $(LOG)"; \
else \
echo "error: VICE failed to start; see $(LOG) for details" >&2; \
exit 1; \
fi
# ============================================================
# kill — stop any detached VICE
# ============================================================
kill:
@# pgrep -f uses ERE: + is a quantifier, so the regex must escape it.
@# x64(sc)? matches both "x64" and "x64sc". The process is launched
@# with the literal argument string `+confirmonexit`.
@pids=$$(pgrep -f 'x64(sc)? \+confirmonexit.*nyuller\.d64' 2>/dev/null || true); \
if [ -n "$$pids" ]; then \
echo "killing VICE process(es): $$pids"; \
kill $$pids 2>/dev/null || true; \
sleep 1; \
kill -9 $$pids 2>/dev/null || true; \
else \
echo "no VICE process running (autostart of nyuller.d64)"; \
fi
@rm -f "$(PID_FILE)" "$(LOG)"
# ============================================================
# $(D64) — build the .d64 disk image from the .prg
# ============================================================
# c1541's exit code is unreliable (the interactive form always
# exits 0 even on failure), so the only reliable success signal
# is listing the disk afterwards and checking the PRG is there.
# The flag-form `c1541 -list image` doesn't work (c1541 treats
# it as a unit number), so we use the interactive heredoc form.
# All c1541 calls are wrapped in `|| true` so the final
# list-and-grep is the authoritative check.
$(D64): $(PRG) | ensure-build-dir
@echo "wrapping $(PRG) in $(D64) (VICE autostart needs a disk image)..."
@c1541 -format ny,of d64 "$(D64)" >/dev/null 2>&1 || true
@echo "write $(PRG)" | c1541 "$(D64)" >/dev/null 2>&1 || true
@if printf "list\nquit\n" | c1541 "$(D64)" 2>/dev/null | grep -q "nyuller.prg"; then \
:; \
else \
echo "error: failed to write $(PRG) to $(D64) (c1541 silently exited 0)" >&2; \
rm -f "$(D64)"; \
exit 1; \
fi
# ============================================================
# clean
# ============================================================
clean:
rm -f "$(PRG)" "$(D64)" "$(BUILD_DIR)/nyuller.asm" "$(BUILD_DIR)/nyuller.map" \
"$(BUILD_DIR)/nyuller.lbl" "$(BUILD_DIR)/nyuller.int" "$(BUILD_DIR)/nyuller.dbj" \
"$(BUILD_DIR)/nyuller.csz" "$(PID_FILE)" "$(LOG)"
@echo "cleaned build/"