cmake_minimum_required(VERSION 3.13) if("$ENV{DEVKITPRO}" STREQUAL "") message(FATAL_ERROR "DEVKITPRO is not set. Please export DEVKITPRO to your devkitPro root.") endif() set(DEVKITPRO_ROOT "$ENV{DEVKITPRO}") set(DEVKITPRO_CMAKE "${DEVKITPRO_ROOT}/cmake/NDS.cmake") if(NOT EXISTS "${DEVKITPRO_CMAKE}") message(FATAL_ERROR "Could not find NDS.cmake at ${DEVKITPRO_CMAKE}. Check DEVKITPRO.") endif() # Set target SD directory for generated NDS ROM set(OUTPUT_DIRECTORY "/mnt/6d0c4735-6031-46df-bf0a-b44eeea7dcca") # Ensure re-configure runs in DS context as well. set(CMAKE_SYSTEM_NAME NintendoDS CACHE INTERNAL "Target system" FORCE) set(CMAKE_SYSTEM_PROCESSOR armv5te CACHE INTERNAL "Target CPU" FORCE) include("${DEVKITPRO_CMAKE}") project(snakePlus LANGUAGES C CXX ASM) # Export compile_commands.json for tooling (clangd, IntelliSense, static analysis). set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS ON) set(TARGET_NAME ${PROJECT_NAME}) set(GAME_TITLE "Snake Plus") set(GAME_SUBTITLE1 "Snake with a twist") set(GAME_SUBTITLE2 "Phillip Kuehne") set(GAME_ICON ${CMAKE_CURRENT_SOURCE_DIR}/icon.bmp) file(GLOB_RECURSE SRC_C CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/source/*.c) file(GLOB_RECURSE SRC_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp) file(GLOB_RECURSE SRC_ASM CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/source/*.s) set(TILEMAP_PNG ${CMAKE_CURRENT_SOURCE_DIR}/gfx/tilemap.png) set(TILEMAP_GRIT ${CMAKE_CURRENT_SOURCE_DIR}/gfx/tilemap.grit) set(TILEMAP_S ${CMAKE_CURRENT_BINARY_DIR}/tilemap.s) set(TILEMAP_H ${CMAKE_CURRENT_BINARY_DIR}/tilemap.h) add_custom_command( OUTPUT ${TILEMAP_S} ${TILEMAP_H} COMMAND ${GRIT_EXE} ${TILEMAP_PNG} -fts -o${CMAKE_CURRENT_BINARY_DIR}/tilemap DEPENDS ${TILEMAP_PNG} ${TILEMAP_GRIT} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating tilemap assets with grit" VERBATIM ) add_custom_target(tilemap_assets DEPENDS ${TILEMAP_S} ${TILEMAP_H}) file(GLOB AUDIO_FILES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/sounds/*.*) set(SOUNDBANK_BIN ${CMAKE_CURRENT_BINARY_DIR}/soundbank.bin) set(SOUNDBANK_H ${CMAKE_CURRENT_BINARY_DIR}/soundbank.h) set(SOUNDBANK_BIN_S ${CMAKE_CURRENT_BINARY_DIR}/soundbank_bin.S) set(SOUNDBANK_BIN_H ${CMAKE_CURRENT_BINARY_DIR}/soundbank_bin.h) find_program(MMUTIL_EXE NAMES mmutil HINTS "${DEVKITPRO_ROOT}/tools/bin") find_program(BIN2S_EXE NAMES bin2s HINTS "${DEVKITPRO_ROOT}/tools/bin") if(NOT MMUTIL_EXE) message(FATAL_ERROR "Could not find mmutil") endif() if(NOT BIN2S_EXE) message(FATAL_ERROR "Could not find bin2s") endif() add_custom_command( OUTPUT ${SOUNDBANK_BIN} ${SOUNDBANK_H} ${SOUNDBANK_BIN_S} ${SOUNDBANK_BIN_H} COMMAND ${MMUTIL_EXE} ${AUDIO_FILES} -d -o${SOUNDBANK_BIN} -h${SOUNDBANK_H} COMMAND /bin/sh -c "\"${BIN2S_EXE}\" -a 4 -H \"${SOUNDBANK_BIN_H}\" \"${SOUNDBANK_BIN}\" > \"${SOUNDBANK_BIN_S}\"" DEPENDS ${AUDIO_FILES} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating maxmod soundbank and embedded binary sources" VERBATIM ) add_custom_target(soundbank_assets DEPENDS ${SOUNDBANK_BIN} ${SOUNDBANK_H} ${SOUNDBANK_BIN_S} ${SOUNDBANK_BIN_H}) add_executable(${TARGET_NAME} ${SRC_C} ${SRC_CPP} ${SRC_ASM} ${TILEMAP_S} ${SOUNDBANK_BIN_S} ) add_dependencies(${TARGET_NAME} tilemap_assets soundbank_assets ) target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR} ${DEVKITPRO_ROOT}/libnds/include ${DEVKITPRO_ROOT}/portlibs/nds/include ${DEVKITPRO_ROOT}/portlibs/armv5te/include ) target_link_directories(${TARGET_NAME} PRIVATE ${DEVKITPRO_ROOT}/calico/lib ${DEVKITPRO_ROOT}/libnds/lib ${DEVKITPRO_ROOT}/portlibs/nds/lib ${DEVKITPRO_ROOT}/portlibs/armv5te/lib ) target_compile_definitions(${TARGET_NAME} PRIVATE ARM9 __NDS__ ) target_compile_options(${TARGET_NAME} PRIVATE -g -Wall -O3 -marm -mthumb-interwork -march=armv5te -mtune=arm946e-s -fno-rtti -fno-exceptions ) set(DS9_SPECS_FLAG "-specs=${DEVKITPRO_ROOT}/calico/share/ds9.specs") string(FIND "${CMAKE_EXE_LINKER_FLAGS}" "${DS9_SPECS_FLAG}" _has_ds9_specs) if(_has_ds9_specs EQUAL -1) set(EXTRA_DS9_SPECS_FLAG "${DS9_SPECS_FLAG}") endif() target_link_options(${TARGET_NAME} PRIVATE ${EXTRA_DS9_SPECS_FLAG} -marm -mthumb-interwork -march=armv5te -mtune=arm946e-s -Wl,-Map,${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.map ) target_link_libraries(${TARGET_NAME} PRIVATE mm9 ) set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${PROJECT_NAME} SUFFIX ".elf" RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) set(NDS_OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.nds) find_program(NDSTOOL_EXE NAMES ndstool HINTS "${DEVKITPRO_ROOT}/tools/bin") if(NOT NDSTOOL_EXE) message(FATAL_ERROR "Could not find ndstool") endif() set(ARM7_DEFAULT ${DEVKITPRO_ROOT}/calico/bin/ds7_maine.elf) if(NOT EXISTS ${ARM7_DEFAULT}) message(FATAL_ERROR "Could not find default ARM7 binary: ${ARM7_DEFAULT}") endif() add_custom_command( OUTPUT ${NDS_OUTPUT} COMMAND ${NDSTOOL_EXE} -c ${NDS_OUTPUT} -9 $ -7 ${ARM7_DEFAULT} -b ${GAME_ICON} "${GAME_TITLE}\;${GAME_SUBTITLE1}\;${GAME_SUBTITLE2}" DEPENDS ${TARGET_NAME} ${GAME_ICON} COMMENT "Building NDS ROM image" VERBATIM ) add_custom_target(${TARGET_NAME}_nds ALL DEPENDS ${NDS_OUTPUT}) add_custom_target(run COMMAND melonDS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.nds DEPENDS ${TARGET_NAME}_nds USES_TERMINAL COMMENT "Running ROM in melonDS" ) add_custom_target(install_sd COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.nds ${OUTPUT_DIRECTORY} DEPENDS ${TARGET_NAME}_nds COMMENT "Copying ROM to SD card" )