# Kult reconstruction. The shared candidate/oracle/test rules live in the kit.
KIT  := lib/kult-core/tools/recreate_kit
GAME := kult
# The toolchain here is gcc (Alpine); the kit defaults to clang.
CC   := gcc
include $(KIT)/kit.mk

# El core vive en el subtree; el kit sigue usando SRC/CFLAGS.
SRC := $(wildcard lib/kult-core/src/*.c) $(wildcard $(KIT)/src/*.c)
CFLAGS += -Ilib/kult-core/include

# Regenera lib/kult-core/include/addrs.h desde lib/kult-core/symbols/names.txt.
.PHONY: addrs
addrs:
	$(PY) lib/kult-core/tools/gen_addrs.py --write

# Regenera lib/kult-core/docs/mapa/ (fichas por modulo + mapa) desde su src/, names.txt y test/.
.PHONY: mapa
mapa:
	$(PY) lib/kult-core/tools/gen_mapa.py

# Mide la deuda de legibilidad por modulo (docs/LEGIBILIDAD.md).
.PHONY: regscan
regscan:
	$(PY) lib/kult-core/tools/regscan.py

# Core con la API publica restringida por version-script (build on-target).
# El build diferencial (build/libkult.so) NO usa esto: necesita todos los simbolos.
CORE     := build/libkultcore.so
CORE_SRC := $(wildcard lib/kult-core/src/*.c) $(wildcard $(KIT)/src/*.c)
$(CORE): $(CORE_SRC) $(wildcard lib/kult-core/include/*.h) lib/kult-core/kult_core.map
	@mkdir -p build
	$(CC) $(CFLAGS) -shared -Wl,--version-script=lib/kult-core/kult_core.map $(CORE_SRC) -o $(CORE)
.PHONY: core
core: $(CORE)

# La suite diferencial canónica vive en el subtree del core.
.PHONY: test-core
test-core:
	@test -f work/disk_a/KULT.PRG || { echo "falta work/disk_a/KULT.PRG"; exit 2; }
	@mkdir -p lib/kult-core/work
	@ln -sfn ../../../work/disk_a lib/kult-core/work/disk_a
	$(MAKE) -C lib/kult-core test PY=$(abspath $(PY))

# Pruebas propias del port (por ahora ringreport).
.PHONY: test-tools
test-tools:
	$(PY) -m pytest -q test

# Suite completa: core diferencial + HAL/ingesta/packs. La receta que kit.mk
# aporta a `test` ejecuta también `pytest test/`, es decir, la suite de
# test-tools. No se añade test-tools como prerrequisito ni otra receta: así cada
# suite se ejecuta una sola vez y Make no emite warnings por recetas repetidas.
.PHONY: test
test: test-core test-port

# ---------------------------------------------------------------------------
# Port PC: core + boot/ + platform/ + app/. Este build NO usa el modelo del kit:
# `-Iplatform/include` sombrea os.h/hw.h/psg.h/sched.h con la HAL de PC. El
# make test ejecuta la suite del core, la HAL y los tests propios.
#   make port       -> build/kult      headless (PPM), sin SDL
#   make port-sdl   -> build/kult-sdl  con ventana SDL3 (-DHAVE_SDL3)
#   make test-port  -> pruebas de la HAL (sin oráculo)
#   make test       -> core + HAL + tests propios del port
CURSOR_OVERLAY_SRC := platform/cursor_overlay.c
PLATFORM_SRC := $(filter-out platform/video_sdl.c platform/audio_sdl.c platform/mac_dialog.c platform/cursor_overlay.c platform/dispatch_trace.c,$(wildcard platform/*.c))
PORT_CORE_SRC := $(wildcard lib/kult-core/src/*.c)
PORT_SRC     := $(PORT_CORE_SRC) $(PLATFORM_SRC) $(CURSOR_OVERLAY_SRC) $(wildcard boot/*.c) $(wildcard app/*.c)
PORT_INC     := -Iplatform -Iplatform/include -Iboot -Ilib/kult-core/include -Iassets -I$(KIT)/include
PORT_CFLAGS  := -std=c11 -O2 -Wall -Wextra -DKULT_VERSION=\"dev\" $(PORT_INC)
PORT_HDRS    := $(wildcard platform/include/*.h) $(wildcard platform/*.h) \
                $(wildcard lib/kult-core/include/*.h) $(wildcard boot/*.h) $(wildcard app/*.h) \
                platform/cpuwork_costs.inc
PORT_BIN     := build/kult

# T-073b: el core se compila con -finstrument-functions para cobrar el coste
# medido por función (platform/cpuwork.c). Solo en el build del port; el
# diferencial (make test) y test-port no se instrumentan.
PORT_OBJDIR  := build/port-obj
PORT_CORE_O  := $(patsubst lib/kult-core/src/%.c,$(PORT_OBJDIR)/lib/kult-core/src/%.o,$(PORT_CORE_SRC))
PORT_OBJS    := $(patsubst %.c,$(PORT_OBJDIR)/%.o,$(filter-out lib/kult-core/src/%,$(PORT_SRC)))

.PHONY: port
port: $(PORT_BIN)
$(PORT_OBJDIR)/lib/kult-core/src/%.o: lib/kult-core/src/%.c $(PORT_HDRS)
	@mkdir -p $(dir $@)
	$(CC) $(PORT_CFLAGS) -finstrument-functions -c $< -o $@
# El cursor del core se renombra; platform/cursor_overlay.c envuelve la función
# original y decide si el cursor se compone en presentación/captura.
$(PORT_OBJDIR)/lib/kult-core/src/cursor.o: lib/kult-core/src/cursor.c $(PORT_HDRS)
	@mkdir -p $(dir $@)
	$(CC) $(PORT_CFLAGS) -finstrument-functions \
	  -Dcursor_draw=kult_core_cursor_draw \
	  -Dcursor_restore=kult_core_cursor_restore -c $< -o $@
$(PORT_OBJDIR)/%.o: %.c $(PORT_HDRS)
	@mkdir -p $(dir $@)
	$(CC) $(PORT_CFLAGS) -c $< -o $@
$(PORT_BIN): $(PORT_CORE_O) $(PORT_OBJS)
	@mkdir -p build
	$(CC) $^ -o $@

# Ventana SDL3 (M3). Requiere `sdl3` (pkg-config).
SDL3_CFLAGS := $(shell pkg-config --cflags sdl3 2>/dev/null)
SDL3_LIBS   := $(shell pkg-config --libs sdl3 2>/dev/null)
PORT_SDL_BIN := build/kult-sdl
SDL_OBJDIR  := build/port-sdl-obj
SDL_CORE_O  := $(patsubst lib/kult-core/src/%.c,$(SDL_OBJDIR)/lib/kult-core/src/%.o,$(PORT_CORE_SRC))
SDL_OBJS    := $(patsubst %.c,$(SDL_OBJDIR)/%.o,$(filter-out lib/kult-core/src/%,$(PORT_SRC)))
SDL_EXTRA   := platform/video_sdl.c platform/audio_sdl.c
SDL_EXTRA_O := $(patsubst %.c,$(SDL_OBJDIR)/%.o,$(SDL_EXTRA))
.PHONY: port-sdl
port-sdl: $(PORT_SDL_BIN)
$(SDL_OBJDIR)/lib/kult-core/src/%.o: lib/kult-core/src/%.c $(PORT_HDRS)
	@mkdir -p $(dir $@)
	$(CC) $(PORT_CFLAGS) -DHAVE_SDL3 $(SDL3_CFLAGS) -finstrument-functions -c $< -o $@
$(SDL_OBJDIR)/lib/kult-core/src/cursor.o: lib/kult-core/src/cursor.c $(PORT_HDRS)
	@mkdir -p $(dir $@)
	$(CC) $(PORT_CFLAGS) -DHAVE_SDL3 $(SDL3_CFLAGS) -finstrument-functions \
	  -Dcursor_draw=kult_core_cursor_draw \
	  -Dcursor_restore=kult_core_cursor_restore -c $< -o $@
$(SDL_OBJDIR)/%.o: %.c $(PORT_HDRS)
	@mkdir -p $(dir $@)
	$(CC) $(PORT_CFLAGS) -DHAVE_SDL3 $(SDL3_CFLAGS) -c $< -o $@
$(PORT_SDL_BIN): $(SDL_CORE_O) $(SDL_OBJS) $(SDL_EXTRA_O)
	@mkdir -p build
	$(CC) $^ $(SDL3_LIBS) -o $@

# Pruebas funcionales de la HAL (sin oráculo): ficheros, vídeo, entrada, reloj.
# Sin instrumentación ni platform/cpuwork.c (la tabla referencia todo el core).
PLATFORM_TEST_SRC := $(filter-out platform/cpuwork.c platform/dispatch_trace.c,$(PLATFORM_SRC))
PLATFORM_TEST := build/test_platform
CURSOR_TEST   := build/test_cursor_overlay
.PHONY: test-port
test-port: $(PLATFORM_TEST) $(CURSOR_TEST) test-diag
	$(PLATFORM_TEST)
	$(CURSOR_TEST)
$(PLATFORM_TEST): platform/test/test_platform.c boot/vbl.c boot/prg.c boot/music_player.c boot/language.c lib/kult-core/src/music.c lib/kult-core/src/input.c $(PLATFORM_TEST_SRC) \
                  $(wildcard platform/include/*.h) $(wildcard platform/*.h) $(wildcard lib/kult-core/include/*.h)
	@mkdir -p build
	$(CC) $(PORT_CFLAGS) -DKULT_NO_CPUWORK platform/test/test_platform.c boot/vbl.c boot/prg.c boot/music_player.c boot/language.c lib/kult-core/src/music.c lib/kult-core/src/input.c $(PLATFORM_TEST_SRC) -o $@

$(CURSOR_TEST): platform/test/test_cursor_overlay.c $(PORT_OBJDIR)/lib/kult-core/src/cursor.o $(PORT_OBJDIR)/platform/cursor_overlay.o \
                $(wildcard platform/*.h) $(wildcard lib/kult-core/include/*.h)
	@mkdir -p build
	$(CC) $(PORT_CFLAGS) platform/test/test_cursor_overlay.c \
	  $(PORT_OBJDIR)/lib/kult-core/src/cursor.o $(PORT_OBJDIR)/platform/cursor_overlay.o -o $@

# Humo del diagnóstico: dos procesos para probar los logs desactivados/activados.
PLATFORM_DIAG_TEST := build/test_diag
.PHONY: test-diag
test-diag: $(PLATFORM_DIAG_TEST)
	$(PLATFORM_DIAG_TEST) off
	$(PLATFORM_DIAG_TEST) on
$(PLATFORM_DIAG_TEST): platform/test/test_diag.c platform/diag.c $(PORT_HDRS)
	@mkdir -p build
	$(CC) $(PORT_CFLAGS) -DKULT_NO_CPUWORK platform/test/test_diag.c platform/diag.c -o $@

# ---------------------------------------------------------------------------
# M7/T-070: build CMake (nativo Linux y cross Windows MinGW). Son envoltorios
# de conveniencia; el Makefile de arriba sigue siendo el del core/diferencial.
CMAKE      ?= cmake
BUILD_NAT  := build-cmake
BUILD_WIN  := build-win
BUILD_WIN_DIAG := build-win-diag
BUILD_MACOS := build-macos
SDL3_MINGW := $(CURDIR)/third_party/SDL3-3.4.10/x86_64-w64-mingw32
SDL3_MACOS := $(CURDIR)/third_party/sdl3-macos
KULT_VERSION ?= 1.2.1

.PHONY: deps-win
deps-win:
	sh tools/fetch_sdl3.sh

.PHONY: deps-linux
deps-linux:
	sh tools/fetch_sdl3_linux.sh
	sh tools/fetch_appimagetool.sh

.PHONY: deps-macos
deps-macos:
	sh tools/fetch_sdl3_macos.sh

.PHONY: cmake-native
cmake-native:
	$(CMAKE) -S . -B $(BUILD_NAT) -DCMAKE_BUILD_TYPE=Release
	$(CMAKE) --build $(BUILD_NAT) -j

.PHONY: cmake-win
cmake-win:
	$(CMAKE) -S . -B $(BUILD_WIN) -DCMAKE_BUILD_TYPE=Release \
	  -DCMAKE_TOOLCHAIN_FILE=cmake/mingw-w64.cmake \
	  -DCMAKE_PREFIX_PATH=$(SDL3_MINGW)
	$(CMAKE) --build $(BUILD_WIN) -j

.PHONY: cmake-win-diag
cmake-win-diag:
	$(CMAKE) -S . -B $(BUILD_WIN_DIAG) -DCMAKE_BUILD_TYPE=Release \
	  -DKULT_DIAG_TRACE=ON \
	  -DCMAKE_TOOLCHAIN_FILE=cmake/mingw-w64.cmake \
	  -DCMAKE_PREFIX_PATH=$(SDL3_MINGW)
	$(CMAKE) --build $(BUILD_WIN_DIAG) -j

.PHONY: package-native
package-native: cmake-native
	cpack --config $(BUILD_NAT)/CPackConfig.cmake -G TGZ -B $(BUILD_NAT)

.PHONY: package-win
package-win: cmake-win
	cpack --config $(BUILD_WIN)/CPackConfig.cmake -G ZIP -B $(BUILD_WIN)

.PHONY: cmake-macos
cmake-macos:
	$(CMAKE) -S . -B $(BUILD_MACOS) -DCMAKE_BUILD_TYPE=Release \
	  -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \
	  -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
	  -DCMAKE_PREFIX_PATH=$(SDL3_MACOS) \
	  -DKULT_SDL3_LIB=$(SDL3_MACOS)/lib/libSDL3.0.dylib
	$(CMAKE) --build $(BUILD_MACOS) -j

.PHONY: package-macos
package-macos: cmake-macos
	rm -rf build/macos-stage
	$(CMAKE) --install $(BUILD_MACOS) --prefix build/macos-stage
	KULT_VERSION=$(KULT_VERSION) tools/build_macos.sh build/macos-stage dist
