# The MIT License (MIT)
#
# Copyright (C) 2026 Scott Duensing
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

# Music library suite: music.lib compiled from its sources (without its
# shell hooks; the test calls musicIdle and musicAppEnded itself) with
# libxmp-lite and audio.lib, against fake sound, FM and MIDI drivers
# (src/test/audio/fakeDrv.c, fakeSynth.c) built as .drv shared objects
# into the work tree the test runs in, with the bundled OP2 bank there.
# The software FM synthesizer is compared with emu8950 (an OPL2
# emulator, MIT; installed pinned into toolchains/emu8950 by
# installMusicRefs.sh, compiled into this test only; lsan.supp covers its
# one known leak).  Module renders are
# checked against golden/render.txt (UPDATE_GOLDENS=1 rewrites it).

include ../dvxtest/dvxtest.mk

.DEFAULT_GOAL := all

MUSIC_DIR  = $(DVXTEST_ROOT)/src/libs/kpunch/music
AUDIO_DIR  = $(DVXTEST_ROOT)/src/libs/kpunch/audio
FAKE_DIR   = $(DVXTEST_ROOT)/src/test/audio
XMP_DIR    = $(MUSIC_DIR)/thirdparty/libxmp-lite
EMU_DIR    = $(DVXTEST_ROOT)/toolchains/emu8950
BINDIR     = $(DVXTEST_BINDIR)/music
MUSIC_TEST = $(BINDIR)/musicTest
WORKDIR    = $(BINDIR)/work
DRVDIR     = $(WORKDIR)/libs/kpunch/audio/drivers
BANKFILE   = $(WORKDIR)/libs/kpunch/music/genmidi.op2
GOLDEN     = $(abspath golden/render.txt)

LIB_SRCS   = $(filter-out $(MUSIC_DIR)/musicShell.c,$(wildcard $(MUSIC_DIR)/*.c)) $(filter-out $(AUDIO_DIR)/audioShell.c,$(wildcard $(AUDIO_DIR)/*.c))
LIB_OBJS   = $(patsubst $(DVXTEST_ROOT)/src/libs/kpunch/%.c,$(BINDIR)/lib/%.o,$(LIB_SRCS))
XMP_SRCS   = $(wildcard $(XMP_DIR)/src/*.c) $(wildcard $(XMP_DIR)/src/loaders/*.c)
XMP_OBJS   = $(patsubst $(XMP_DIR)/%.c,$(BINDIR)/xmp/%.o,$(XMP_SRCS))
XMP_OPTS   = -DLIBXMP_CORE_PLAYER -DLIBXMP_NO_PROWIZARD -DLIBXMP_NO_DEPACKERS -DBUILDING_STATIC -I$(XMP_DIR)/include -I$(XMP_DIR)/src
EMU_OBJS   = $(BINDIR)/emu8950.o $(BINDIR)/emuadpcm.o

CFLAGS     = $(DVXTEST_CFLAGS) -I$(MUSIC_DIR) -I$(AUDIO_DIR) -I$(XMP_DIR)/include -I$(EMU_DIR) -I$(DVXTEST_ROOT)/src/libs/kpunch -DMUSIC_GOLDEN='"$(GOLDEN)"' -DMUSIC_WORKDIR='"$(WORKDIR)"' -DXMP_TEST_DIR='"$(XMP_DIR)/test"'
XMP_CFLAGS = $(filter-out $(WARNFLAGS) $(DEPFLAGS),$(DVXTEST_CFLAGS)) -w $(XMP_OPTS)

FAKE_DEFS  = -DFAKE_NAME='"pcm"' -DFAKE_PRIORITY=30 -DFAKE_CLOCK=0 -DFAKE_TONE=0 -DFAKE_DAC=1 -DFAKE_RATE=22050 -DFAKE_BITS=16 -DFAKE_CHANNELS=2 -DFAKE_OPEN_OK=1 -DFAKE_PLAY_OK=1
FAKE_DRVS  = $(DRVDIR)/pcm.drv $(DRVDIR)/fmfake.drv $(DRVDIR)/midifake.drv

.PHONY: all run clean

all: run

$(EMU_DIR)/emu8950.c:
	@echo "musicTest: emu8950 is missing; run ./installToolchain.sh (src/test/music/installMusicRefs.sh)" >&2
	@false

$(BINDIR)/lib/%.o: $(DVXTEST_ROOT)/src/libs/kpunch/%.c $(DVX_MAKEFILES)
	@mkdir -p $(dir $@)
	$(HOSTCC) $(CFLAGS) -c -o $@ $<

$(BINDIR)/xmp/%.o: $(XMP_DIR)/%.c $(DVX_MAKEFILES)
	@mkdir -p $(dir $@)
	$(HOSTCC) $(XMP_CFLAGS) -c -o $@ $<

$(BINDIR)/emu%.o: $(EMU_DIR)/emu%.c $(DVX_MAKEFILES)
	@mkdir -p $(BINDIR)
	$(HOSTCC) $(XMP_CFLAGS) -fno-sanitize=undefined -c -o $@ $<

$(DRVDIR)/pcm.drv: $(FAKE_DIR)/fakeDrv.c $(AUDIO_DIR)/audioDrv.h $(DVX_MAKEFILES)
	@mkdir -p $(DRVDIR)
	$(HOSTCC) $(CFLAGS) -shared $(FAKE_DEFS) -o $@ $<

$(DRVDIR)/fmfake.drv: $(FAKE_DIR)/fakeSynth.c $(AUDIO_DIR)/audioDrv.h $(DVX_MAKEFILES)
	@mkdir -p $(DRVDIR)
	$(HOSTCC) $(CFLAGS) -shared -DFAKE_SYN_FM -o $@ $<

$(DRVDIR)/midifake.drv: $(FAKE_DIR)/fakeSynth.c $(AUDIO_DIR)/audioDrv.h $(DVX_MAKEFILES)
	@mkdir -p $(DRVDIR)
	$(HOSTCC) $(CFLAGS) -shared -o $@ $<

$(BANKFILE): $(MUSIC_DIR)/thirdparty/genmidi/GENMIDI.OP2
	@mkdir -p $(dir $@)
	cp $< $@

$(MUSIC_TEST): musicTest.c $(LIB_OBJS) $(XMP_OBJS) $(EMU_OBJS) $(DVX_MAKEFILES) $(DVXTEST_ARCHIVES) | dvxtest-libs
	@mkdir -p $(BINDIR)
	$(HOSTCC) $(CFLAGS) -o $@ $< $(LIB_OBJS) $(XMP_OBJS) $(EMU_OBJS) $(DVXTEST_LINK)

-include $(LIB_OBJS:.o=.d) $(MUSIC_TEST).d

run: $(MUSIC_TEST) $(FAKE_DRVS) $(BANKFILE)
	cd $(BINDIR) && ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=suppressions=$(abspath lsan.supp) ./musicTest

clean:
	rm -rf $(BINDIR)
