# Atari ST (m68k-atari-mint-gcc) build rules.

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

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

# CFLAGS_EXTRA: command-line A/B hook (e.g. make CFLAGS_EXTRA=-DX)
# so flag experiments never edit a tracked file (perf-hunt-2 rank 17).
CFLAGS  := $(COMMON_CFLAGS) -m68000 -fomit-frame-pointer -I$(REPO_DIR)/toolchains/audio/libxmp-lite/include -I$(REPO_DIR)/toolchains/atarist/include-shim -I$(SRC_DIR)/atarist -I$(SRC_68K) -MMD -MP $(CFLAGS_EXTRA)
LDFLAGS :=

# libxmp-lite shared with the DOS port. Built as a static archive that
# provides the Protracker pattern decoder for the ST audio HAL; the
# 68k 4-channel mixer + YM2149 PWM output stage layer on top.
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_OBJDIR)/math_shim.o
LIBXMP_AR      := $(LIBDIR)/libxmplite.a
# LIBXMP_CORE_DISABLE_IT skips the IT-format filter code so libxmp-lite
# doesn't reach for math.h / libm -- mintlib doesn't ship either. We
# target MOD as the authoring format anyway, so dropping IT filter
# support has no impact on JoeyLib's audio.
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

PORT_C_SRCS := $(wildcard $(SRC_DIR)/atarist/*.c)
PORT_S_SRCS := $(wildcard $(SRC_DIR)/atarist/*.s)
SHARED_S    := $(wildcard $(SRC_68K)/*.s)

# Sprite codegen: the ST-interleaved emitter (spriteEmitInterleaved68k.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)) \
    $(patsubst $(SRC_DIR)/generic/%.c,$(BUILD)/obj/generic/%.o,$(GENERIC_C_SRCS)) \
    $(patsubst $(SRC_DIR)/atarist/%.c,$(BUILD)/obj/port/%.o,$(PORT_C_SRCS)) \
    $(patsubst $(SRC_DIR)/atarist/%.s,$(BUILD)/obj/port/%.o,$(PORT_S_SRCS)) \
    $(patsubst $(SRC_68K)/%.s,$(BUILD)/obj/68k/%.o,$(SHARED_S)) \
    $(BUILD)/obj/68k/spriteEmitInterleaved68k.o \
    $(BUILD)/obj/codegen/spriteCompile.o \
    $(BUILD)/obj/codegen/spriteStage.o

LIB := $(LIBDIR)/libjoey.a

HELLO_SRC   := $(EXAMPLES)/hello/hello.c
HELLO_BIN   := $(BINDIR)/HELLO.PRG
PATTERN_SRC := $(EXAMPLES)/pattern/pattern.c
PATTERN_BIN := $(BINDIR)/PATTERN.PRG
DRAW_SRC    := $(EXAMPLES)/draw/draw.c
DRAW_BIN    := $(BINDIR)/DRAW.PRG
KEYS_SRC    := $(EXAMPLES)/keys/keys.c
KEYS_BIN    := $(BINDIR)/KEYS.PRG
SERIAL_SRC  := $(EXAMPLES)/serial/serial.c
SERIAL_BIN  := $(BINDIR)/SERIAL.PRG
SERTEST_SRC := $(EXAMPLES)/sertest/sertest.c
SERTEST_BIN := $(BINDIR)/SERTEST.PRG
SAVE_SRC    := $(EXAMPLES)/save/save.c
SAVE_BIN    := $(BINDIR)/SAVE.PRG
JOY_SRC     := $(EXAMPLES)/joy/joy.c
JOY_BIN     := $(BINDIR)/JOY.PRG
SPRITE_SRC  := $(EXAMPLES)/sprite/sprite.c
SPRITE_BIN  := $(BINDIR)/SPRITE.PRG
AUDIO_SRC   := $(EXAMPLES)/audio/audio.c
AUDIO_BIN   := $(BINDIR)/AUDIO.PRG
UBER_SRC    := $(EXAMPLES)/uber/uber.c
UBER_BIN    := $(BINDIR)/UBER.PRG
ADV_SRC     := $(EXAMPLES)/adventure/adventure.c
ADV_BIN     := $(BINDIR)/ADV.PRG
ADV2_SRC    := $(EXAMPLES)/adventure2/adventure2.c
ADV2_BIN    := $(BINDIR)/ADV2.PRG
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
AGI_BIN     := $(BINDIR)/AGI.PRG
STAXI_SRCS  := $(EXAMPLES)/spacetaxi/spacetaxi.c $(EXAMPLES)/spacetaxi/stLevel.c $(EXAMPLES)/spacetaxi/stRender.c $(EXAMPLES)/spacetaxi/stEngine.c $(EXAMPLES)/spacetaxi/stPassenger.c $(EXAMPLES)/spacetaxi/stHud.c $(EXAMPLES)/spacetaxi/stAudio.c
STAXI_INSTALL_DIR := $(BINDIR)/STAXI
STAXI_BIN   := $(STAXI_INSTALL_DIR)/STAXI.PRG

# Space Taxi asset pipeline (mirrors dos.mk / amiga.mk).
STAXI_SRC_DIR       := $(EXAMPLES)/spacetaxi/assets
STAXI_GEN_DIR       := $(EXAMPLES)/spacetaxi/generated/atarist
STAXI_RUN_DIR       := $(STAXI_INSTALL_DIR)/DATA
# Level data is extracted from the C64 ROM (see dos.mk for the long
# explanation): 24 lettered levels A..X from scenes 0..23 plus the
# title from scene 24, via stuff/spacetaxi/romToLevel.py.
STAXI_RAW_DUMP      := $(REPO_DIR)/stuff/spacetaxi/raw.bin
ROMTOLEVEL_BIN      := $(REPO_DIR)/stuff/spacetaxi/romToLevel.py
STAXI_LEVEL_NUMS    := 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
STAXI_ROM_LEVEL_GEN := $(foreach n,$(STAXI_LEVEL_NUMS),$(STAXI_GEN_DIR)/levels/level$(n).dat) \
                       $(STAXI_GEN_DIR)/levels/title.dat
STAXI_LEVEL_GEN     := $(STAXI_ROM_LEVEL_GEN)
STAXI_TILE_PNGS   := $(STAXI_SRC_DIR)/font.png $(wildcard $(STAXI_SRC_DIR)/tiles/*.png)
STAXI_SPRITE_PNGS := $(wildcard $(STAXI_SRC_DIR)/sprites/*.png)
STAXI_TBK_GEN     := $(patsubst $(STAXI_SRC_DIR)/%.png,$(STAXI_GEN_DIR)/%.tbk,$(STAXI_TILE_PNGS))
STAXI_SPR_GEN     := $(patsubst $(STAXI_SRC_DIR)/%.png,$(STAXI_GEN_DIR)/%.spr,$(STAXI_SPRITE_PNGS))
STAXI_LEVEL_RUN   := $(patsubst $(STAXI_GEN_DIR)/%,$(STAXI_RUN_DIR)/%,$(STAXI_LEVEL_GEN))
STAXI_TBK_RUN     := $(patsubst $(STAXI_GEN_DIR)/%,$(STAXI_RUN_DIR)/%,$(STAXI_TBK_GEN))
STAXI_SPR_RUN     := $(patsubst $(STAXI_GEN_DIR)/%,$(STAXI_RUN_DIR)/%,$(STAXI_SPR_GEN))
STAXI_ASSET_DSTS  := $(STAXI_LEVEL_RUN) $(STAXI_TBK_RUN) $(STAXI_SPR_RUN)
# Pre-compiled sprite banks (.spc): baked from the .spr by the host spritebake
# tool for THIS target and staged next to the .spr, so the runtime loads
# compiled routines with no startup JIT (jlSpriteBankLoadPrecompiled). ST is
# the one port whose .spc carries a reloc list (the shifted-DRAW thunk's jmp to
# stSpriteDrawShiftWalker), re-stamped by the loader.
SPRITEBAKE_BIN    := $(REPO_DIR)/build/tools/spritebake-atarist
STAXI_SPC_GEN     := $(STAXI_SPR_GEN:.spr=.spc)
STAXI_SPC_RUN     := $(patsubst $(STAXI_GEN_DIR)/%,$(STAXI_RUN_DIR)/%,$(STAXI_SPC_GEN))
STAXI_ASSET_DSTS  += $(STAXI_SPC_RUN)
ASSETBAKE_BIN     := $(REPO_DIR)/tools/assetbake/assetbake.py
ASSETBAKE_TARGET  := atarist

# Game data lives under bin/DATA/, alongside the binaries Hatari picks
# up when bin/ is mounted as the GEMDOS C: drive. audio.c fopens
# "DATA/test.mod" etc.
DATA_DIR    := $(BINDIR)/DATA
DATA_FILES  := $(DATA_DIR)/test.mod $(DATA_DIR)/test.sfx

.PHONY: all atarist clean-atarist clean
all atarist: $(LIB) $(LIBXMP_AR) $(HELLO_BIN) $(PATTERN_BIN) $(DRAW_BIN) $(KEYS_BIN) $(SERIAL_BIN) $(SERTEST_BIN) $(SAVE_BIN) $(JOY_BIN) $(SPRITE_BIN) $(AUDIO_BIN) $(UBER_BIN) $(ADV_BIN) $(ADV2_BIN) $(AGI_BIN) $(STAXI_BIN) $(DATA_FILES) $(STAXI_ASSET_DSTS)

$(BUILD)/obj/core/%.o: $(SRC_CORE)/%.c
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) -c $< -o $@

$(BUILD)/obj/generic/%.o: $(SRC_DIR)/generic/%.c
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) -c $< -o $@

$(BUILD)/obj/port/%.o: $(SRC_DIR)/atarist/%.c
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) -c $< -o $@

# Hand-written 68k assembly: GAS syntax, fed through the gcc driver
# so the bundled m68k-atari-mint-as (binutils) does the work. No vasm
# dependency on the ST path.
$(BUILD)/obj/port/%.o: $(SRC_DIR)/atarist/%.s
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) -c $< -o $@

$(BUILD)/obj/68k/%.o: $(SRC_68K)/%.s
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) -c $< -o $@

# 68k sprite emitters (spriteEmitInterleaved68k.c) live in src/m68k/;
# -I$(CODEGEN_DIR) lets them resolve spriteEmitter.h.
$(BUILD)/obj/68k/%.o: $(SRC_68K)/%.c
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) -I$(CODEGEN_DIR) -c $< -o $@

$(BUILD)/obj/codegen/%.o: $(CODEGEN_DIR)/%.c
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) -I$(CODEGEN_DIR) -c $< -o $@

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

$(LIBXMP_OBJDIR)/%.o: $(LIBXMP_DIR)/src/%.c
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $(LIBXMP_CFLAGS) -c $< -o $@

$(LIBXMP_OBJDIR)/math_shim.o: $(REPO_DIR)/toolchains/atarist/include-shim/math_shim.c
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) -c $< -o $@

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

$(HELLO_BIN): $(HELLO_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $< $(LIB) $(LIBXMP_AR) -o $@ $(LDFLAGS)

$(PATTERN_BIN): $(PATTERN_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $< $(LIB) $(LIBXMP_AR) -o $@ $(LDFLAGS)

$(DRAW_BIN): $(DRAW_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $< $(LIB) $(LIBXMP_AR) -o $@ $(LDFLAGS)

$(KEYS_BIN): $(KEYS_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $< $(LIB) $(LIBXMP_AR) -o $@ $(LDFLAGS)

$(SERIAL_BIN): $(SERIAL_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $< $(LIB) $(LIBXMP_AR) -o $@ $(LDFLAGS)

$(SERTEST_BIN): $(SERTEST_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $< $(LIB) $(LIBXMP_AR) -o $@ $(LDFLAGS)

$(SAVE_BIN): $(SAVE_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $< $(LIB) $(LIBXMP_AR) -o $@ $(LDFLAGS)

$(JOY_BIN): $(JOY_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $< $(LIB) $(LIBXMP_AR) -o $@ $(LDFLAGS)

$(SPRITE_BIN): $(SPRITE_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $< $(LIB) $(LIBXMP_AR) -o $@ $(LDFLAGS)

$(AUDIO_BIN): $(AUDIO_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $< $(LIB) $(LIBXMP_AR) -o $@ $(LDFLAGS)

$(UBER_BIN): $(UBER_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $< $(LIB) $(LIBXMP_AR) -o $@ $(LDFLAGS)

$(ADV_BIN): $(ADV_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $< $(LIB) $(LIBXMP_AR) -o $@ $(LDFLAGS)

$(ADV2_BIN): $(ADV2_SRC) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $< $(LIB) $(LIBXMP_AR) -o $@ $(LDFLAGS)

$(AGI_BIN): $(AGI_SRCS) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $(AGI_SRCS) $(LIB) $(LIBXMP_AR) -o $@ $(LDFLAGS)

$(STAXI_BIN): $(STAXI_SRCS) $(LIB) $(LIBXMP_AR)
	@mkdir -p $(dir $@)
	$(ST_CC) $(CFLAGS) $(STAXI_SRCS) $(LIB) $(LIBXMP_AR) -o $@ $(LDFLAGS)

# Space Taxi asset pipeline (mirrors dos.mk + amiga.mk).
.SECONDARY: $(STAXI_LEVEL_GEN) $(STAXI_TBK_GEN) $(STAXI_SPR_GEN) $(STAXI_SPC_GEN)

$(STAXI_ROM_LEVEL_GEN) &: $(STAXI_RAW_DUMP) $(ROMTOLEVEL_BIN)
	@mkdir -p $(STAXI_GEN_DIR)/levels
	python3 $(ROMTOLEVEL_BIN) $(STAXI_RAW_DUMP) $(STAXI_GEN_DIR)/levels

$(STAXI_GEN_DIR)/%.tbk: $(STAXI_SRC_DIR)/%.png $(ASSETBAKE_BIN)
	@mkdir -p $(dir $@)
	python3 $(ASSETBAKE_BIN) --type tile --target $(ASSETBAKE_TARGET) $< $@

$(STAXI_GEN_DIR)/%.spr: $(STAXI_SRC_DIR)/%.png $(ASSETBAKE_BIN)
	@mkdir -p $(dir $@)
	python3 $(ASSETBAKE_BIN) --type sprite --cell 3x3 $< $@

$(STAXI_GEN_DIR)/%.spc: $(STAXI_GEN_DIR)/%.spr $(SPRITEBAKE_BIN)
	@mkdir -p $(dir $@)
	$(SPRITEBAKE_BIN) $< $@

$(SPRITEBAKE_BIN):
	$(MAKE) -f $(REPO_DIR)/make/tools.mk spritebake-atarist

$(STAXI_RUN_DIR)/levels/%.dat: $(STAXI_GEN_DIR)/levels/%.dat
	@mkdir -p $(dir $@)
	cp $< $@

$(STAXI_RUN_DIR)/%.tbk: $(STAXI_GEN_DIR)/%.tbk
	@mkdir -p $(dir $@)
	cp $< $@

$(STAXI_RUN_DIR)/%.spr: $(STAXI_GEN_DIR)/%.spr
	@mkdir -p $(dir $@)
	cp $< $@

$(STAXI_RUN_DIR)/%.spc: $(STAXI_GEN_DIR)/%.spc
	@mkdir -p $(dir $@)
	cp $< $@

$(DATA_DIR)/test.mod: $(REPO_DIR)/assets/test.mod
	@mkdir -p $(DATA_DIR)
	cp $< $@

$(DATA_DIR)/test.sfx: $(REPO_DIR)/assets/test.sfx
	@mkdir -p $(DATA_DIR)
	cp $< $@

clean-atarist:
	rm -rf $(BUILD)

# `clean` as an alias for `clean-atarist`. Without it a bare
# `make -f make/atarist.mk clean` FAILS -- and with stderr discarded that
# looks like success while leaving stale objects the next build links.
clean: clean-atarist

# 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)
