SOURCEDIR := $(abspath $(patsubst %/,%,$(dir $(abspath $(lastword \
	$(MAKEFILE_LIST))))))

NAME := mednafen
JGNAME := $(NAME)-jg

FLAGS_DEPS := -std=gnu99 -fomit-frame-pointer -fwrapv
FLAGS := -std=gnu++11 -fjump-tables -fno-fast-math \
	-fno-unsafe-math-optimizations -fomit-frame-pointer -fsigned-char \
	-fstrict-aliasing -fwrapv
DEFS := -DHAVE_CONFIG_H -DHAVE_LIBFLAC -DLSB_FIRST -DMPC_FIXED_POINT \
	-DMDFN_DISABLE_NO_OPT_ERRWARN -DMDFN_DISABLE_PICPIE_ERRWARN \
	-DMDFN_PCE_VCE_AWESOMEMODE -DMDFN_PSS_STYLE=1 -DICONV_CONST=
DEFS += -DWANT_LYNX_EMU
DEFS += -DWANT_NGP_EMU
DEFS += -DWANT_PCE_EMU
DEFS += -DWANT_PCE_FAST_EMU
#DEFS += -DWANT_PCFX_EMU # Most PC-FX games make me uncomfortable.
DEFS += -DWANT_PSX_EMU
DEFS += -DWANT_SS_EMU
DEFS += -DWANT_SNES_FAUST_EMU
DEFS += -DWANT_VB_EMU
DEFS += -DWANT_WSWAN_EMU

SRCDIR := $(SOURCEDIR)/../src

INCLUDES = -I$(SOURCEDIR)/. -I$(SOURCEDIR)/conf -I$(SOURCEDIR)/../include

LIBS = -lstdc++

DOCS := ../COPYING README

ENABLE_AVX ?= 0
USE_EXTERNAL_TRIO ?= 0

# Object dirs
MKDIRS := cdplay cdrom cheat_formats compress demo hash hw_cpu/m68k \
	hw_cpu/v810 hw_cpu/z80-fuse hw_misc/arcade_card hw_sound/pce_psg \
	hw_video/huc6270 mpcdec mthreading quicklz sound string resampler \
	time video

MKDIRS += lynx
MKDIRS += ngp/TLCS-900h
MKDIRS += pce/input
MKDIRS += pce_fast
#MKDIRS += pcfx/input
MKDIRS += psx/input
MKDIRS += snes_faust/cart snes_faust/input
MKDIRS += ss/cart ss/input
MKDIRS += wswan/dis
MKDIRS += vb

override INSTALL_DATA := 0
override INSTALL_EXAMPLE := 0
override INSTALL_SHARED := 0

include $(SOURCEDIR)/mk/jg.mk

override PREREQ += $(SOURCEDIR)/conf/config.h

EXT := cpp
LINKER := $(CXX)

CONF_ARGS = --build=$(BUILD) --host=$(HOST)

BUILD = $(shell $(CC) -dumpmachine)
HOST = $(shell $(CC) -dumpmachine)

LIBS_PTHREAD := -lpthread

ifeq ($(USE_EXTERNAL_TRIO), 0)
	CFLAGS_TRIO := -I$(SRCDIR)/trio
	LIBS_TRIO :=
	MKDIRS += trio
	SRCS_TRIO := trio/trio.c trio/trionan.c trio/triostr.c
	OBJS_TRIO := $(SRCS_TRIO:.c=.o)
else
	override REQUIRES_PRIVATE += libtrio
	CFLAGS_TRIO = $(shell $(PKG_CONFIG) --cflags libtrio)
	LIBS_TRIO = $(shell $(PKG_CONFIG) --libs libtrio)
	OBJS_TRIO :=
endif

INCLUDES += $(CFLAGS_FLAC) $(CFLAGS_LZO) $(CFLAGS_TRIO) $(CFLAGS_ZLIB) \
	$(CFLAGS_ZSTD)
LIBS += $(LIBS_FLAC) $(LIBS_LZO) $(LIBS_TRIO) $(LIBS_ZLIB) $(LIBS_ZSTD)

ifeq ($(UNAME), Darwin)
	FLAGS += -stdlib=libc++
	DEFS += -DHAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP
else ifeq ($(OS), Windows_NT)
	FLAGS += -fno-aggressive-loop-optimizations
	DEFS += -DWIN32 -D_LFS64_LARGEFILE=1
	LIBS += -lwinmm
