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 \
	-DICONV_CONST=

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

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

LINKER = $(CXX)

LIBS =

FLAGS_STATIC =
LIBS_STATIC = -lstdc++

LIBS_REQUIRES :=

DOCS := ../COPYING README

# 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_sound/sms_apu hw_sound/ym2413 hw_sound/ym2612 hw_video/huc6270 \
	mpcdec mthreading quicklz sound string resampler time video

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

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

override REQUIRES_PRIVATE += $(PKGCONF_FLAC) $(PKGCONF_ZLIB) $(PKGCONF_ZSTD)

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_sound/sms_apu/Sms_Apu.cpp \
	hw_sound/ym2413/emu2413.cpp \
	hw_sound/ym2612/Ym2612_Emu.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
DEFS += -DWANT_LYNX_EMU
MKDIRS += 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

# Sega Mega Drive (Genesis)
DEFS += -DWANT_MD_EMU
MKDIRS += md/cart md/cd md/input
CXXSRCS += md/cart/cart.cpp \
	md/cart/map_eeprom.cpp \
	md/cart/map_ff.cpp \
	md/cart/map_realtec.cpp \
	md/cart/map_rmx3.cpp \
	md/cart/map_rom.cpp \
	md/cart/map_sbb.cpp \
	md/cart/map_sram.cpp \
	md/cart/map_ssf2.cpp \
	md/cart/map_svp.cpp \
	md/cart/map_yase.cpp \
	md/cd/cd.cpp \
	md/cd/cdc_cdd.cpp \
	md/cd/interrupt.cpp \
	md/cd/pcm.cpp \
	md/cd/timer.cpp \
	md/input/4way.cpp \
	md/input/gamepad.cpp \
	md/input/megamouse.cpp \
	md/input/multitap.cpp \
	md/genesis.cpp \
	md/genio.cpp \
	md/header.cpp \
	md/mem68k.cpp \
	md/membnk.cpp \
	md/memvdp.cpp \
	md/memz80.cpp \
	md/sound.cpp \
	md/system.cpp \
	md/vdp.cpp

# Neo Geo Pocket
DEFS += -DWANT_NGP_EMU
MKDIRS += ngp/TLCS-900h
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
DEFS += -DWANT_PCE_EMU -DMDFN_PCE_VCE_AWESOMEMODE
MKDIRS += pce/input
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)
DEFS += -DWANT_PCE_FAST_EMU
MKDIRS += pce_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
# If you want to play PC-FX, that's none of my business
DEFS += -DWANT_PCFX_EMU
MKDIRS += pcfx/input
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
DEFS += -DWANT_PSX_EMU
MKDIRS += psx/input
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 Master System
# Required for MD support
DEFS += -DWANT_SMS_EMU
MKDIRS += sms
CXXSRCS += sms/cart.cpp \
	sms/memz80.cpp \
	sms/pio.cpp \
	sms/render.cpp \
	sms/romdb.cpp \
	sms/sms.cpp \
	sms/sound.cpp \
	sms/system.cpp \
	sms/tms.cpp \
	sms/vdp.cpp

# Sega Saturn
DEFS += -DWANT_SS_EMU
MKDIRS += ss/cart ss/input
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)
DEFS += -DWANT_SNES_FAUST_EMU
MKDIRS += snes_faust/cart snes_faust/input
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
DEFS += -DWANT_VB_EMU
MKDIRS += vb
CXXSRCS += vb/input.cpp \
	vb/timer.cpp \
	vb/vb.cpp \
	vb/vip.cpp \
	vb/vsu.cpp

# Bandai WonderSwan
DEFS += -DWANT_WSWAN_EMU
MKDIRS += wswan/dis
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

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

# Darwin specific
ifeq ($(PLATFORM), Darwin)
	MKDIRS += minilzo
	CSRCS += minilzo/minilzo.c
else
	INCLUDES += $(CFLAGS_LZO)
	LIBS += $(LIBS_LZO)
	override REQUIRES_PRIVATE += $(PKGCONF_LZO)
endif

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

# 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
