# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License. # See LICENSE.md for license information. # SPDX-License-Identifier: MIT # # Sharp X68000 (elf2x68k / m68k-xelf-gcc) build rules. # # The port draws planar into the text plane (src/x68000/halPlanar.c), shares # the Amiga's 68k planar fills, plots and sprite emitter (src/m68k), plays # chip music on the OPM and samples through the ADPCM channel. # # The toolchain is elf2x68k (BSD-3, gcc 13.4.0 / binutils / newlib), installed # by ./install.sh (X68K_ROOT). m68k-xelf-gcc emits ELF; the driver's # -Wl,-elf2x68k pass converts it to a Human68k .X. # # This file holds JoeyLib's library for the X68000 and programRules, the # X68000'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 and the X68000 gates are at the end. PLATFORM := x68000 include $(dir $(lastword $(MAKEFILE_LIST)))/common.mk $(call requireTool,$(X68K_ROOT)/bin/m68k-xelf-gcc,toolchain:x68000) X68K_CC := $(X68K_ROOT)/bin/m68k-xelf-gcc X68K_AR := $(X68K_ROOT)/bin/m68k-xelf-ar # The linker is driven by a wrapper script (m68k-elf/bin/ld.x) that shells out # to `m68k-xelf-ld.bfd` by bare name, so the toolchain's own bin/ MUST be on # PATH or the link dies with "m68k-xelf-ld.bfd: command not found". Compiling # and archiving work fine without it, so this only bites at link time. export PATH := $(X68K_ROOT)/bin:$(PATH) CFLAGS := $(COMMON_CFLAGS) -m68000 -fomit-frame-pointer \ -DJOEYLIB_PLATFORM_X68000 \ -I$(SRC_DIR)/x68000 -I$(SRC_68K) -I$(REPO_DIR)/src/codegen -MMD -MP LDFLAGS := -lm PORT_C_SRCS := $(wildcard $(SRC_DIR)/x68000/*.c) # Raw interrupt shims (timer tick, frame count, SCB raster, SCC receive): each # saves every register and returns with RTE, which a C function cannot. And # the present's copy (x68kPresent.s). PORT_S_SRCS := $(wildcard $(SRC_DIR)/x68000/*.s) # Sprite codegen is the shared 68k PLANAR emitter, unchanged. Its # AMIGA_PLANE_STRIDE is JL_SURFACE_WIDTH/8 = 40, which is this port's surface # stride too -- the display's 128-byte stride never reaches the emitter, which # only ever addresses the surface. So sprites COMPILE here rather than # interpret; spriteEmitStub.o is gone. CODEGEN_DIR := $(REPO_DIR)/src/codegen LIB_OBJS := \ $(patsubst $(SRC_CORE)/%.c,$(BUILD)/obj/core/%.o,$(CORE_C_SRCS)) \ $(patsubst $(SRC_DIR)/generic/%.c,$(BUILD)/obj/generic/%.o,$(GENERIC_C_SRCS)) \ $(patsubst $(SRC_DIR)/x68000/%.c,$(BUILD)/obj/port/%.o,$(PORT_C_SRCS)) \ $(patsubst $(SRC_DIR)/x68000/%.s,$(BUILD)/obj/port/%.o,$(PORT_S_SRCS)) \ $(BUILD)/obj/68k/planarFill.o \ $(BUILD)/obj/68k/planarPlot.o \ $(BUILD)/obj/68k/stageBands.o \ $(BUILD)/obj/68k/modMix.o \ $(BUILD)/obj/68k/sfxMix.o \ $(BUILD)/obj/68k/planarSpriteWalk.o \ $(BUILD)/obj/68k/spriteEmitPlanar68k.o \ $(BUILD)/obj/68k/planarSprite.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 $@) $(X68K_CC) $(CFLAGS) -c $< -o $@ $(BUILD)/obj/generic/%.o: $(SRC_DIR)/generic/%.c @mkdir -p $(dir $@) $(X68K_CC) $(CFLAGS) -c $< -o $@ # Port-local asm. Same object dir as the port C objects; make picks between the # two pattern rules by which prerequisite exists. $(BUILD)/obj/port/%.o: $(SRC_DIR)/x68000/%.s @mkdir -p $(dir $@) $(X68K_CC) $(CFLAGS) -c $< -o $@ $(BUILD)/obj/68k/%.o: $(SRC_68K)/%.s @mkdir -p $(dir $@) $(X68K_CC) $(CFLAGS) -c $< -o $@ $(BUILD)/obj/68k/%.o: $(SRC_68K)/%.c @mkdir -p $(dir $@) $(X68K_CC) $(CFLAGS) -c $< -o $@ $(BUILD)/obj/codegen/%.o: $(CODEGEN_DIR)/%.c @mkdir -p $(dir $@) $(X68K_CC) $(CFLAGS) -I$(CODEGEN_DIR) -c $< -o $@ $(BUILD)/obj/port/%.o: $(SRC_DIR)/x68000/%.c @mkdir -p $(dir $@) $(X68K_CC) $(CFLAGS) -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 $@ $(X68K_AR) rcs $@ $(LIB_OBJS) # Pull in per-object header-dependency files generated by gcc -MMD/-MP, so a # header edit rebuilds every object that includes it. -include $(LIB_OBJS:.o=.d) # ---- programs ----------------------------------------------------------------- # A program is NAME.X, in bin/ or in its own bin/NAME/ with its DATA beside it # (ID_FOLDER: a game's megabyte of data then never rides onto every other # program's floppy); joey-run copies the program and its DATA onto a Human68k # data floppy. PROGRAM_EXT := .X PROGRAM_FOLDERS := yes # One program, $(1) its id: compiled and linked in one step with the library # (the link also leaves NAME.X.elf). gcc's -MMD leaves NAME.d beside it, for # header edits. define programRules $(call programBin,$(1)): $(call programVar,$(1),SRCS) $(LIB) @mkdir -p $$(dir $$@) $(X68K_CC) $(CFLAGS) $(call programVar,$(1),CFLAGS) $(call programVar,$(1),SRCS) $(LIB) $(LDFLAGS) $(call programVar,$(1),LDFLAGS) -o $$@ -include $(basename $(call programBin,$(1))).d endef # ---- JoeyLib's own build: its examples and the X68000 gates ---------------------- ifndef JOEY_PROJECT include $(REPO_DIR)/make/examples.mk include $(REPO_DIR)/make/programs.mk .DEFAULT_GOAL := all .PHONY: all x68000 x68000-lib x68000-examples x68000-verify-audio x68000-verify-serial x68000-verify-mouse x68000-verify-serial-mouse x68000-verify-serial-scb x68000-verify-joy x68000-verify-tilebank x68000-verify-scb x68000-verify-golden clean-x68000 clean all x68000: x68000-lib x68000-examples x68000-lib: $(LIB) x68000-examples: programs # Audio gate: AUDIOPRB (AUDIO pressing its own keys, make/examples.mk) under # MAME with write taps on the OPM, the PPI and the ADPCM: every noise code in # the port's table, the ADPCM fed at 7812 Hz to both speakers (~1 min). x68000-verify-audio: $(call programBin,AUDIOPRB) $(REPO_DIR)/scripts/verify-x68000-audio.sh $(call programBin,AUDIOPRB) # Both-directions RS-232C gate (~1 min). x68000-verify-serial: $(call programBin,SERIAL) $(REPO_DIR)/scripts/verify-x68000-serial.sh # Mouse gate: injected MAME mouse packets through the IOCS ROM into # jlMouse* state, read back from KEYS.X's verification scanline. x68000-verify-mouse: $(call programBin,KEYS) $(REPO_DIR)/scripts/verify-x68000-mouse.sh # Serial + mouse together: both share the SCC, so stream both ways on the # RS-232C port while the mouse moves, and check neither disturbs the other. x68000-verify-serial-mouse: $(call programBin,SERMOUSE) $(REPO_DIR)/scripts/verify-x68000-serial-mouse.sh # Serial + mouse under per-line palette changes: the serial + mouse gate with # examples/sermouse built for a dense SCB at 9600, 19200 and 38400 (~3 min). x68000-verify-serial-scb: $(LIB) $(REPO_DIR)/scripts/verify-x68000-serial-scb.sh # Joystick gate: every direction, both triggers and every release on both # ports, held through MAME's pads and read back from JOY.X's display (~10 s). x68000-verify-joy: $(call programBin,JOY) $(REPO_DIR)/scripts/verify-x68000-joy.sh # Tile-bank gate: this port's own .tbk bake loaded both ways must hash like # the host gate's, and every other target's bake must be refused (~1 min). x68000-verify-tilebank: $(call programBin,TILEBANK) $(TILEBANK_DATA) $(REPO_DIR)/scripts/verify-x68000-tilebank.sh # SCB gate: every text-palette reload of a 147-change screen, timed on the # beam, lands between the last stage pixel of the line above its band and the # band's first (~10 s). x68000-verify-scb: $(call programBin,SCB) $(REPO_DIR)/scripts/verify-x68000-scb.sh # Golden-hash gate against the Apple IIgs reference (~1 min: UBER with # one-frame windows, which is all the hashes need). x68000-verify-golden: $(LIB) $(REPO_DIR)/scripts/verify-x68000-golden.sh clean-x68000: rm -rf $(BUILD) # `clean` as an alias for `clean-x68000`. Without it a bare # `make -f make/x68000.mk clean` FAILS -- and with stderr discarded that # looks like success while leaving stale objects the next build links. clean: clean-x68000 endif