# nekoDOS_Windows build
.PHONY: all win test clean
#  make            -> Linux test build (build/linux/nekoDOS_Windows)
#  make win        -> Windows build via mingw-w64 (build/win/nekoDOS_Windows.exe)
#  make test       -> core unit test + emulator integration test (Linux)
NP2 = np2src
FE  = frontend

# CPU core: ia32 (80386, default: Touhou etc. use 386 instructions) / i286 (old core, CPU=i286)
CPU ?= ia32
ifeq ($(CPU),i286)
CPU_C = i286c/cpumem.c i286c/i286c.c i286c/i286c_0f.c i286c/i286c_8x.c i286c/i286c_ea.c i286c/i286c_f6.c \
 i286c/i286c_fe.c i286c/i286c_mn.c i286c/i286c_rp.c i286c/i286c_sf.c i286c/v30patch.c
CPU_INC = -I$(NP2)/i286c
CPU_DEF =
else
CPU_C = i386c/cpumem.c i386c/cpucore.c i386c/ia32/cpu.c i386c/ia32/cpu_io.c i386c/ia32/cpu_mem.c \
 i386c/ia32/ctrlxfer.c i386c/ia32/exception.c i386c/ia32/groups.c i386c/ia32/ia32.c i386c/ia32/inst_table.c \
 i386c/ia32/interface.c i386c/ia32/paging.c i386c/ia32/resolve.c i386c/ia32/segments.c i386c/ia32/task.c \
 i386c/ia32/instructions/bin_arith.c i386c/ia32/instructions/bit_byte.c i386c/ia32/instructions/ctrl_trans.c \
 i386c/ia32/instructions/data_trans.c i386c/ia32/instructions/dec_arith.c i386c/ia32/instructions/flag_ctrl.c \
 i386c/ia32/instructions/fpu.c i386c/ia32/instructions/fpu/fpdummy.c i386c/ia32/instructions/logic_arith.c \
 i386c/ia32/instructions/misc_inst.c i386c/ia32/instructions/seg_reg.c i386c/ia32/instructions/shift_rotate.c \
 i386c/ia32/instructions/string_inst.c i386c/ia32/instructions/system_inst.c i386c/ia32/debug.c
CPU_INC = -I$(NP2)/i386c -I$(NP2)/i386c/ia32 -I$(NP2)/i386c/ia32/instructions -I$(NP2)/i386c/ia32/instructions/fpu
CPU_DEF = -DCPUCORE_IA32
endif

