# undoom: linuxdoom-1.10 ported to lumbda Scheme.
#
# One game, several copies: every host runs our same src/*.lsp.
#
#   make                this help (make all: build all hosts + run tests)
#   make play           play E1M1 on SDL2 (MODE=jit, ARGS="-warp 1 1 -skill 3")
#   make play-dry       play on fox's Dry engine
#   make play-wasm      serve the browser build, E1M1 (see hosts/wasm)
#   make play-headless  run the game headless, screenshots into out/
#   make tiers          headless game on every lumbda tier (pass/fail matrix)
#   make help           list every target
#
# MODE picks lumbda's evaluator for native copies: jit (x86_64 native
# code, 35 fps), fast (bytecode VM), tree (tree-walker). Results are
# identical in every mode; only speed differs.

LUMBDA_DIR ?= $(HOME)/git/lumbda
LUMBDA     ?= $(LUMBDA_DIR)/c/lumbda
MODE       ?= jit
MODE_FLAGS_jit  := --jit
MODE_FLAGS_fast := --fast
MODE_FLAGS_tree :=
LUMBDA_FLAGS ?= $(MODE_FLAGS_$(MODE))
export LUMBDA_STDLIB ?= $(LUMBDA_DIR)/stdlib.lsp
WAD_DIR    := wad
FREEDOOM   := $(WAD_DIR)/freedoom1.wad
IWAD       ?= $(FREEDOOM)
ARGS       ?= -warp 1 1 -skill 3
TICS       ?= 350

.PHONY: all help hosts test test-all ref wads lumbda gen titlepic \
        sdl2 wasm play play-sdl2 play-sdl2-title play-dry play-dry-title \
        play-wasm publish-wasm play-headless demo tiers tiers-demo \
        tier-c-jit tier-c-fast tier-c-tree tier-python tier-asm tier-wat \
        tier-wasm-c test-wasm clean FORCE

# Bare `make` prints help; `make all` builds every host and runs tests.
.DEFAULT_GOAL := help

all: hosts test

help:
	@echo "undoom: linuxdoom-1.10 in lumbda Scheme.  make <target> [MODE=jit|fast|tree] [ARGS=...]   (bare make = this help)"
	@echo
	@echo "play (every copy of the game):"
	@echo "  play, play-sdl2      SDL2 window, E1M1 (ARGS=\"$(ARGS)\"; ARGS= for title + menu)"
	@echo "  play-sdl2-title      SDL2, title screen and menu"
	@echo "  play-dry             Dry engine window, E1M1 (first build compiles Dry, ~15 min)"
	@echo "  play-dry-title       Dry engine, title screen and menu"
	@echo "  play-wasm            browser build on 127.0.0.1:8080, E1M1 (click to grab mouse)"
	@echo "  publish-wasm         copy the browser build into lumbda's www/doom/ (lumbda.com/doom/)"
	@echo "  play-headless        no window: TICS=$(TICS), screenshot every 35 tics into out/"
	@echo "  demo                 replay the chocolate-doom oracle demo headless, compare per tic"
	@echo
	@echo "lumbda tiers (headless game on each lumbda implementation):"
	@echo "  tiers                TITLEPIC golden on $(TIERS) wasm-c: pass/fail matrix"
	@echo "  tiers-demo           full-game demo sync vs chocolate-doom on $(DEMO_TIERS)"
	@echo "  tier-<name>          one tier: $(addprefix tier-,$(TIERS)) tier-wasm-c"
	@echo
	@echo "build:"
	@echo "  all                  hosts + test"
	@echo "  hosts                sdl2 + dry + wasm"
	@echo "  sdl2                 build/undoom-sdl2"
	@echo "  dry                  build/undoom-dry (builds Dry into build/dry first)"
	@echo "  dry-engine           only Dry's libDry.a;  dry-check: compile-check the host;  dry-clean"
	@echo "  wasm                 browser build into hosts/wasm/dist"
	@echo "  lumbda               build lumbda's C tier ($(LUMBDA_DIR))"
	@echo
	@echo "test:"
	@echo "  test                 undoom suites under MODE=$(MODE) (core, playsim, render, game)"
	@echo "  test-wasm            browser host in a node Worker"
	@echo "  test-all             test + tiers + tiers-demo"
	@echo "  titlepic             render TITLEPIC to out/titlepic.ppm"
	@echo
	@echo "data:"
	@echo "  wads                 fetch Freedoom into wad/ (DOOM1.WAD: place by hand)"
	@echo "  ref                  clone id's linuxdoom source into ref/"
	@echo "  gen                  regenerate src/gen/*.lsp from id's C data"
	@echo "  clean                remove out/, logs, state logs, demos, build/undoom-sdl2"
	@echo
	@echo "MODE: jit = x86_64 native code (35 fps), fast = bytecode VM, tree = tree-walker."