endif

ifeq ($(findstring $(UNAME),Linux NetBSD),)
	LIBS += -liconv
endif

ifeq ($(ENABLE_AVX), 0)
	CONF_ARGS += --disable-avx
else
	CONF_ARGS += --enable-avx
endif

CSRCS := resampler/resample.c

CXXSRCS := ExtMemStream.cpp \
	FileStream.cpp \
	IPSPatcher.cpp \
	MTStreamReader.cpp \
	MemoryStream.cpp \
	NativeVFS.cpp \
	PSFLoader.cpp \
	SNSFLoader.cpp \
	SPCReader.cpp \
	Stream.cpp \
	VirtualFS.cpp \
	debug.cpp \
	endian.cpp \
	error.cpp \
	file.cpp \
	general.cpp \
	git.cpp \
	mednafen.cpp \
	memory.cpp \
	mempatcher.cpp \
	movie.cpp \
	netplay.cpp \
	player.cpp \
	qtrecord.cpp \
	settings.cpp \
	state.cpp \
	tests.cpp \
	testsexp.cpp \
	cdplay/cdplay.cpp \
	cdrom/CDAFReader.cpp \
	cdrom/CDAFReader_FLAC.cpp \
	cdrom/CDAFReader_PCM.cpp \
	cdrom/CDAccess.cpp \
	cdrom/CDAccess_CCD.cpp \
	cdrom/CDAccess_Image.cpp \
	cdrom/CDInterface.cpp \
	cdrom/CDInterface_MT.cpp \
	cdrom/CDInterface_ST.cpp \
	cdrom/CDUtility.cpp \
	cdrom/crc32.cpp \
	cdrom/galois.cpp \
	cdrom/l-ec.cpp \
	cdrom/lec.cpp \
	cdrom/recover-raw.cpp \
	cdrom/scsicd.cpp \
	cheat_formats/gb.cpp \
	cheat_formats/psx.cpp \
	cheat_formats/snes.cpp \
	compress/ArchiveReader.cpp \
	compress/DecompressFilter.cpp \
	compress/GZFileStream.cpp \
	compress/ZIPReader.cpp \
	compress/ZLInflateFilter.cpp \
	compress/ZstdDecompressFilter.cpp \
	demo/demo.cpp \
	hash/crc.cpp \
	hash/md5.cpp \
	hash/sha1.cpp \
	hash/sha256.cpp \
	hw_cpu/m68k/m68k.cpp \
	hw_cpu/v810/v810_cpu.cpp \
	hw_cpu/v810/v810_fp_ops.cpp \
	hw_cpu/z80-fuse/z80.cpp \
	hw_cpu/z80-fuse/z80_ops.cpp \
	hw_misc/arcade_card/arcade_card.cpp \
	hw_sound/pce_psg/pce_psg.cpp \
	hw_video/huc6270/vdc.cpp \
	sound/Blip_Buffer.cpp \
	sound/DSPUtility.cpp \
	sound/Fir_Resampler.cpp \
	sound/OwlResampler.cpp \
	sound/Stereo_Buffer.cpp \
	sound/SwiftResampler.cpp \
	sound/WAVRecord.cpp \
	sound/okiadpcm.cpp \
	string/escape.cpp \
	string/string.cpp \
	video/Deinterlacer.cpp \
	video/Deinterlacer_Blend.cpp \
	video/Deinterlacer_Simple.cpp \
	video/convert.cpp \
	video/font-data.cpp \
	video/png.cpp \
	video/primitives.cpp \
	video/resize.cpp \
	video/surface.cpp \
	video/tblur.cpp \
	video/text.cpp \
	video/video.cpp

# Atari Lynx
CXXSRCS += lynx/c65c02.cpp \
	lynx/cart.cpp \
	lynx/memmap.cpp \
	lynx/mikie.cpp \
	lynx/ram.cpp \
	lynx/rom.cpp \
	lynx/susie.cpp \
	lynx/system.cpp