CORE_C = calendar.c debugsub.c keystat.c nevent.c pccore.c statsave.c timing.c \
 bios/bios.c bios/bios09.c bios/bios0c.c bios/bios12.c bios/bios13.c bios/bios18.c bios/bios19.c \
 bios/bios1a.c bios/bios1b.c bios/bios1c.c bios/bios1f.c bios/sxsibios.c \
 cbus/amd98.c cbus/atapicmd.c cbus/board118.c cbus/board14.c cbus/board26k.c cbus/board86.c \
 cbus/boardpx.c cbus/boardso.c cbus/boardspb.c cbus/boardx2.c cbus/cbuscore.c cbus/cs4231io.c \
 cbus/ideio.c cbus/mpu98ii.c cbus/pc9861k.c cbus/pcm86io.c cbus/sasiio.c cbus/scsicmd.c cbus/scsiio.c \
 codecnv/sjisucs2.c codecnv/tcswap16.c codecnv/tcswap32.c codecnv/textcnv.c codecnv/ucs2sjis.c \
 codecnv/ucs2utf8.c codecnv/utf8ucs2.c \
 common/_memory.c common/bmpdata.c common/lstarray.c common/milstr.c \
 common/mimpidef.c common/parts.c common/profile.c common/rect.c common/resize.c common/strres.c \
 common/textfile.c common/wavefile.c \
 embed/vramhdl.c embed/vrammix.c embed/menubase/menubase.c embed/menubase/menudlg.c \
 embed/menubase/menuicon.c embed/menubase/menumbox.c embed/menubase/menures.c embed/menubase/menusys.c \
 embed/menubase/menuvram.c \
 fdd/diskdrv.c fdd/fdd_d88.c fdd/fdd_mtr.c fdd/fdd_xdf.c fdd/fddfile.c fdd/newdisk.c fdd/sxsi.c \
 fdd/sxsicd.c fdd/sxsihdd.c \
 font/font.c font/fontdata.c font/fontfm7.c font/fontmake.c font/fontpc88.c font/fontpc98.c \
 font/fontv98.c font/fontx1.c font/fontx68k.c \
 generic/cmjasts.c generic/cmndraw.c generic/cmver.c \
 $(CPU_C) \
 io/artic.c io/cgrom.c io/cpuio.c io/crtc.c io/dipsw.c io/dmac.c io/egc.c io/emsio.c io/epsonio.c \
 io/fdc.c io/fdd320.c io/gdc.c io/gdc_pset.c io/gdc_sub.c io/iocore.c io/mouseif.c io/necio.c \
 io/nmiio.c io/np2sysp.c io/pcidev.c io/pic.c io/pit.c io/printif.c io/serial.c io/sysport.c io/upd4990.c \
 lio/gcircle.c lio/gline.c lio/gpset.c lio/gput1.c lio/gscreen.c lio/lio.c \
 mem/dmav30.c mem/dmax86.c mem/memegc.c mem/memems.c mem/memepp.c mem/memtram.c mem/memvga.c mem/memvram.c \
 sound/adpcmc.c sound/adpcmg.c sound/beepc.c sound/beepg.c sound/cs4231c.c sound/cs4231g.c \
 sound/fmboard.c sound/opna.c sound/opl3.c sound/oplgenc.c sound/oplgeng.c sound/opngenc.c sound/opngeng.c sound/opntimer.c \
 sound/pcm86c.c sound/pcm86g.c sound/pcmmix.c sound/psggenc.c sound/psggeng.c sound/rhythmc.c \
 sound/s98.c sound/sndcsec.c sound/sound.c sound/soundrom.c sound/tms3631c.c sound/tms3631g.c \
 sound/getsnd/getsnd.c sound/getsnd/getsmix.c sound/getsnd/getwave.c sound/getsnd/getmp3.c sound/getsnd/getogg.c \
 vram/dispsync.c vram/makegrex.c vram/makegrph.c vram/maketext.c vram/maketgrp.c vram/palettes.c \
 vram/scrndraw.c vram/scrnsave.c vram/sdraw.c vram/sdrawq16.c vram/vram.c \
 sdl2/commng.c sdl2/dosio.c sdl2/fontmng.c sdl2/ini.c sdl2/inputmng.c sdl2/joymng.c sdl2/mousemng.c \
 sdl2/scrnmng.c sdl2/sdlkbd.c sdl2/sysmng.c sdl2/timemng.c sdl2/trace.c
CORE_CPP = sdl2/soundmng.cpp sound/ymfmbridge.cpp
# ymfm (FM sound engine, BSD-3-Clause)
YMFM_CPP = ymfm_opn.cpp ymfm_ssg.cpp ymfm_adpcm.cpp
YMFM = third_party/ymfm
CXXSTD = -std=c++14
FE_C = nekodos.c dndbox.c taskmng.c fatimg.c stubs.c cmmidi.c nekocfg.c settings_win.c fontsel.c outcollect.c arcinput.c sjisconv.c hddimg.c cmdline.c

INCS = -I$(FE) -I$(NP2) -I$(NP2)/sdl2 -I$(NP2)/common $(CPU_INC) $(CPU_DEF) -I$(NP2)/io -I$(NP2)/cbus \
  -I$(NP2)/mem -I$(NP2)/sound -I$(NP2)/vram -I$(NP2)/fdd -I$(NP2)/font -I$(NP2)/bios -I$(NP2)/lio \
  -I$(NP2)/embed -I$(NP2)/embed/menubase -I$(NP2)/embed/menu -I$(NP2)/generic -I$(NP2)/codecnv
CWARN = -w -MMD -MP
COPT = -O2 -fno-strict-aliasing -fwrapv

# ---- linux
LB = build/linux
L_OBJS = $(addprefix $(LB)/core/,$(CORE_C:.c=.o) $(CORE_CPP:.cpp=.o)) $(addprefix $(LB)/fe/,$(FE_C:.c=.o)) $(addprefix $(LB)/ymfm/,$(YMFM_CPP:.cpp=.o))
# libarchive (ZIP / LZH / RAR) + zlib, static:  sh third_party/build_libarchive.sh linux|mingw
TPL = third_party/linux
TPW = third_party/mingw
L_CFLAGS = $(COPT) $(CWARN) $(INCS) $(shell sdl2-config --cflags) -DNEKODOS_TEST -I$(TPL)/include
all: $(LB)/nekoDOS_Windows
$(LB)/nekoDOS_Windows: $(L_OBJS)
	g++ -o $@ $^ $(TPL)/lib/libarchive.a $(TPL)/lib/libz.a $(shell sdl2-config --libs) -lm
$(LB)/core/%.o: $(NP2)/%.c
	@mkdir -p $(dir $@); gcc $(L_CFLAGS) -c $< -o $@