hosts: sdl2 dry wasm

lumbda:
	$(MAKE) -C $(LUMBDA_DIR) c-build

ref: ref/DOOM
ref/DOOM:
	git clone --depth 1 https://github.com/id-Software/DOOM.git ref/DOOM

# Freedoom via our distro mirror (github release downloads disallowed by robots.txt).
# Shareware DOOM1.WAD: place by hand at wad/doom1.wad for demo-sync tests.
wads: $(FREEDOOM)
$(FREEDOOM):
	mkdir -p $(WAD_DIR) build/deb
	cd build/deb && apt-get download freedoom
	dpkg-deb -x build/deb/freedoom_*.deb build/deb/x
	cp build/deb/x/usr/share/games/doom/freedoom1.wad build/deb/x/usr/share/games/doom/freedoom2.wad $(WAD_DIR)/

# Regenerate src/gen/*.lsp from id's C data (gcc evaluates every initializer).
gen: ref
	python3 -u tools/gen_data.py ref/DOOM/linuxdoom-1.10 src/gen

# ── tests ────────────────────────────────────────────────────────────────

# C oracles: id's own code compiled beside a dumper; tests compare against them.
ORACLES := build/geom-oracle.lsp build/maputl-oracle.lsp build/rmain-oracle.lsp
build/geom-oracle: tests/oracle/geom.c | ref
	mkdir -p build
	gcc -w -std=gnu99 -fwrapv -I ref/DOOM/linuxdoom-1.10 -o $@ $< ref/DOOM/linuxdoom-1.10/tables.c -lm
build/geom-oracle.lsp: build/geom-oracle
	$< > $@
build/maputl-oracle: tests/oracle/maputl.c | ref
	mkdir -p build
	gcc -w -std=gnu99 -fwrapv -I ref/DOOM/linuxdoom-1.10 -o $@ $<
build/maputl-oracle.lsp: build/maputl-oracle
	$< > $@
build/rmain-oracle: tests/oracle/rmain.c | ref
	mkdir -p build
	gcc -w -std=gnu99 -fwrapv -I ref/DOOM/linuxdoom-1.10 -o $@ $< ref/DOOM/linuxdoom-1.10/tables.c -lm
build/rmain-oracle.lsp: build/rmain-oracle
	$< > $@

test: lumbda wads $(ORACLES)
	$(LUMBDA) $(LUMBDA_FLAGS) tests/run.lsp
	$(LUMBDA) $(LUMBDA_FLAGS) tests/run-playsim.lsp
	$(LUMBDA) $(LUMBDA_FLAGS) tests/run-render.lsp
	$(LUMBDA) $(LUMBDA_FLAGS) tests/run-game.lsp

test-all: test tiers tiers-demo

# Milestone 2 smoke: render TITLEPIC through PLAYPAL into out/titlepic.ppm
titlepic: lumbda wads
	mkdir -p out
	IWAD=$(IWAD) $(LUMBDA) $(LUMBDA_FLAGS) tools/titlepic.lsp

# ── lumbda tiers: our headless game on each implementation ───────────────
# tier-* : TITLEPIC golden (WAD, lumps, patches, palette, bytevectors).
# tiers  : every tier, keeps going past failures, prints a matrix.
TIERS := c-jit c-fast c-tree python asm wat
DEMO_TIERS := c-jit c-tree c-fast