# Neo Geo Pocket
CXXSRCS += ngp/T6W28_Apu.cpp \
	ngp/TLCS-900h/TLCS900h_disassemble.cpp \
	ngp/TLCS-900h/TLCS900h_disassemble_dst.cpp \
	ngp/TLCS-900h/TLCS900h_disassemble_extra.cpp \
	ngp/TLCS-900h/TLCS900h_disassemble_reg.cpp \
	ngp/TLCS-900h/TLCS900h_disassemble_src.cpp \
	ngp/TLCS-900h/TLCS900h_interpret.cpp \
	ngp/TLCS-900h/TLCS900h_interpret_dst.cpp \
	ngp/TLCS-900h/TLCS900h_interpret_reg.cpp \
	ngp/TLCS-900h/TLCS900h_interpret_single.cpp \
	ngp/TLCS-900h/TLCS900h_interpret_src.cpp \
	ngp/TLCS-900h/TLCS900h_registers.cpp \
	ngp/Z80_interface.cpp \
	ngp/bios.cpp \
	ngp/biosHLE.cpp \
	ngp/dma.cpp \
	ngp/flash.cpp \
	ngp/gfx.cpp \
	ngp/gfx_scanline_colour.cpp \
	ngp/gfx_scanline_mono.cpp \
	ngp/interrupt.cpp \
	ngp/mem.cpp \
	ngp/neopop.cpp \
	ngp/rom.cpp \
	ngp/rtc.cpp \
	ngp/sound.cpp

# NEC PC Engine
CXXSRCS += pce/hes.cpp \
	pce/huc.cpp \
	pce/huc6280.cpp \
	pce/input.cpp \
	pce/input/gamepad.cpp \
	pce/input/mouse.cpp \
	pce/input/tsushinkb.cpp \
	pce/mcgenjin.cpp \
	pce/pce.cpp \
	pce/pcecd.cpp \
	pce/tsushin.cpp \
	pce/vce.cpp

# NEC PC Engine (Fast)
CXXSRCS += pce_fast/hes.cpp \
	pce_fast/huc.cpp \
	pce_fast/huc6280.cpp \
	pce_fast/input.cpp \
	pce_fast/pce.cpp \
	pce_fast/pcecd.cpp \
	pce_fast/pcecd_drive.cpp \
	pce_fast/psg.cpp \
	pce_fast/vdc.cpp

# NEC PC-FX
#CXXSRCS += pcfx/fxscsi.cpp  \
#	pcfx/huc6273.cpp \
#	pcfx/idct.cpp \
#	pcfx/input.cpp \
#	pcfx/input/gamepad.cpp \
#	pcfx/input/mouse.cpp \
#	pcfx/interrupt.cpp \
#	pcfx/king.cpp \
#	pcfx/pcfx.cpp \
#	pcfx/rainbow.cpp \
#	pcfx/soundbox.cpp \
#	pcfx/timer.cpp

# Sony PlayStation
CXXSRCS += psx/cdc.cpp \
	psx/cpu.cpp \
	psx/dis.cpp \
	psx/dma.cpp \
	psx/frontio.cpp \
	psx/gpu.cpp \
	psx/gpu_line.cpp \
	psx/gpu_polygon.cpp \
	psx/gpu_sprite.cpp \
	psx/gte.cpp \
	psx/input/dualanalog.cpp \
	psx/input/dualshock.cpp \
	psx/input/gamepad.cpp \
	psx/input/guncon.cpp \
	psx/input/justifier.cpp \
	psx/input/memcard.cpp \
	psx/input/mouse.cpp \
	psx/input/multitap.cpp \
	psx/input/negcon.cpp \
	psx/irq.cpp \
	psx/mdec.cpp \
	psx/psx.cpp \
	psx/sio.cpp \
	psx/spu.cpp \
	psx/timer.cpp

# Sega Saturn
CXXSRCS += ss/ak93c45.cpp \
	ss/cart.cpp \
	ss/cart/ar4mp.cpp \
	ss/cart/backup.cpp \
	ss/cart/bootrom.cpp \
	ss/cart/cs1ram.cpp \
	ss/cart/extram.cpp \
	ss/cart/rom.cpp \
	ss/cart/stv.cpp \
	ss/cdb.cpp \
	ss/db.cpp \
	ss/input/3dpad.cpp \
	ss/input/gamepad.cpp \
	ss/input/gun.cpp \
	ss/input/jpkeyboard.cpp \
	ss/input/keyboard.cpp \
	ss/input/mission.cpp \
	ss/input/mouse.cpp \
	ss/input/multitap.cpp \
	ss/input/wheel.cpp \
	ss/scu_dsp_gen.cpp \
	ss/scu_dsp_jmp.cpp \
	ss/scu_dsp_misc.cpp \
	ss/scu_dsp_mvi.cpp \
	ss/smpc.cpp \
	ss/sound.cpp \
	ss/ss.cpp \
	ss/stvio.cpp \
	ss/vdp1.cpp \
	ss/vdp1_line.cpp \
	ss/vdp1_poly.cpp \
	ss/vdp1_sprite.cpp \
	ss/vdp2.cpp \
	ss/vdp2_render.cpp

