# Sharp X68000 (elf2x68k / m68k-xelf-gcc) build rules.
#
# BRING-UP STATE. This builds libjoey.a and the serial example against the
# generic backend -- no native primitives, no audio, no sprite codegen yet.
# See docs/x68000_port.md for what is and is not real.
#
# The toolchain is elf2x68k (BSD-3, gcc 13.4.0 / binutils / newlib), staged into
# toolchains/x68000 by the tarball. m68k-xelf-gcc emits ELF; the driver's
# -Wl,-elf2x68k pass converts it to a Human68k .X.

include $(dir $(lastword $(MAKEFILE_LIST)))/common.mk

# The libxmp-lite rules below define a real target before `all`, which would
# otherwise silently become make's default goal (symptom: a bare `make -f
# make/x68000.mk` reports only "libxmplite.a is up to date" and builds nothing).
.DEFAULT_GOAL := all

PLATFORM := x68000
BUILD    := $(REPO_DIR)/build/$(PLATFORM)
LIBDIR   := $(BUILD)/lib
BINDIR   := $(BUILD)/bin

X68K_ROOT := $(REPO_DIR)/toolchains/x68000/m68k-xelf
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$(REPO_DIR)/toolchains/audio/libxmp-lite/include \
           -I$(SRC_DIR)/x68000 -I$(SRC_68K) -I$(REPO_DIR)/src/codegen -MMD -MP $(CFLAGS_EXTRA)
LDFLAGS := -lm

PORT_C_SRCS := $(wildcard $(SRC_DIR)/x68000/*.c)
# Port-local 68000 asm, if any lands. Empty today: SCB per-band palettes are
# done in the pixel expansion (DOS-style), not with a raster ISR, so the port is
# pure C again.
PORT_S_SRCS := $(wildcard $(SRC_DIR)/x68000/*.s)

# No src/m68k sources yet: those are the planar sprite emitters and the planar
# surface helpers, and this port is still chunky. They come in with the storage
# model decision.
# common.mk filters spriteEmitStub.c out of GENERIC_C_SRCS because every
# shipping port has a real per-CPU emitter. This port does not yet, so add it
# back: jlSpriteCompile returns false and sprites stay INTERPRETER-ONLY, which
# is correct but slow (see the "sprites must be compiled or they interpret"
# note). Replacing this with a real 68k emitter is part of the storage-model
# work -- src/m68k/spriteEmitPlanar68k.c already exists and, on the text-plane
# path, needs only AMIGA_PLANE_STRIDE changed at three sites.
# Real sprite codegen: the shared 68k PLANAR emitter, unchanged. Its
# AMIGA_PLANE_STRIDE is 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/spriteEmitPlanar68k.o \
    $(BUILD)/obj/codegen/spriteCompile.o \
    $(BUILD)/obj/codegen/spriteStage.o

# libxmp-lite: the Protracker decoder shared with the DOS and ST ports. Same
# build recipe as make/atarist.mk -- LIBXMP_CORE_DISABLE_IT keeps it off math.h,
# which this newlib does not usefully provide for a 68000 target.
LIBXMP_DIR    := $(REPO_DIR)/toolchains/audio/libxmp-lite
LIBXMP_SRC    := $(filter-out %/win32.c, $(wildcard $(LIBXMP_DIR)/src/*.c) $(wildcard $(LIBXMP_DIR)/src/loaders/*.c))
LIBXMP_OBJDIR := $(BUILD)/obj/libxmp-lite
LIBXMP_OBJS   := $(patsubst $(LIBXMP_DIR)/src/%.c,$(LIBXMP_OBJDIR)/%.o,$(LIBXMP_SRC))
LIBXMP_AR     := $(LIBDIR)/libxmplite.a
LIBXMP_CFLAGS := -DLIBXMP_CORE_PLAYER -DLIBXMP_CORE_DISABLE_IT -DHAVE_FNMATCH=0 \
                 -I$(LIBXMP_DIR)/include -I$(LIBXMP_DIR)/include/libxmp-lite \
                 -I$(LIBXMP_DIR)/src -Wno-error -w

$(LIBXMP_OBJDIR)/%.o: $(LIBXMP_DIR)/src/%.c
	@mkdir -p $(dir $@)
	$(X68K_CC) $(COMMON_CFLAGS) -m68000 -fomit-frame-pointer $(LIBXMP_CFLAGS) -c $< -o $@

$(LIBXMP_AR): $(LIBXMP_OBJS)
	@mkdir -p $(dir $@)
	$(X68K_AR) rcs $@ $(LIBXMP_OBJS)

LIB := $(LIBDIR)/libjoey.a

PATTERN_SRC := $(EXAMPLES)/pattern/pattern.c
SERIAL_SRC := $(EXAMPLES)/serial/serial.c
UBER_SRC   := $(EXAMPLES)/uber/uber.c
AUDIO_SRC  := $(EXAMPLES)/audio/audio.c

.PHONY: all x68000 x68000-lib x68000-examples x68000-verify-serial x68000-verify-golden clean-x68000 clean

all x68000: x68000-lib x68000-examples

x68000-lib: $(LIB) $(LIBXMP_AR)

x68000-examples: $(BINDIR)/SERIAL.X $(BINDIR)/UBER.X $(BINDIR)/AUDIO.X $(BINDIR)/PATTERN.X

$(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 $@

$(LIB): $(LIB_OBJS)
	@mkdir -p $(dir $@)
	$(X68K_AR) rcs $@ $(LIB_OBJS)

# PATTERN is the SCB acceptance vehicle: 8 bands of 25 lines with 8 gradient
# palettes, so a mis-placed band boundary is immediately visible.
$(BINDIR)/PATTERN.X: $(PATTERN_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(X68K_CC) $(CFLAGS) $(PATTERN_SRC) $(LIB) $(LIBXMP_AR) $(LDFLAGS) -o $@

$(BINDIR)/SERIAL.X: $(SERIAL_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(X68K_CC) $(CFLAGS) $(SERIAL_SRC) $(LIB) $(LIBXMP_AR) $(LDFLAGS) -o $@

# UBER is the golden-hash vehicle: it exercises every public op and prints a
# hash per op, which tools/diff-uber-hashes compares against the IIgs reference.
$(BINDIR)/UBER.X: $(UBER_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(X68K_CC) $(CFLAGS) $(UBER_SRC) $(LIB) $(LIBXMP_AR) $(LDFLAGS) -o $@

# AUDIO exercises both audio paths: JYM1 chip music on the OPM and MOD/SFX
# through the ADPCM channel.
$(BINDIR)/AUDIO.X: $(AUDIO_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(X68K_CC) $(CFLAGS) $(AUDIO_SRC) $(LIB) $(LIBXMP_AR) $(LDFLAGS) -o $@

# Both-directions RS-232C gate (~1 min).
x68000-verify-serial: $(BINDIR)/SERIAL.X
	$(REPO_DIR)/scripts/verify-x68000-serial.sh

# Golden-hash gate against the Apple IIgs reference (~70 min: UBER on the
# generic renderer is slow and must reach jlLogFlush before hashes exist).
x68000-verify-golden: $(LIB) $(LIBXMP_AR)
	$(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

-include $(shell find $(BUILD) -name '*.d' 2>/dev/null)
