# Apple IIgs build rules. # # Uses GoldenGate's iix to drive ORCA/C 2.1.0 + ORCA Linker. The # toolchains/iigs/iix-build.sh wrapper handles ORCA's case-sensitivity # quirks (lowercase .a/.root/.sym vs linker demands for uppercase), # multi-source compile/link, and pragma injection for include paths # and the stdint/stdbool shim headers. include $(dir $(lastword $(MAKEFILE_LIST)))/common.mk PLATFORM := iigs BUILD := $(REPO_DIR)/build/$(PLATFORM) BINDIR := $(BUILD)/bin PORT_C_SRCS_ALL := $(wildcard $(SRC_PORT)/iigs/*.c) # Hand-rolled .asm sources go through ORCA's macro assembler via # iix-build.sh's `assemble` dispatch. Each .asm declares its target # load segment in the START operand (e.g. peislam.asm -> PEISLAMS) # so the linker places its bytes in a separate bank from _ROOT. # See ORCA/M for IIgs ch. 6 "Load Segments" for the mechanism. PORT_ASM_SRCS_ALL := $(wildcard $(SRC_PORT)/iigs/*.asm) # audio_full.c declares its functions in the AUDIOIMPL load segment # (`segment "AUDIOIMPL"` at file scope, see ORCA/C ch. 30) so the # implementation code lives in its own bank, not _ROOT. That lets # the same source link into every binary, replacing the earlier # audio.c-stub vs audio_full.c-real split. The 34 KB NTP replayer # bytes still ride along via the xxd-baked header. PORT_C_SRCS := $(PORT_C_SRCS_ALL) # IIgs uses NTPstreamsound for SFX, not the libxmp+overlay combo that # DOS and ST share, so src/core/audioSfxMix.c is unused here. Filter # it out so the ORCA Linker doesn't pull its dead code into every # IIgs binary (the monolithic-link budget is tight). CORE_C_SRCS_IIGS := $(filter-out %/audioSfxMix.c, $(CORE_C_SRCS)) # Sprite codegen: 65816 emitter + cross-platform compile dispatch. CODEGEN_SRCS := $(REPO_DIR)/src/codegen/spriteEmitIigs.c \ $(REPO_DIR)/src/codegen/spriteCompile.c # NinjaTrackerPlus replayer. Assembled with Merlin32 from the staged # source at toolchains/iigs/ntp/ninjatrackerplus.s. Output is a 34 KB # raw 65816 binary that the IIgs audio HAL loads at runtime via # Memory Manager into a fixed-bank handle. NTP source is bank-internal # (no JSL/JML cross-bank jumps) so the player works at any bank-start # load address even though it was assembled with `org $0F0000`. NTP_SRC := $(REPO_DIR)/toolchains/iigs/ntp/ninjatrackerplus.s NTP_BIN := $(BUILD)/audio/ntpplayer.bin NTP_ASM := $(BUILD)/audio/ntpdata.asm IIGS_MERLIN := $(REPO_DIR)/toolchains/iigs/merlin32/bin/merlin32 # IMPORTANT: CODEGEN_SRCS (specifically spriteEmitIigs.c) MUST be the # first entry after the main object in the link order. ORCA-Linker's # bank assignment is order-sensitive: when spriteEmitIigs.c lands at # any later position, the linker assigns SPRITECG to a bank where its # intra-OMF-segment static-symbol relocations (emitMvnCopyRoutine, # shiftedByteAt, writeLE16) can't be encoded -- you get cryptic # "Addressing error" / "Unresolved reference Label: ..." failures # whose root cause is bank packing, not source. Putting CODEGEN_SRCS # first gives SPRITECG prime placement and the relocations resolve. # This was the underlying cause of feedback_orca_link_segment_count # cases 2-5 (we'd been working around it by managing _ROOT mass). LIB_SRCS := $(CODEGEN_SRCS) $(CORE_C_SRCS_IIGS) $(PORT_C_SRCS) $(PORT_ASM_SRCS_ALL) $(NTP_ASM) HELLO_SRC := $(EXAMPLES)/hello/hello.c HELLO_BIN := $(BINDIR)/HELLO PATTERN_SRC := $(EXAMPLES)/pattern/pattern.c PATTERN_BIN := $(BINDIR)/PATTERN DRAW_SRC := $(EXAMPLES)/draw/draw.c DRAW_BIN := $(BINDIR)/DRAW KEYS_SRC := $(EXAMPLES)/keys/keys.c KEYS_BIN := $(BINDIR)/KEYS JOY_SRC := $(EXAMPLES)/joy/joy.c JOY_BIN := $(BINDIR)/JOY SPRITE_SRC := $(EXAMPLES)/sprite/sprite.c SPRITE_BIN := $(BINDIR)/SPRITE AUDIO_SRC := $(EXAMPLES)/audio/audio.c AUDIO_BIN := $(BINDIR)/AUDIO AUDIO_MOD := $(REPO_DIR)/assets/test.mod AUDIO_SFX := $(REPO_DIR)/assets/test.sfx AUDIO_NTP := $(BUILD)/audio/test.ntp AUDIO_HEADER := $(BUILD)/audio/test_assets.h JOEYMOD := $(REPO_DIR)/tools/joeymod/joeymod DISK_IMG := $(BINDIR)/joey.2mg IIGS_PACKAGE := $(REPO_DIR)/toolchains/iigs/package-disk.sh IIX_INCLUDES := \ -I $(IIGS_INCLUDE_SHIM) \ -I $(INCLUDE_DIR) \ -I $(INCLUDE_DIR)/joey \ -I $(SRC_CORE) \ -I $(REPO_DIR)/src/codegen .PHONY: all iigs iigs-disk clean-iigs # Building the disk implicitly builds every binary it depends on, so # `make iigs` ends with a fresh joey.2mg on every change. Without this, # stale disk images would silently mask binary updates -- a surprise # when the run script always boots from joey.2mg. all iigs: $(DISK_IMG) $(NTP_BIN): $(NTP_SRC) $(IIGS_MERLIN) @mkdir -p $(dir $@) @cp $(NTP_SRC) $(BUILD)/audio/ninjatrackerplus.s cd $(BUILD)/audio && $(IIGS_MERLIN) . ninjatrackerplus.s mv $(BUILD)/audio/ntpplayer $@ # Bake the NTP replayer bytes into an ORCA-M asm file. The asm declares # the bytes in a `data NTPDATA` segment; ORCA's linker groups same- # name object segments into one load segment, and the GS/OS loader # places it in its own bank. Net effect: the 34 KB of NTP bytes don't # crowd _ROOT in any binary, so audio_full.c can link into every demo # (vs the old audio.c-stub split). audio_full.c references # gNtpPlayerBytes / gNtpPlayerBytes_len as externs (case-sensitive # symbol match against the asm labels). $(NTP_ASM): $(NTP_BIN) $(REPO_DIR)/toolchains/iigs/bin-to-asm.sh @mkdir -p $(dir $@) $(REPO_DIR)/toolchains/iigs/bin-to-asm.sh $(NTP_BIN) $@ NTPDATA gNtpPlayerBytes gNtpPlayerBytes_len # iix-build.sh takes MAIN.c first, then EXTRA sources (compiled with # #pragma noroot). The example source supplies main(); libjoey sources # are the extras. The chtyp post-step tags the output as GS/OS S16 # ($B3) so GS/OS recognizes it as launchable; the file-type lives in # a user.com.apple.FinderInfo xattr that iix and profuse preserve. # # All binaries use ORCA-C large memory model (-b). Cost: slightly # larger / slower compiled C per the ORCA docs. Win: 32-bit pointers # everywhere, so library asm can take SurfaceT* args via one # consistent ABI (small-mm 16-bit pointers truncated bank bytes, # which broke any asm that wanted to address bank-1 stage memory). $(HELLO_BIN): $(HELLO_SRC) $(LIB_SRCS) $(NTP_ASM) $(IIGS_BUILD) @mkdir -p $(dir $@) $(IIGS_BUILD) -b $(IIX_INCLUDES) -o $@ $(HELLO_SRC) $(LIB_SRCS) $(IIGS_IIX) chtyp -t S16 $@ $(PATTERN_BIN): $(PATTERN_SRC) $(LIB_SRCS) $(NTP_ASM) $(IIGS_BUILD) @mkdir -p $(dir $@) $(IIGS_BUILD) -b $(IIX_INCLUDES) -o $@ $(PATTERN_SRC) $(LIB_SRCS) $(IIGS_IIX) chtyp -t S16 $@ $(DRAW_BIN): $(DRAW_SRC) $(LIB_SRCS) $(NTP_ASM) $(IIGS_BUILD) @mkdir -p $(dir $@) $(IIGS_BUILD) -b $(IIX_INCLUDES) -o $@ $(DRAW_SRC) $(LIB_SRCS) $(IIGS_IIX) chtyp -t S16 $@ $(KEYS_BIN): $(KEYS_SRC) $(LIB_SRCS) $(NTP_ASM) $(IIGS_BUILD) @mkdir -p $(dir $@) $(IIGS_BUILD) -b $(IIX_INCLUDES) -o $@ $(KEYS_SRC) $(LIB_SRCS) $(IIGS_IIX) chtyp -t S16 $@ $(JOY_BIN): $(JOY_SRC) $(LIB_SRCS) $(NTP_ASM) $(IIGS_BUILD) @mkdir -p $(dir $@) $(IIGS_BUILD) -b $(IIX_INCLUDES) -o $@ $(JOY_SRC) $(LIB_SRCS) $(IIGS_IIX) chtyp -t S16 $@ $(SPRITE_BIN): $(SPRITE_SRC) $(LIB_SRCS) $(NTP_ASM) $(IIGS_BUILD) @mkdir -p $(dir $@) $(IIGS_BUILD) -b $(IIX_INCLUDES) -o $@ $(SPRITE_SRC) $(LIB_SRCS) $(IIGS_IIX) chtyp -t S16 $@ # Convert the cross-platform .MOD asset to NinjaTrackerPlus runtime # format via joeymod (which shells out to ntpconverter.php). Without # php-cli the conversion is skipped; in that case the IIgs disk just # won't carry a TEST.NTP and the audio demo will report "missing data # file" at runtime instead of crashing on bad MOD magic. HAVE_PHP := $(shell command -v php >/dev/null 2>&1 && echo 1) ifeq ($(HAVE_PHP),1) $(AUDIO_NTP): $(AUDIO_MOD) $(JOEYMOD) @mkdir -p $(dir $@) $(JOEYMOD) $< $@ AUDIO_DATA_FILES := $(AUDIO_NTP) $(AUDIO_SFX) else $(info iigs: php-cli not installed -- AUDIO demo will ship without TEST.NTP; install php-cli for real IIgs audio playback) AUDIO_DATA_FILES := $(AUDIO_SFX) endif $(AUDIO_BIN): $(AUDIO_SRC) $(LIB_SRCS) $(NTP_ASM) $(IIGS_BUILD) @mkdir -p $(dir $@) $(IIGS_BUILD) -b $(IIX_INCLUDES) -I $(EXAMPLES)/audio -o $@ $(AUDIO_SRC) $(LIB_SRCS) $(IIGS_IIX) chtyp -t S16 $@ # Assemble an 800KB ProDOS 2img containing the examples, ready to # mount in GSplus alongside a GS/OS boot volume. iigs-disk: $(DISK_IMG) $(DISK_IMG): $(HELLO_BIN) $(PATTERN_BIN) $(DRAW_BIN) $(KEYS_BIN) $(JOY_BIN) $(SPRITE_BIN) $(AUDIO_BIN) $(AUDIO_DATA_FILES) $(IIGS_PACKAGE) @mkdir -p $(dir $@) $(IIGS_PACKAGE) $@ $(HELLO_BIN) $(PATTERN_BIN) $(DRAW_BIN) $(KEYS_BIN) $(JOY_BIN) $(SPRITE_BIN) $(AUDIO_BIN) -- $(AUDIO_DATA_FILES) clean-iigs: rm -rf $(BUILD)