# Super Nintendo Entertainment System (snes_faust)
CXXSRCS += snes_faust/apu.cpp \
	snes_faust/cart.cpp \
	snes_faust/cpu.cpp \
	snes_faust/input.cpp \
	snes_faust/input/gamepad.cpp \
	snes_faust/input/mouse.cpp \
	snes_faust/input/multitap.cpp \
	snes_faust/msu1.cpp \
	snes_faust/ppu.cpp \
	snes_faust/ppu_mt.cpp \
	snes_faust/ppu_mtrender.cpp \
	snes_faust/ppu_st.cpp \
	snes_faust/snes.cpp \
	snes_faust/cart/cx4.cpp \
	snes_faust/cart/dsp1.cpp \
	snes_faust/cart/dsp2.cpp \
	snes_faust/cart/sa1.cpp \
	snes_faust/cart/sa1cpu.cpp \
	snes_faust/cart/sdd1.cpp \
	snes_faust/cart/superfx.cpp

# Nintendo Virtual Boy
CXXSRCS += vb/input.cpp \
	vb/timer.cpp \
	vb/vb.cpp \
	vb/vip.cpp \
	vb/vsu.cpp

# Bandai WonderSwan
CXXSRCS += wswan/comm.cpp \
	wswan/dis/dis_decode.cpp \
	wswan/dis/dis_groups.cpp \
	wswan/dis/resolve.cpp \
	wswan/dis/syntax.cpp \
	wswan/eeprom.cpp \
	wswan/gfx.cpp \
	wswan/interrupt.cpp \
	wswan/main.cpp \
	wswan/memory.cpp \
	wswan/rtc.cpp \
	wswan/sound.cpp \
	wswan/tcache.cpp \
	wswan/v30mz.cpp

# Windows specific
ifeq ($(OS), Windows_NT)
	CXXSRCS += win32-common.cpp \
		mthreading/MThreading_Win32.cpp \
		time/Time_Win32.cpp
else
	CXXSRCS += mthreading/MThreading_POSIX.cpp \
		time/Time_POSIX.cpp
	LIBS += $(LIBS_PTHREAD)
endif

# The Jolly Good API Shim
JGSRCS := serial.cpp \
	stubs.cpp \
	jg.cpp

# List of object files
OBJS := $(patsubst %,$(OBJDIR)/%,$(CSRCS:.c=.o) $(CXXSRCS:.cpp=.o) $(OBJS_TRIO))
OBJS_JG := $(patsubst %,$(OBJDIR)/%,$(JGSRCS:.cpp=.o))

# Dependencies command
BUILD_DEPS = $(call COMPILE_C, $(FLAGS_DEPS) $(DEFS) $(INCLUDES))

# Core commands
BUILD_JG = $(call COMPILE_CXX, $(FLAGS) $(DEFS) $(INCLUDES) $(CFLAGS_JG))
BUILD_MAIN = $(call COMPILE_CXX, $(FLAGS) $(DEFS) $(INCLUDES))

.PHONY: $(PHONY) distclean

all: $(TARGET)

# Core rules
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(PREREQ)
	$(call COMPILE_INFO,$(BUILD_DEPS))
	@$(BUILD_DEPS)

$(OBJDIR)/%.o: $(SRCDIR)/%.$(EXT) $(PREREQ)
	$(call COMPILE_INFO,$(BUILD_MAIN))
	@$(BUILD_MAIN)

# Configure rules
$(SOURCEDIR)/conf/configure: $(SOURCEDIR)/conf/configure.ac
	@( cd $(SOURCEDIR)/conf && autoreconf -fi )

$(SOURCEDIR)/conf/config.h: $(SOURCEDIR)/conf/configure
	@( cd $(SOURCEDIR)/conf && $< $(CONF_ARGS) )

distclean: clean
	rm -rf $(SOURCEDIR)/conf/autom4te.cache
	rm -f $(SOURCEDIR)/conf/config.*
	rm -f $(SOURCEDIR)/conf/configure $(SOURCEDIR)/conf/configure~

include $(SOURCEDIR)/mk/rules.mk
