# Apple IIgs build rules (llvm-mos w65816: clang + llvm-mc + link816). # # make/support/iigs/clang-build.sh drives compile (clang) / assemble # (llvm-mc) / link (link816) against the prebuilt w65816 runtime. # Hand-rolled asm lives in src/iigs/*.s (llvm-mc GAS syntax); # bank placement is handled by -ffunction-sections + link816 # dead-stripping. # # STATUS: the launchable-binary pipeline (multi-segment OMF emission + # disk packaging + GS/OS launch) is still being brought up. `iigs-lib` # compile-checks every library + example translation unit, and # `iigs-clang-smoke` (not part of the default goal: it needs MAME) # validates the full clang -> llvm-mc -> link816 -> MAME path end to end. Per-example binary targets build via # clang-build.sh; large examples need the multi-segment OMF wiring still # in progress. include $(dir $(lastword $(MAKEFILE_LIST)))/common.mk PLATFORM := iigs BUILD := $(REPO_DIR)/build/$(PLATFORM) BINDIR := $(BUILD)/bin OBJDIR := $(BUILD)/obj CLANG := $(LLVM816_ROOT)/tools/llvm-mos-build/bin/clang $(call requireTool,$(CLANG),toolchain:iigs) $(call requireTool,$(IIGS_AS),toolchain:iigs) $(call requireTool,$(IIGS_NTP_DIR)/ninjatrackerplus.s,toolchain:iigs) LLVM_MC := $(LLVM816_ROOT)/tools/llvm-mos-build/bin/llvm-mc AR := $(LLVM816_ROOT)/tools/llvm-mos-build/bin/llvm-ar CCWRAP := $(LLVM816_ROOT)/scripts/ccRegallocFallback.sh RT_INC := $(LLVM816_ROOT)/runtime/include CFLAGS := --target=w65816 -O2 -ffreestanding -ffunction-sections $(EXTRA_CFLAGS) INCLUDES := -I$(RT_INC) -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/joey -I$(SRC_CORE) -I$(REPO_DIR)/src/codegen LIBDIR := $(BUILD)/lib LIB := $(LIBDIR)/libjoey.a PORT_C_SRCS := $(wildcard $(SRC_DIR)/iigs/*.c) # Hand-rolled asm, migrated to llvm-mc GAS .s. PORT_ASM_SRCS := $(wildcard $(SRC_DIR)/iigs/*.s) # IIgs uses NTPstreamsound for SFX, not the libxmp+overlay combo that # DOS and ST share, so src/core/audioSfxMix.c is unused here. CORE_C_SRCS_IIGS := $(filter-out %/audioSfxMix.c, $(CORE_C_SRCS)) # Sprite codegen: the 65816 emitter (spriteEmitIigs.c) now lives in src/iigs/ # and is picked up by PORT_C_SRCS; only the CPU-independent compile dispatch # remains in src/codegen. CODEGEN_SRCS := $(REPO_DIR)/src/codegen/spriteCompile.c $(REPO_DIR)/src/codegen/spriteStage.c LIB_C_SRCS := $(CORE_C_SRCS_IIGS) $(GENERIC_C_SRCS) $(PORT_C_SRCS) $(CODEGEN_SRCS) LIB_SRCS := $(LIB_C_SRCS) $(PORT_ASM_SRCS) # Library header set for archive rebuild triggering (coarse on purpose: any # header change forces a full lib recompile -- a needless rebuild is safe, a # missed one is not). IIGS_LIB_HDRS := $(wildcard $(INCLUDE_DIR)/joey/*.h) $(wildcard $(SRC_CORE)/*.h) $(wildcard $(REPO_DIR)/src/codegen/*.h) $(wildcard $(SRC_DIR)/iigs/*.h) $(wildcard $(REPO_DIR)/src/m68k/*.h) # Example sources (single-TU unless noted). PATTERN_SRC := $(EXAMPLES)/pattern/pattern.c DRAW_SRC := $(EXAMPLES)/draw/draw.c KEYS_SRC := $(EXAMPLES)/keys/keys.c SERIAL_SRC := $(EXAMPLES)/serial/serial.c SERTEST_SRC := $(EXAMPLES)/sertest/sertest.c SCCPROBE_SRC := $(EXAMPLES)/sccprobe/sccprobe.c SERLOSS_SRC := $(EXAMPLES)/serloss/serloss.c SAVE_SRC := $(EXAMPLES)/save/save.c TILEBANK_SRC := $(EXAMPLES)/tilebank/tilebank.c JOY_SRC := $(EXAMPLES)/joy/joy.c SPRITE_SRC := $(EXAMPLES)/sprite/sprite.c UBER_SRC := $(EXAMPLES)/uber/uber.c ADV_SRC := $(EXAMPLES)/adventure/adventure.c ADV2_SRC := $(EXAMPLES)/adventure2/adventure2.c AGI_SRCS := $(EXAMPLES)/agi/agi.c $(EXAMPLES)/agi/agiRes.c $(EXAMPLES)/agi/agiPic.c $(EXAMPLES)/agi/agiView.c $(EXAMPLES)/agi/agiVm.c $(EXAMPLES)/agi/agiObj.c $(EXAMPLES)/agi/agiText.c STAXI_SRCS := $(EXAMPLES)/spacetaxi/stC64Data.c $(EXAMPLES)/spacetaxi/stCels.c $(EXAMPLES)/spacetaxi/stSim.c $(EXAMPLES)/spacetaxi/spacetaxi.c $(EXAMPLES)/spacetaxi/stLevel.c $(EXAMPLES)/spacetaxi/stLevelFile.c $(EXAMPLES)/spacetaxi/stRender.c $(EXAMPLES)/spacetaxi/stFare.c $(EXAMPLES)/spacetaxi/stHooks.c $(EXAMPLES)/spacetaxi/stTitle.c $(EXAMPLES)/spacetaxi/stAudio.c $(EXAMPLES)/spacetaxi/stLevelCels.c AUDIO_SRC := $(EXAMPLES)/audio/audio.c # TILEBANK's DATA/tilebank: this port's bake of the tile-bank fixture, the # other targets' bakes it must refuse, and the expected pixels (common.mk). # make-iigs-disk.sh packs it as /JOEYLIB/DATA/TILEBANK beside the program. TILEBANK_DATA := $(BINDIR)/DATA/tilebank/own.tbk # NinjaTrackerPlus replayer: Merlin32-assemble ninjatrackerplus.s to a 34KB # binary that ships next to the program; jlpAudioInit loads "ntpplayer" from # disk at run time (see the $(BINDIR)/AUDIO rule). The source is assembled # with JoeyLib's interrupt window added to NTPstreamsound (NTP_PATCH). NTP_SRC := $(IIGS_NTP_DIR)/ninjatrackerplus.s NTP_PATCH := $(REPO_DIR)/make/support/iigs/ntpIrqWindow.py NTP_BIN := $(BUILD)/audio/ntpplayer.bin IIGS_MERLIN := $(IIGS_AS) .PHONY: all iigs iigs-lib iigs-clang-smoke iigs-examples iigs-disk iigs-disk-all iigs-game-disk iigs-game-disks iigs-game-disk-agi iigs-verify-game-disk iigs-verify iigs-verify-all iigs-verify-save iigs-verify-serial iigs-verify-serial-loss iigs-verify-shrtail iigs-verify-tilebank clean-iigs clean # Default: build (compile-check) the library. The MAME smoke test is # `iigs-clang-smoke`; disks and examples are `iigs-disk`. all iigs: iigs-lib # Per-example launchable binaries. STAXI and AUDIO are INCLUDED: the # old exclusion comment ("blocked on deeper toolchain features") went # stale -- STAXI has linked and run since 2026-07-08 (toolchain #77 # fix), and AUDIO's 34KB-rodata blocker was resolved by loading the # NTP replayer from disk (see the $(BINDIR)/AUDIO rule). Leaving them # out made `make iigs` silently test 8-day-old STAXI binaries against # new assets (the 2026-07-20 gear-out/no-flame reports). TILEBANK's staged # DATA rides along, so every disk that packs TILEBANK finds it. iigs-examples: $(BINDIR)/PATTERN $(BINDIR)/DRAW $(BINDIR)/KEYS $(BINDIR)/SERIAL $(BINDIR)/SERTEST $(BINDIR)/SAVE $(BINDIR)/JOY \ $(BINDIR)/SPRITE $(BINDIR)/UBER $(BINDIR)/ADV $(BINDIR)/ADV2 \ $(BINDIR)/AGI $(BINDIR)/STAXI $(BINDIR)/AUDIO $(BINDIR)/TILEBANK $(TILEBANK_DATA) # Build the JOEYLIB data disk (build/iigs/bin/joey.2mg) that the gates, and # `joey-run build/iigs/bin/joey.2mg`, mount beside GS/OS. Packs the launchable examples as ProDOS S16 apps # (an 800KB floppy can't hold every example; see make-iigs-disk.sh). # NTP_BIN rides along so jlpAudioInit's runtime load of "ntpplayer" finds it # on the volume -- without it every example logs "audioInit failed" (Phase 1 # IIgs stabilization item c: the audio code is wired; the file was missing). # Pre-compiled sprite banks for Space Taxi. Unlike the other ports, the IIgs # asset tree (examples/spacetaxi/generated/iigs) is produced out-of-band, so # we bake the .spc straight from the committed .spr with the host spritebake # tool; make-iigs-disk.sh then find(1)s the whole generated/iigs tree, so the # .spc rides onto the disk automatically once it exists. # The cel bank is GENERATED by staxibake from the game's shared cel table # (stCels.c) + C64 bitmaps, then compiled to a .spc by the host # spritebake; make-iigs-disk.sh find(1)s the whole generated/iigs tree so # the .spc rides onto the disk. The game loads it at boot # (jlSpriteBankLoadPrecompiled) instead of JIT-compiling every cel. STAXICELS_SPR := $(EXAMPLES)/spacetaxi/generated/iigs/sprites/staxicels.spr STAXI_IIGS_SPC := $(STAXICELS_SPR:.spr=.spc) # Per-level hook-sprite banks (see make/dos.mk): baked from the level file # by staxibake --level, pre-compiled for the 65816. make-iigs-disk.sh copies # them onto the floppy last and only while there is room; a missing bank # makes the game JIT-compile that level's cels at entry instead. STAXI_CEL_LEVELS := 07 08 09 10 12 16 17 21 STAXILEVEL_IIGS_SPC := $(foreach n,$(STAXI_CEL_LEVELS),$(EXAMPLES)/spacetaxi/generated/iigs/sprites/level$(n).spc) # Speech baked to 1-bit PCM per passenger pitch (assets/genSpeechPcm.py); # make-iigs-disk.sh picks it up from the generated tree. STAXI_IIGS_SPEECH := $(EXAMPLES)/spacetaxi/generated/iigs/speech.bin $(STAXI_IIGS_SPEECH): $(EXAMPLES)/spacetaxi/stSpeechData.c $(EXAMPLES)/spacetaxi/assets/genSpeechPcm.py @mkdir -p $(dir $@) python3 $(EXAMPLES)/spacetaxi/assets/genSpeechPcm.py $< $@ --biased # Level files: extracted from the C64 game image exactly as on the other # ports (see make/dos.mk), then found by make-iigs-disk.sh in the tree. STAXI_IIGS_LEVELS := $(foreach n,$(STAXI_LEVEL_NUMS),$(EXAMPLES)/spacetaxi/generated/iigs/levels/level$(n).dat) \ $(EXAMPLES)/spacetaxi/generated/iigs/levels/title.dat $(STAXI_IIGS_LEVELS) &: $(STAXI_RAW_DUMP) $(ROMTOLEVEL_BIN) @mkdir -p $(EXAMPLES)/spacetaxi/generated/iigs/levels python3 $(ROMTOLEVEL_BIN) $(STAXI_RAW_DUMP) $(EXAMPLES)/spacetaxi/generated/iigs/levels SPRITEBAKE_IIGS := $(REPO_DIR)/build/tools/spritebake-iigs STAXIBAKE := $(REPO_DIR)/build/tools/staxibake $(SPRITEBAKE_IIGS): $(MAKE) -f $(REPO_DIR)/make/tools.mk spritebake-iigs $(STAXIBAKE): $(MAKE) -f $(REPO_DIR)/make/tools.mk staxibake $(STAXICELS_SPR): $(STAXIBAKE) $(EXAMPLES)/spacetaxi/stCels.c $(EXAMPLES)/spacetaxi/stC64Data.c @mkdir -p $(dir $@) $(STAXIBAKE) $@ $(EXAMPLES)/spacetaxi/generated/iigs/sprites/level%.spr: $(EXAMPLES)/spacetaxi/generated/iigs/levels/level%.dat $(STAXIBAKE) $(EXAMPLES)/spacetaxi/stLevelCels.c @mkdir -p $(dir $@) $(STAXIBAKE) --level $< $@ $(EXAMPLES)/spacetaxi/generated/iigs/sprites/%.spc: $(EXAMPLES)/spacetaxi/generated/iigs/sprites/%.spr $(SPRITEBAKE_IIGS) $(SPRITEBAKE_IIGS) $< $@ iigs-disk: iigs-examples $(NTP_BIN) $(STAXI_IIGS_SPC) $(call staxiData,$(STAXI_IIGS_LEVELS) $(STAXILEVEL_IIGS_SPC)) $(STAXI_IIGS_SPEECH) BINDIR="$(BINDIR)" NTP_BIN="$(NTP_BIN)" $(REPO_DIR)/scripts/make-iigs-disk.sh $(BINDIR)/joey.2mg # ONE self-booting volume per game: a GS/OS system stripped to what JoeyLib # actually uses, a launcher in place of the Finder, and the program in its own # folder so that folder can be copied to a hard drive and run from there. # Boot to the program is 21.8 s against 43.4 s for the two-floppy boot disk. # The size is chosen per example: a program that fits beside a stripped # system gets a bootable 800KB 3.5" floppy, and one that does not (STAXI, # AGI) gets a 2048KB volume, which MAME can only boot off a CFFA2 card # because its 3.5 drive is 800KB GCR: # mame apple2gs -sl7 cffa2 -hard1 build/iigs/bin/STAXI.2mg # Pass GAME=name for a different example, GAME_DISK_SIZE to force a size. # It builds its OWN one-example data image rather than depending on # iigs-disk: the default joey.2mg carries the small examples and NOT STAXI # (see make-iigs-disk.sh's JOEY_DISK_EXAMPLES), and the gates depend on # joey.2mg's exact contents, so this must not rewrite it. GAME ?= STAXI iigs-game-disk: iigs-examples $(NTP_BIN) $(STAXI_IIGS_SPC) $(call staxiData,$(STAXI_IIGS_LEVELS) $(STAXILEVEL_IIGS_SPC)) $(STAXI_IIGS_SPEECH) BINDIR="$(BINDIR)" NTP_BIN="$(NTP_BIN)" JOEY_DISK_EXAMPLES="$(GAME)" \ $(REPO_DIR)/scripts/make-iigs-disk.sh $(BINDIR)/$(GAME)-data.2mg JOEY_GAME_DISK_SIZE="$(or $(GAME_DISK_SIZE),auto)" \ $(REPO_DIR)/scripts/make-iigs-game-disk.sh $(BINDIR)/$(GAME).2mg $(GAME) $(GAME) $(BINDIR)/$(GAME)-data.2mg # Every example that ships as its own bootable volume. AGI is excluded # because its resources come from a different builder (see below). IIGS_GAME_DISKS := DRAW PATTERN KEYS JOY SPRITE SAVE AUDIO ADV ADV2 UBER SERIAL SERTEST STAXI iigs-game-disks: @for g in $(IIGS_GAME_DISKS); do \ $(MAKE) --no-print-directory -f make/iigs.mk iigs-game-disk GAME=$$g || exit 1; \ done # AGI needs King's Quest III's resources, which make-agi-iigs-disk.sh lays # out, so it cannot use the generic one-example data image. It also wants a # bigger Memory Manager pool: run it with -ramsize 8M. AGI_GAME ?= kq3 iigs-game-disk-agi: $(BINDIR)/AGI $(REPO_DIR)/scripts/make-agi-iigs-disk.sh $(BINDIR)/AGI-data.2mg $(AGI_GAME) $(REPO_DIR)/scripts/make-iigs-game-disk.sh $(BINDIR)/AGI.2mg AGI AGI $(BINDIR)/AGI-data.2mg # Boot one game disk headlessly and assert it reaches the program and draws. # An 800KB image goes in the 3.5 drive, a larger one on a CFFA2 card. iigs-verify-game-disk: iigs-game-disk $(REPO_DIR)/scripts/verify-iigs-game-disk.sh $(BINDIR)/$(GAME).2mg # Every launchable example on one image. The full set (~1.7 MB of binaries # plus STAXI's data) will not fit an 800KB 3.5" floppy, so this is a 16 MB # ProDOS hard-disk image (joey-all.2mg): boot it in MAME with # `-sl7 cffa2 -hard1 -hard2 build/iigs/bin/joey-all.2mg` and launch # any example from the JOEYLIB volume in the Finder. iigs-disk-all: iigs-examples $(NTP_BIN) $(STAXI_IIGS_SPC) $(call staxiData,$(STAXI_IIGS_LEVELS) $(STAXILEVEL_IIGS_SPC)) $(STAXI_IIGS_SPEECH) BINDIR="$(BINDIR)" NTP_BIN="$(NTP_BIN)" \ JOEY_DISK_SIZE="16MB" \ JOEY_DISK_EXAMPLES="DRAW PATTERN KEYS JOY SPRITE SERIAL SERTEST SAVE TILEBANK AUDIO UBER ADV2 ADV AGI STAXI" \ $(REPO_DIR)/scripts/make-iigs-disk.sh $(BINDIR)/joey-all.2mg # Headless visual-verification gate: boot GS/OS under MAME, launch the DRAW # example off joey.2mg, and assert the SHR framebuffer was actually rendered # (many distinct colors -> pixels/lines/circles/tiles/flood all drew). Pass # VERIFY_EXAMPLE=name to check a different example. iigs-verify: iigs-disk $(REPO_DIR)/scripts/verify-iigs.sh $(or $(VERIFY_EXAMPLE),draw) # Cross-channel SCC gate: opening the modem port must leave the printer channel # (AppleTalk's) transmitting. Builds its own one-example disk; ~2 min. iigs-verify-serial: $(BINDIR)/SCCPROBE $(REPO_DIR)/scripts/verify-iigs-serial.sh # Receive-loss gate: 4096 bytes streamed at 9600 baud while the program does # nothing but full-screen presents must all arrive. Runs the modem port (SCC) # and a Super Serial Card in slot 2 (6551) on the installed MAME, with the SCC # receive FIFO cut to the real chip's 3 bytes (JOEY_Z80SCC_RX_FIFO=3) and the # card's a2ssc firmware from iigsFirmware; see the script header. ~3 min per mode. # The card runs at SERLOSS_SSC_BAUD: its 6551 holds ONE received byte, so it is # lossless through full-screen presents only up to 2400 (docs/ApiSerial.adoc); # at 9600 this half could never pass. SERLOSS_SSC_BAUD := 2400 iigs-verify-serial-loss: $(BINDIR)/SERLOSS $(BINDIR)/SERLOSSS $(REPO_DIR)/scripts/verify-iigs-serial-loss.sh scc SERLOSS_BAUD=$(SERLOSS_SSC_BAUD) $(REPO_DIR)/scripts/verify-iigs-serial-loss.sh ssc # Boot-verify every launchable example on joey.2mg (per-example thresholds). iigs-verify-all: iigs-disk $(REPO_DIR)/scripts/verify-iigs-all.sh # Gate the 712 display-state bytes ABOVE the pixel block: the SCB array # ($E1:9D00-$9DC7) and all 16 palettes ($E1:9E00-$9FFF). Nothing else in the # tree can see them -- the golden hash covers the STAGE, not $E1, and P9's # pixel compare stops at $9CFF -- so a wrong palette is invisible to every # other gate and shows only as wrong colors on a real screen. That blind spot # is why a phantom "PEI-slam corrupts palettes 1-15" note survived five weeks. # # UBER's shrTailUpload / shrTailSlam rows live behind #ifdef UBER_PROBE, which # no normal build defines, so this target builds its own UBER (never the # goldened one) into a scratch dir, packs a single-app disk, and benches that. # -DUBER_FRAMES=1 shrinks the timing window: a -DUBER_PROBE run at the golden # 16 frames does not fit bench-iigs.sh's MAME cap. The goldened UBER binary, # joey.2mg and joeylog.txt are all left untouched. IIGS_PROBE_DIR := $(BUILD)/probe iigs-verify-shrtail: $(LIB) $(NTP_BIN) @mkdir -p $(IIGS_PROBE_DIR)/bin $(IIGS_CLANG_BUILD) -DUBER_PROBE -DUBER_FRAMES=1 $(INCLUDES) -o $(IIGS_PROBE_DIR)/bin/UBER $(UBER_SRC) $(LIB) BINDIR="$(IIGS_PROBE_DIR)/bin" NTP_BIN="$(NTP_BIN)" JOEY_DISK_EXAMPLES="UBER" \ $(REPO_DIR)/scripts/make-iigs-disk.sh $(IIGS_PROBE_DIR)/uberprobe.2mg BENCH_DATA_DISK="$(IIGS_PROBE_DIR)/uberprobe.2mg" BENCH_OUT_LOG="$(IIGS_PROBE_DIR)/probelog.txt" \ BENCH_MAX_FRAMES="$(or $(PROBE_MAX_FRAMES),45000)" $(REPO_DIR)/scripts/bench-iigs.sh @grep -E 'shrParity|shrTailUpload|shrTailSlam' $(IIGS_PROBE_DIR)/probelog.txt || \ { echo "iigs-verify-shrtail: FAIL - no probe rows captured" >&2; exit 1; } @grep -qE 'shrTail(Upload|Slam) FAIL' $(IIGS_PROBE_DIR)/probelog.txt && \ { echo "iigs-verify-shrtail: FAIL - \$$E1 SCB/palette block mismatched the stage" >&2; exit 1; } || true @echo "iigs-verify-shrtail: PASS" # Tile-bank gate: TILEBANK loads this port's own .tbk bake both ways off its # own one-example disk; both must hash like the host gate's, and every other # target's bake must be refused. NTP_BIN keeps the disk's audio init quiet. iigs-verify-tilebank: $(BINDIR)/TILEBANK $(TILEBANK_DATA) $(NTP_BIN) $(REPO_DIR)/scripts/verify-iigs-tilebank.sh # Runtime gate for the save HAL's GS/OS calls (Create + GetDevNumber/DInfo/ # Volume): boots SAVE under MAME and checks the save-OK lamp + disk-free bar. iigs-verify-save: $(BINDIR)/SAVE $(BINDIR)/DRAW $(REPO_DIR)/scripts/verify-iigs-save.sh $(NTP_BIN): $(NTP_SRC) $(NTP_PATCH) $(IIGS_MERLIN) @mkdir -p $(BUILD)/audio @python3 $(NTP_PATCH) $(NTP_SRC) $(BUILD)/audio/ninjatrackerplus.s cd $(BUILD)/audio && $(IIGS_MERLIN) . ninjatrackerplus.s mv $(BUILD)/audio/ntpplayer $@ # Compile-check every library and example translation unit with clang, # and assemble every .s with llvm-mc. This is the canonical "does the # IIgs source still build" gate while the launchable pipeline is wired. # The real static library: compile every library TU (through the regalloc # fallback, matching clang-build.sh) + assemble every .s, then archive them # into libjoey.a. link816 reads the archive natively and --gc-sections selects # what each example references, so examples link $(LIB) exactly like the other # ports. `iigs-lib' is kept as the canonical build/compile-check entry point. $(LIB): $(LIB_SRCS) $(IIGS_LIB_HDRS) @mkdir -p $(OBJDIR) $(LIBDIR) @set -e; objs=""; \ for c in $(LIB_C_SRCS); do \ o=$(OBJDIR)/$$(echo $$c | sed 's#[/.]#_#g').o; \ echo " CC $$c"; \ $(CCWRAP) $(CLANG) $(CFLAGS) $(INCLUDES) -c $$c -o $$o; \ objs="$$objs $$o"; \ done; \ for s in $(PORT_ASM_SRCS); do \ o=$(OBJDIR)/$$(basename $$s .s).o; \ echo " AS $$s"; \ $(LLVM_MC) -arch=w65816 -filetype=obj $$s -o $$o; \ objs="$$objs $$o"; \ done; \ rm -f $@; \ echo " AR $@"; \ $(AR) rcs $@ $$objs iigs-lib: $(LIB) # End-to-end smoke test: clang -> llvm-mc -> link816 -> MAME, validating # the ported asm computes correctly on emulated hardware. iigs-clang-smoke: $(REPO_DIR)/make/support/iigs/clang-smoke.sh # Per-example binaries via clang-build.sh. clang-build.sh mirrors the # old driver's CLI (-I / -o / -M; -s and -b are accepted no-ops). These # link single-segment today; examples larger than one bank need the # multi-segment OMF wiring still in progress. DEP_DIR := $(BUILD)/dep $(BINDIR)/PATTERN: $(PATTERN_SRC) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/PATTERN.d $(INCLUDES) -o $@ $(PATTERN_SRC) $(LIB) $(BINDIR)/DRAW: $(DRAW_SRC) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/DRAW.d $(INCLUDES) -o $@ $(DRAW_SRC) $(LIB) $(BINDIR)/KEYS: $(KEYS_SRC) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/KEYS.d $(INCLUDES) -o $@ $(KEYS_SRC) $(LIB) $(BINDIR)/SERIAL: $(SERIAL_SRC) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/SERIAL.d $(INCLUDES) -o $@ $(SERIAL_SRC) $(LIB) $(BINDIR)/SERTEST: $(SERTEST_SRC) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/SERTEST.d $(INCLUDES) -o $@ $(SERTEST_SRC) $(LIB) # Cross-channel SCC check: does opening the modem port leave the printer port # (AppleTalk's channel) alive? Driven by scripts/verify-iigs-serial.sh. $(BINDIR)/SCCPROBE: $(SCCPROBE_SRC) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/SCCPROBE.d $(INCLUDES) -o $@ $(SCCPROBE_SRC) $(LIB) # Receive-loss probes for iigs-verify-serial-loss: modem port and slot-2 SSC. $(BINDIR)/SERLOSS: $(SERLOSS_SRC) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/SERLOSS.d $(INCLUDES) -o $@ $(SERLOSS_SRC) $(LIB) $(BINDIR)/SERLOSSS: $(SERLOSS_SRC) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/SERLOSSS.d -DSERLOSS_SLOT=2 -DSERLOSS_BAUD=$(SERLOSS_SSC_BAUD)u $(INCLUDES) -o $@ $(SERLOSS_SRC) $(LIB) $(BINDIR)/SAVE: $(SAVE_SRC) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/SAVE.d $(INCLUDES) -o $@ $(SAVE_SRC) $(LIB) $(BINDIR)/TILEBANK: $(TILEBANK_SRC) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/TILEBANK.d $(INCLUDES) -o $@ $(TILEBANK_SRC) $(LIB) $(TILEBANK_DATA): $(TILEBANK_BAKE_DEPS) python3 $(TILEBANK_STAGE) $(PLATFORM) $(TILEBANK_PNG) $(dir $@) $(BINDIR)/JOY: $(JOY_SRC) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/JOY.d $(INCLUDES) -o $@ $(JOY_SRC) $(LIB) $(BINDIR)/SPRITE: $(SPRITE_SRC) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/SPRITE.d $(INCLUDES) -o $@ $(SPRITE_SRC) $(LIB) $(BINDIR)/UBER: $(UBER_SRC) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/UBER.d $(INCLUDES) -o $@ $(UBER_SRC) $(LIB) $(BINDIR)/ADV: $(ADV_SRC) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/ADV.d $(INCLUDES) -o $@ $(ADV_SRC) $(LIB) $(BINDIR)/ADV2: $(ADV2_SRC) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/ADV2.d $(INCLUDES) -o $@ $(ADV2_SRC) $(LIB) # AGI opts into large overflow segments. --segment-cap bounds the ENTRY # bank (which also holds rodata + bss + heap under the $$C000 IO window); # overflow banks carry text only, so capping them the same way wasted # ~50K per bank. With this AGI links 5 bank-aligned segments instead of # 19, which matters because it already needs -ramsize 4M. Verified by # running KQ3 headless and diffing AGI's own joeylog.txt against the # 19-segment build: identical apart from the embedded build timestamp. # # Both AGI and STAXI opt in; see clang-build.sh for the measurements. $(BINDIR)/AGI: export JOEY_OVERFLOW_CAP := 0xF000 $(BINDIR)/AGI: $(AGI_SRCS) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/AGI.d $(INCLUDES) -I$(EXAMPLES)/agi -o $@ $(AGI_SRCS) $(LIB) # STAXI now also opts into large overflow segments: 26 bank-aligned # segments starved the Memory Manager, so NTP's 34K NewHandle failed and # the IIgs build ran SILENT (gNTPReady stayed 0). Freeing that memory lets # audio initialise; the latent crash that then surfaced is fixed in # src/iigs/audio_full.c (sfxTrigger now requires a running replayer). $(BINDIR)/STAXI: export JOEY_OVERFLOW_CAP := 0xF000 $(BINDIR)/STAXI: $(STAXI_SRCS) $(LIB) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/STAXI.d $(INCLUDES) -I$(EXAMPLES)/spacetaxi -o $@ $(STAXI_SRCS) $(LIB) # AUDIO loads the NTP replayer from disk at runtime: audio_full.c reads # ntpplayer.bin via NTP_PATH instead of baking the 34KB replayer as rodata # (which overflowed bank 0, and clang's IMM16+$BE near form can't reach a far # rodata segment anyway). $(NTP_BIN) is shipped on the application disk next # to the binary. $(BINDIR)/AUDIO: $(AUDIO_SRC) $(LIB) $(NTP_BIN) $(IIGS_CLANG_BUILD) @mkdir -p $(dir $@) $(DEP_DIR) $(IIGS_CLANG_BUILD) -M $(DEP_DIR)/AUDIO.d $(INCLUDES) -o $@ $(AUDIO_SRC) $(LIB) clean-iigs: rm -rf $(BUILD) # `clean` as an alias for `clean-iigs`. Without it a bare # `make -f make/iigs.mk clean` FAILS -- and with stderr discarded that # looks like success while leaving stale objects the next build links. clean: clean-iigs -include $(wildcard $(DEP_DIR)/*.d)