cmake_minimum_required(VERSION 2.8.5)

set(CMAKE_USER_MAKE_RULES_OVERRIDE ${CMAKE_CURRENT_SOURCE_DIR}/static_crt_override_c.cmake)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX ${CMAKE_CURRENT_SOURCE_DIR}/static_crt_override_cxx.cmake)
project(zsnes C CXX ASM_NASM)
include(GNUInstallDirs)

option(DEBUGGER "Enable the integrated ZSNES debugger (requires pdcurses)")
option(ENABLE_LIBPNG "Enable libpng support." ON)

if(NOT DEBUGGER)
    set(DEBUGGER_FLAG NO_DEBUGGER)
    set(PSR_DEBUGGER_FLAG -DNO_DEBUGGER)
endif()

set(CHIPDIR chips)
set(CPUDIR cpu)
set(DOSDIR dos)
set(EFFECTSDIR effects)
set(GUIDIR gui)
set(JMADIR jma)
set(NETDIR net)
set(VIDEODIR video)
set(WINDIR win)
set(ZIPDIR zip)
set(MMLIBDIR mmlib)

set(SRC_GRP_PREFIX "Source Files\\")
set(SRC_CHIPS ${CHIPDIR}/dsp1emu.c ${CHIPDIR}/fxemu2.asm ${CHIPDIR}/sfxproc.asm
	${CHIPDIR}/fxemu2b.asm ${CHIPDIR}/fxemu2c.asm ${CHIPDIR}/fxtable.asm
	${CHIPDIR}/sa1proc.asm ${CHIPDIR}/sa1regs.asm ${CHIPDIR}/dsp1proc.asm
	${CHIPDIR}/st10proc.asm ${CHIPDIR}/seta10.c ${CHIPDIR}/dsp2proc.asm
	${CHIPDIR}/sdd1emu.c ${CHIPDIR}/c4emu.c ${CHIPDIR}/dsp4proc.asm
	${CHIPDIR}/dsp4emu.c ${CHIPDIR}/dsp3proc.asm ${CHIPDIR}/dsp3emu.c
	${CHIPDIR}/obc1emu.c ${CHIPDIR}/obc1proc.asm ${CHIPDIR}/c4proc.asm
	${CHIPDIR}/7110proc.asm ${CHIPDIR}/st11proc.asm ${CHIPDIR}/seta11.c)
source_group(${SRC_GRP_PREFIX}chips FILES ${SRC_CHIPS})

set(SRC_CPU ${CPUDIR}/dma.asm ${CPUDIR}/dsp.asm ${CPUDIR}/dspproc.asm
	${CPUDIR}/execute.asm ${CPUDIR}/executec.c ${CPUDIR}/irq.asm
	${CPUDIR}/memory.asm ${CPUDIR}/memtable.c ${CPUDIR}/spc700.asm
	${CPUDIR}/stable.asm ${CPUDIR}/table.asm ${CPUDIR}/tablec.asm)
source_group(${SRC_GRP_PREFIX}cpu FILES ${SRC_CPU})

set(SRC_EFFECTS ${EFFECTSDIR}/burn.c ${EFFECTSDIR}/water.c ${EFFECTSDIR}/smoke.c)
source_group(${SRC_GRP_PREFIX}effects FILES ${SRC_EFFECTS})

set(SRC_GUI ${GUIDIR}/gui.asm ${GUIDIR}/guifuncs.c ${GUIDIR}/menu.asm)
source_group(${SRC_GRP_PREFIX}gui FILES ${SRC_GUI})

set(SRC_JMA ${JMADIR}/7zlzma.cpp ${JMADIR}/crc32.cpp ${JMADIR}/iiostrm.cpp
	${JMADIR}/inbyte.cpp ${JMADIR}/jma.cpp ${JMADIR}/lzma.cpp ${JMADIR}/lzmadec.cpp
	${JMADIR}/winout.cpp ${JMADIR}/zsnesjma.cpp)
source_group(${SRC_GRP_PREFIX}jma FILES ${SRC_JMA})

set(SRC_MAIN endmem.asm init.asm initc.c patch.c
	ui.c vcache.asm version.c zmovie.c zstate.c zloader.c
	cfg.c md.c input.c zpath.c ztimec.c ztime.asm)
source_group(${SRC_GRP_PREFIX}main FILES ${SRC_MAIN})

set(SRC_VIDEO ${VIDEODIR}/makev16b.asm ${VIDEODIR}/makev16t.asm ${VIDEODIR}/makevid.asm
	${VIDEODIR}/mode716.asm ${VIDEODIR}/mode716b.asm ${VIDEODIR}/mode716d.asm
	${VIDEODIR}/mode716e.asm ${VIDEODIR}/mode716t.asm ${VIDEODIR}/mode7.asm
	${VIDEODIR}/mode7ext.asm ${VIDEODIR}/mv16tms.asm ${VIDEODIR}/newg162.asm
	${VIDEODIR}/newgfx16.asm ${VIDEODIR}/newgfx2.asm ${VIDEODIR}/newgfx.asm
	${VIDEODIR}/m716text.asm ${VIDEODIR}/procvid.asm ${VIDEODIR}/procvidc.c
    ${VIDEODIR}/ntsc.c)
