# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License. # See LICENSE.md for license information. # SPDX-License-Identifier: MIT # # Amiga (Bebbo m68k-amigaos-gcc) build rules: JoeyLib's library for the # Amiga, and programRules, the Amiga's rules for one program, which # make/programs.mk instantiates for every program (a project reaches both # through make/project.mk). JoeyLib's own examples are at the end. PLATFORM := amiga include $(dir $(lastword $(MAKEFILE_LIST)))/common.mk $(call requireTool,$(AMIGA_CC),toolchain:amiga) $(call requireTool,$(AMIGA_AS),toolchain:amiga) $(call requireTool,$(AMIGA_PTPLAYER)/ptplayer.asm,toolchain:amiga) # PTPlayer is installed by ./install.sh (AMIGA_PTPLAYER); we # reference its ptplayer.asm + header from there rather than copying # them into the source tree, so the installer can refresh / version it # independently. -I on $(SRC_DIR)/amiga lets ptplayer.h resolve # from the machine-local shim alongside our code. PTPLAYER_DIR := $(AMIGA_PTPLAYER) CFLAGS := $(COMMON_CFLAGS) -m68000 -fomit-frame-pointer -noixemul -D__OSCOMPAT -I$(SRC_DIR)/amiga -I$(SRC_68K) -I$(PTPLAYER_DIR) -MMD -MP # OSCOMPAT=1 selects PTPlayer's audio.device-friendly variant (uses # CIA-B + audio.device interrupts via the OS rather than taking over # Paula directly), matching the way our HAL cooperates with Intuition. # vasm is only invoked for ptplayer.asm here -- Frank Wille's source # is written in Devpac/vasm syntax and there is no maintained GAS- # syntax port. JoeyLib's own .s files are GAS syntax and assembled by # the bundled m68k-amigaos-as via the gcc driver. # -Fhunk matches Bebbo gcc-amigaos's AmigaOS HUNK object format. ELF # objects from vasm cannot be linked into a HUNK libjoey.a (the ar # "file format not recognized" failure mode is silent at archive time # and surfaces as undefined references at every binary's link step). PTPLAYER_ASFLAGS := -Fhunk -m68000 -quiet -DOSCOMPAT=1 # --allow-multiple-definition lets our user-space tzset stub # (src/amiga/libinit.c) win over libnix's version in # __gmtoffset.o. libnix's tzset dereferences a possibly-NULL # LocaleBase; our no-op skips the deref. LDFLAGS := -noixemul -Wl,--allow-multiple-definition PORT_C_SRCS := $(wildcard $(SRC_DIR)/amiga/*.c) PORT_S_SRCS := $(wildcard $(SRC_DIR)/amiga/*.s) SHARED_S := $(wildcard $(SRC_68K)/*.s) # Amiga uses PTPlayer's mt_playfx for SFX, not the libxmp+overlay # combo that DOS and ST share, so the shared SFX overlay mixer in # src/core/audioSfxMix.c is unused here. Filter it out to keep dead # code out of every Amiga binary. CORE_C_SRCS_AMIGA := $(filter-out %/audioSfxMix.c, $(CORE_C_SRCS)) # Sprite codegen: the Amiga-planar emitter (spriteEmitPlanar68k.c) lives in # src/m68k/ and builds into obj/68k/; only the CPU-independent dispatch stays # in src/codegen. CODEGEN_DIR := $(REPO_DIR)/src/codegen LIB_OBJS := \ $(patsubst $(SRC_CORE)/%.c,$(BUILD)/obj/core/%.o,$(CORE_C_SRCS_AMIGA)) \ $(patsubst $(SRC_DIR)/generic/%.c,$(BUILD)/obj/generic/%.o,$(GENERIC_C_SRCS)) \ $(patsubst $(SRC_DIR)/amiga/%.c,$(BUILD)/obj/port/%.o,$(PORT_C_SRCS)) \ $(patsubst $(SRC_DIR)/amiga/%.s,$(BUILD)/obj/port/%.o,$(PORT_S_SRCS)) \ $(patsubst $(SRC_68K)/%.s,$(BUILD)/obj/68k/%.o,$(SHARED_S)) \ $(BUILD)/obj/port/ptplayer.o \ $(BUILD)/obj/68k/spriteEmitPlanar68k.o \ $(BUILD)/obj/codegen/spriteCompile.o \ $(BUILD)/obj/codegen/spriteStage.o LIB := $(LIBDIR)/libjoey.a $(BUILD)/obj/core/%.o: $(SRC_CORE)/%.c @mkdir -p $(dir $@) $(AMIGA_CC) $(CFLAGS) -c $< -o $@ $(BUILD)/obj/generic/%.o: $(SRC_DIR)/generic/%.c @mkdir -p $(dir $@) $(AMIGA_CC) $(CFLAGS) -c $< -o $@ $(BUILD)/obj/port/%.o: $(SRC_DIR)/amiga/%.c @mkdir -p $(dir $@) $(AMIGA_CC) $(CFLAGS) -c $< -o $@ # Hand-written 68k assembly: GAS syntax, fed through the gcc driver # so the bundled m68k-amigaos-as (binutils) does the work. $(BUILD)/obj/port/%.o: $(SRC_DIR)/amiga/%.s @mkdir -p $(dir $@) $(AMIGA_CC) $(CFLAGS) -c $< -o $@ # PTPlayer is third-party Devpac/vasm-syntax assembly with no # maintained GAS port; vasm is invoked only here. $(BUILD)/obj/port/ptplayer.o: $(PTPLAYER_DIR)/ptplayer.asm @mkdir -p $(dir $@) $(AMIGA_AS) $(PTPLAYER_ASFLAGS) $< -o $@ $(BUILD)/obj/codegen/%.o: $(CODEGEN_DIR)/%.c @mkdir -p $(dir $@) $(AMIGA_CC) $(CFLAGS) -I$(CODEGEN_DIR) -c $< -o $@ $(BUILD)/obj/68k/%.o: $(SRC_68K)/%.s @mkdir -p $(dir $@) $(AMIGA_CC) $(CFLAGS) -c $< -o $@ # 68k sprite emitters (spriteEmitPlanar68k.c) live in src/m68k/; # -I$(CODEGEN_DIR) lets them resolve spriteEmitter.h. $(BUILD)/obj/68k/%.o: $(SRC_68K)/%.c @mkdir -p $(dir $@) $(AMIGA_CC) $(CFLAGS) -I$(CODEGEN_DIR) -c $< -o $@ # Archived from scratch, so the members -- and every program's layout -- # follow LIB_OBJS rather than the order earlier builds added them in. $(LIB): $(LIB_OBJS) @mkdir -p $(dir $@) rm -f $@ $(AMIGA_AR) rcs $@ $^ # Pull in per-object header-dependency files generated by gcc -MMD/-MP. # Without this, editing a header (e.g. surfaceInternal.h) doesn't rebuild # the .c files that include it, leaving a frankenstein binary where # different TUs see different struct layouts. -include $(LIB_OBJS:.o=.d) # ---- programs ----------------------------------------------------------------- # A program is a mixed-case Name with no extension (an AmigaDOS name), in bin/ # or in its own bin/Name/ with its DATA beside it; joey-run boots the folder # as the JOEYLIB hard drive. PROGRAM_EXT := PROGRAM_FOLDERS := yes programNameRule = $(call capFirst,$(call lc,$(1))) # One program, $(1) its id: compiled and linked in one step with the library. # gcc's -MMD leaves Name.d beside it, for header edits. define programRules $(call programBin,$(1)): $(call programVar,$(1),SRCS) $(LIB) @mkdir -p $$(dir $$@) $(AMIGA_CC) $(CFLAGS) $(call programVar,$(1),CFLAGS) $(call programVar,$(1),SRCS) $(LIB) -o $$@ $(LDFLAGS) $(call programVar,$(1),LDFLAGS) -include $(call programBin,$(1)).d endef # ---- JoeyLib's own build: its examples ------------------------------------------ ifndef JOEY_PROJECT include $(REPO_DIR)/make/examples.mk include $(REPO_DIR)/make/programs.mk .DEFAULT_GOAL := all .PHONY: all amiga clean-amiga clean all amiga: $(LIB) programs clean-amiga: rm -rf $(BUILD) # `clean` as an alias for `clean-amiga`. Without it a bare # `make -f make/amiga.mk clean` FAILS -- and with stderr discarded that # looks like success while leaving stale objects the next build links. clean: clean-amiga endif