$(addprefix tier-,$(TIERS)): tier-%: wads
	@tools/tier-check.sh $*

tier-wasm-c: test-wasm

tiers: wads
	@mkdir -p build; fail=0; for t in $(TIERS); do tools/tier-check.sh $$t || fail=1; done; \
	 if $(MAKE) --no-print-directory test-wasm >build/tier-wasm-c.log 2>&1; \
	   then echo "PASS wasm-c titlepic (node Worker, hosts/wasm)"; \
	   else echo "FAIL wasm-c: see build/tier-wasm-c.log"; fail=1; fi; \
	 exit $$fail

tiers-demo: wads
	@fail=0; for t in $(DEMO_TIERS); do tools/tier-check.sh $$t --demo || fail=1; done; exit $$fail

# ── SDL2 host ────────────────────────────────────────────────────────────
# Embeds lumbda (liblumbda.a) and implements our platform shim.
# GC flags must match how liblumbda.a was built (lumbda's own autodetect).
LUMBDA_GC ?= $(shell test -f /usr/include/gc.h && echo 1 || echo 0)
ifeq ($(LUMBDA_GC),1)
GC_CFLAGS := -DUSE_BOEHM_GC
GC_LIBS := -lgc
endif
SDL2_HOST := build/undoom-sdl2
sdl2: $(SDL2_HOST)
# Sound: hosts/common (shared with the Dry host) mixes into SDL audio.
SOUND_SRCS := hosts/common/sdl_sound.c hosts/common/undoom_mixer.c
$(SDL2_HOST): hosts/sdl2/sdl2_host.c $(SOUND_SRCS) hosts/common/*.h $(LUMBDA_DIR)/c/liblumbda.a
	mkdir -p build
	$(CC) -O2 -Wall -Wextra -std=c11 -D_GNU_SOURCE $(GC_CFLAGS) -I$(LUMBDA_DIR)/c -Ihosts/common $$(sdl2-config --cflags) \
	  -o $@ hosts/sdl2/sdl2_host.c $(SOUND_SRCS) $(LUMBDA_DIR)/c/liblumbda.a $$(sdl2-config --libs) $(GC_LIBS) -lm
# lumbda's own make decides whether liblumbda.a is stale.
$(LUMBDA_DIR)/c/liblumbda.a: FORCE
	$(MAKE) -C $(LUMBDA_DIR)/c liblumbda.a
FORCE:

play: play-sdl2
play-sdl2: sdl2 wads
	$(SDL2_HOST) $(LUMBDA_FLAGS) hosts/boot.lsp $(ARGS)
play-sdl2-title: sdl2 wads
	$(SDL2_HOST) $(LUMBDA_FLAGS) hosts/boot.lsp

# ── Dry host (fox's Dry engine, ~/git/dry, built out of tree into build/dry)
include hosts/dry/dry.mk

play-dry: dry wads
	$(DRY_HOST) $(LUMBDA_FLAGS) hosts/boot.lsp $(ARGS)
play-dry-title: dry wads
	$(DRY_HOST) $(LUMBDA_FLAGS) hosts/boot.lsp

# ── WebAssembly browser host (emscripten; hosts/wasm/Makefile) ──────────
wasm:
	$(MAKE) -C hosts/wasm build
test-wasm:
	$(MAKE) -C hosts/wasm test
play-wasm: wads
	$(MAKE) -C hosts/wasm serve
publish-wasm:
	$(MAKE) -C hosts/wasm publish

# ── headless host ────────────────────────────────────────────────────────
play-headless: lumbda wads
	mkdir -p out
	$(LUMBDA) $(LUMBDA_FLAGS) tools/run-headless.lsp --tics $(TICS) --every 35 --prefix headless \
	  -- -iwad $(IWAD) -config build/headless.cfg $(ARGS)

demo: lumbda wads
	@tools/tier-check.sh c-$(MODE) --demo

clean:
	rm -rf out build/*.log build/*.state build/*.lmp build/undoom-sdl2