source_group(${SRC_GRP_PREFIX}video FILES ${SRC_VIDEO})

if(WIN32)
    set(OSDEF __WIN32__)
    set(SRC_WIN ${WINDIR}/zsnes.rc
        ${WINDIR}/winintrf.asm ${WINDIR}/winlink.cpp ${WINDIR}/lib.c
        ${WINDIR}/safelib.c ${MMLIBDIR}/mm.c ${MMLIBDIR}/windows.c)
    source_group(${SRC_GRP_PREFIX}win FILES ${SRC_WIN})

    set(SRC_WINVID ${VIDEODIR}/sw_draw.asm ${VIDEODIR}/hq2x16.asm ${VIDEODIR}/hq2x32.asm
        ${VIDEODIR}/2xsaiw.asm ${VIDEODIR}/hq3x16.asm ${VIDEODIR}/hq3x32.asm
        ${VIDEODIR}/hq4x16.asm ${VIDEODIR}/hq4x32.asm ${VIDEODIR}/copyvwin.asm)
    source_group(${SRC_GRP_PREFIX}video FILES ${SRC_WINVID})
else()
    set(OSDEF __UNIXSDL__)
endif()

set(SRC_ZIP ${ZIPDIR}/unzip.c ${ZIPDIR}/zpng.c)
source_group(${SRC_GRP_PREFIX}zip FILES ${SRC_ZIP})

if(DEBUGGER)
    set(SRC_DEBUGGER debugger.c debugasm.asm)
endif()

# Include directories must end with a slash.  Sadly, include_directories() doesn't do this.
set(CMAKE_ASM_NASM_FLAGS "-w-orphan-labels -D${OSDEF} ${PSR_DEBUGGER_FLAG} -I${CMAKE_CURRENT_SOURCE_DIR}/")
set(CMAKE_ASM_NASM_FLAGS_RELEASE "-D__RELEASE__")
set(CMAKE_ASM_NASM_FLAGS_RELWITHDEBINFO "-D__RELEASE__")
include_directories(${CMAKE_CURRENT_BINARY_DIR})

if(MSVC)
    set_property(DIRECTORY PROPERTY COMPILE_DEFINITIONS _CRT_SECURE_NO_WARNINGS)
endif()

if(WIN32)
    set(PLATFORM_LIBS dinput8.lib winmm.lib)
endif()

find_package(ZLIB REQUIRED)
add_library(zlib UNKNOWN IMPORTED)
set_target_properties(zlib PROPERTIES IMPORTED_LOCATION "${ZLIB_LIBRARY}" INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIRS}")

if(ENABLE_LIBPNG)
    find_package(PNG)
    if(PNG_FOUND)
        add_library(png UNKNOWN IMPORTED)
        set_target_properties(png PROPERTIES IMPORTED_LOCATION "${PNG_LIBRARY}" INTERFACE_INCLUDE_DIRECTORIES "${PNG_INCLUDE_DIRS}" INTERFACE_COMPILE_DEFINITIONS "${PNG_DEFINITIONS}")
        set(PNG png)
    else()
        set(PNG_FLAG NO_PNG)
        set(PSR_PNG_FLAG -DNO_PNG)
    endif()
endif()

add_executable(parsegen parsegen.cpp)
target_link_libraries(parsegen zlib)

foreach(psr cfg input md)
    add_custom_command(OUTPUT ${psr}.c ${psr}.h COMMAND parsegen -D${OSDEF} ${PSR_PNG_FLAG} ${PSR_DEBUGGER_FLAG} -cheader ${psr}.h -fname ${psr} ${psr}.c "${CMAKE_CURRENT_SOURCE_DIR}/${psr}.psr"
        MAIN_DEPENDENCY ${psr}.psr)
endforeach(psr)

add_executable(zsnes WIN32 MACOSX_BUNDLE ${SRC_CHIPS} ${SRC_CPU} ${SRC_GUI} ${SRC_VIDEO} ${SRC_MAIN} ${SRC_ZIP} ${SRC_EFFECTS} ${SRC_JMA}
    ${SRC_WIN} ${SRC_WINVID})
target_compile_definitions(zsnes PRIVATE ${OSDEF} ${PNG_FLAG} ${DEBUGGER_FLAG})
set_target_properties(zsnes PROPERTIES COMPILE_DEFINITIONS_RELEASE __RELEASE__ COMPILE_DEFINITIONS_RELWITHDEBINFO __RELEASE__)
target_link_libraries(zsnes zlib ${PNG} ${PLATFORM_LIBS})

install(TARGETS zsnes DESTINATION ${CMAKE_INSTALL_BINDIR})