$(LB)/core/%.o: $(NP2)/%.cpp
	@mkdir -p $(dir $@); g++ $(CXXSTD) $(L_CFLAGS) -I$(YMFM) -c $< -o $@
$(LB)/ymfm/%.o: $(YMFM)/%.cpp
	@mkdir -p $(dir $@); g++ $(CXXSTD) -O2 -w -c $< -o $@
$(LB)/fe/%.o: $(FE)/%.c
	@mkdir -p $(dir $@); gcc $(L_CFLAGS) -c $< -o $@

# ---- windows (mingw-w64, i686 -> runs on all Windows)
WB = build/win
MINGW ?= i686-w64-mingw32
SDL2W ?= sdl2-mingw/$(MINGW)
W_OBJS = $(addprefix $(WB)/core/,$(CORE_C:.c=.o) $(CORE_CPP:.cpp=.o)) $(addprefix $(WB)/fe/,$(FE_C:.c=.o)) $(addprefix $(WB)/ymfm/,$(YMFM_CPP:.cpp=.o)) $(WB)/res.o
W_CFLAGS = $(COPT) $(CWARN) $(INCS) -I$(SDL2W)/include -I$(TPW)/include -DLIBARCHIVE_STATIC
win: $(WB)/nekoDOS_Windows.exe
$(WB)/nekoDOS_Windows.exe: $(W_OBJS)
	$(MINGW)-g++ -o $@ $^ $(TPW)/lib/libarchive.a $(TPW)/lib/libz.a -L$(SDL2W)/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -lwinmm -lcomctl32 -lole32 -luuid -lcomdlg32 -static-libgcc -static-libstdc++ -lshell32
$(WB)/core/%.o: $(NP2)/%.c
	@mkdir -p $(dir $@); $(MINGW)-gcc $(W_CFLAGS) -c $< -o $@
$(WB)/core/%.o: $(NP2)/%.cpp
	@mkdir -p $(dir $@); $(MINGW)-g++ $(CXXSTD) $(W_CFLAGS) -I$(YMFM) -c $< -o $@
$(WB)/ymfm/%.o: $(YMFM)/%.cpp
	@mkdir -p $(dir $@); $(MINGW)-g++ $(CXXSTD) -O2 -w -c $< -o $@
$(WB)/fe/%.o: $(FE)/%.c
	@mkdir -p $(dir $@); $(MINGW)-gcc $(W_CFLAGS) -c $< -o $@
$(WB)/res.o: $(FE)/nekodos.rc
	@mkdir -p $(dir $@); $(MINGW)-windres -I$(FE) $< -o $@

clean:
	rm -rf build

# header dependencies (-MMD): e.g. guestbin.h (RUN.COM) -> nekodos.o
-include $(L_OBJS:.o=.d) $(W_OBJS:.o=.d)

# ---- tests (Linux)
LIBARCHIVE_SRC ?= /tmp/libarchive
test: $(LB)/nekoDOS_Windows
	gcc -O1 -Ifrontend -I$(NP2) -I$(NP2)/sdl2 -I$(NP2)/common $(shell sdl2-config --cflags) test/test_core.c \
	  frontend/outcollect.c frontend/fatimg.c frontend/nekocfg.c -o $(LB)/test_core $(shell sdl2-config --libs)
	$(LB)/test_core
	gcc -O1 -Ifrontend -I$(TPL)/include test/test_arc.c frontend/arcinput.c frontend/sjisconv.c frontend/fatimg.c \
	  frontend/outcollect.c $(TPL)/lib/libarchive.a $(TPL)/lib/libz.a -o $(LB)/test_arc
	gcc -O1 -Ifrontend -I$(NP2) -I$(NP2)/sdl2 -I$(NP2)/common -I$(TPL)/include $(shell sdl2-config --cflags) test/test_dnd.c \
	  frontend/dndbox.c frontend/arcinput.c frontend/sjisconv.c frontend/fatimg.c frontend/nekocfg.c frontend/outcollect.c \
	  $(TPL)/lib/libarchive.a $(TPL)/lib/libz.a $(shell sdl2-config --libs) -o $(LB)/test_dnd
	$(LB)/test_dnd test/dnd/
	cd test/arc && python3 mkfix.py $(LIBARCHIVE_SRC)
	$(LB)/test_arc test/arc/
	cd test/guest && for f in write slowa view cat env waitkey errl; do nasm -f bin $$f.asm -o `echo $$f | tr a-z A-Z`.COM; done
	cd test && ./run_tests.sh
	cd test && ./run_arc_tests.sh
