Browse Source

[3DS] CMake instructions

pull/1032/head
MrHuu 6 years ago committed by Anders Jenbo
parent
commit
d56cc3cb40
  1. 21
      .circleci/config.yml
  2. 48
      CMake/ctr/FindCTRULIB.cmake
  3. 511
      CMake/ctr/Tools3DS.cmake
  4. 3
      CMake/ctr/bin2s_header.h.in
  5. 63
      CMake/ctr/devkitarm-libctru.cmake
  6. 61
      CMake/ctr/modules/FindCITRO3D.cmake
  7. 54
      CMake/ctr/modules/FindFreetype.cmake
  8. 60
      CMake/ctr/modules/FindMAD.cmake
  9. 60
      CMake/ctr/modules/FindMikMod.cmake
  10. 60
      CMake/ctr/modules/FindOgg.cmake
  11. 60
      CMake/ctr/modules/FindPNG.cmake
  12. 66
      CMake/ctr/modules/FindVorbis.cmake
  13. 51
      CMake/ctr/modules/FindZLIB.cmake
  14. 265
      CMake/ctr/modules/LibFindMacros.cmake
  15. 15
      CMake/ctr/modules/try_add_imported_target.cmake
  16. 63
      CMakeLists.txt
  17. 57
      Packaging/ctr/build.sh
  18. 31
      README.md

21
.circleci/config.yml

@ -112,6 +112,26 @@ jobs:
- run: PKG_CONFIG_PATH=/opt/m68k-amigaos/lib/pkgconfig/:/opt/m68k-amigaos/share/pkgconfig/ cmake -S. -Bbuild -DM68K_CPU=68040 -DM68K_FPU=hard -DM68K_COMMON="-s -ffast-math -O3 -noixemul -D__BIG_ENDIAN__ -D__AMIGA__ -fpermissive" ..
- run: cd build && make -j$(nproc)
- store_artifacts: {path: ./build/devilutionx, destination: devilutionx_m68k}
3ds:
docker:
- image: devkitpro/devkitarm:latest
working_directory: ~/repo
steps:
- checkout
- run: echo deb http://deb.debian.org/debian stretch-backports main > /etc/apt/sources.list.d/debian-backports.list
- run: echo deb http://deb.debian.org/debian stretch-backports-sloppy main >> /etc/apt/sources.list.d/debian-backports.list
- run: apt-get update && apt-get install -y -t 'stretch-backports*' cmake unzip
- run: dkp-pacman -Syu --noconfirm
- run: dkp-pacman -S --needed --noconfirm --quiet devkitpro-pkgbuild-helpers
- run: wget https://github.com/Steveice10/bannertool/releases/download/1.1.0/bannertool.zip
- run: unzip -j "bannertool.zip" "linux-x86_64/bannertool" -d "/opt/devkitpro/tools/bin"
- run: wget https://github.com/jakcron/Project_CTR/releases/download/v0.16/makerom_016_ctrtool.zip
- run: unzip -j "makerom_016_ctrtool.zip" "Ubuntu/makerom" -d "/opt/devkitpro/tools/bin"
- run: sudo chmod +rx /opt/devkitpro/tools/bin/makerom
- run: cd build && cmake .. -DNIGHTLY_BUILD=ON -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/3ds.cmake
- run: cd build && cmake --build . -j $(nproc)
- store_artifacts: {path: ./build/devilutionx.3dsx, destination: devilutionx.3dsx}
- store_artifacts: {path: ./build/devilutionx.cia, destination: devilutionx.cia}
workflows:
version: 2
@ -124,4 +144,5 @@ workflows:
- windows_x64
- linux_x86_64_sdl1
- switch
- 3ds
- amigaos-m68k

48
CMake/ctr/FindCTRULIB.cmake

@ -0,0 +1,48 @@
# - Try to find ctrulib
# Once done this will define
# LIBCTRU_FOUND - System has ctrulib
# LIBCTRU_INCLUDE_DIRS - The ctrulib include directories
# LIBCTRU_LIBRARIES - The libraries needed to use ctrulib
#
# It also adds an imported target named `3ds::ctrulib`.
# Linking it is the same as target_link_libraries(target ${LIBCTRU_LIBRARIES}) and target_include_directories(target ${LIBCTRU_INCLUDE_DIRS})
# DevkitPro paths are broken on windows, so we have to fix those
macro(msys_to_cmake_path MsysPath ResultingPath)
string(REGEX REPLACE "^/([a-zA-Z])/" "\\1:/" ${ResultingPath} "${MsysPath}")
endmacro()
if(NOT DEVKITPRO)
msys_to_cmake_path("$ENV{DEVKITPRO}" DEVKITPRO)
endif()
set(CTRULIB_PATHS $ENV{CTRULIB} libctru ctrulib ${DEVKITPRO}/libctru ${DEVKITPRO}/ctrulib)
find_path(LIBCTRU_INCLUDE_DIR 3ds.h
PATHS ${CTRULIB_PATHS}
PATH_SUFFIXES include libctru/include )
find_library(LIBCTRU_LIBRARY NAMES ctru libctru.a
PATHS ${CTRULIB_PATHS}
PATH_SUFFIXES lib libctru/lib )
set(LIBCTRU_LIBRARIES ${LIBCTRU_LIBRARY} )
set(LIBCTRU_INCLUDE_DIRS ${LIBCTRU_INCLUDE_DIR} )
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set LIBCTRU_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(CTRULIB DEFAULT_MSG
LIBCTRU_LIBRARY LIBCTRU_INCLUDE_DIR)
mark_as_advanced(LIBCTRU_INCLUDE_DIR LIBCTRU_LIBRARY )
if(CTRULIB_FOUND)
set(CTRULIB ${LIBCTRU_INCLUDE_DIR}/..)
message(STATUS "setting CTRULIB to ${CTRULIB}")
add_library(3ds::ctrulib STATIC IMPORTED GLOBAL)
set_target_properties(3ds::ctrulib PROPERTIES
IMPORTED_LOCATION "${LIBCTRU_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${LIBCTRU_INCLUDE_DIR}"
)
endif()

511
CMake/ctr/Tools3DS.cmake

@ -0,0 +1,511 @@
############################################################################
# Various macros for 3DS homebrews tools
#
# add_3dsx_target
# ^^^^^^^^^^^^^^^
#
# This macro has two signatures :
#
# ## add_3dsx_target(target [NO_SMDH])
#
# Adds a target that generates a .3dsx file from `target`. If NO_SMDH is specified, no .smdh file will be generated.
#
# You can set the following variables to change the SMDH file :
#
# * APP_TITLE is the name of the app stored in the SMDH file (Optional)
# * APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# * APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# * APP_ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - $(target).png
# - icon.png
# - $(libctru folder)/default_icon.png
#
# ## add_3dsx_target(target APP_TITLE APP_DESCRIPTION APP_AUTHOR [APP_ICON])
#
# This version will produce the SMDH with tha values passed as arguments. Tha APP_ICON is optional and follows the same rule as the other version of `add_3dsx_target`.
#
# add_cia_target(target RSF IMAGE SOUND [APP_TITLE APP_DESCRIPTION APP_AUTHOR [APP_ICON]])
# ^^^^^^^^^^^^^^
#
# Same as add_3dsx_target but for CIA files.
#
# RSF is the .rsf file to be given to makerom.
# IMAGE is either a .png or a cgfximage file.
# SOUND is either a .wav or a cwavaudio file.
#
# add_netload_target(name target_or_file)
# ^^^^^^^^^^^^^^^^^^
#
# Adds a target `name` that sends a .3dsx using the homebrew launcher netload system (3dslink).
# target_or_file is either the name of a target or of file.
#
# add_binary_library(target input1 [input2 ...])
# ^^^^^^^^^^^^^^^^^^
#
# /!\ Requires ASM to be enabled ( `enable_language(ASM)` or `project(yourprojectname C CXX ASM)`)
#
# Converts the files given as input to arrays of their binary data. This is useful to embed resources into your project.
# For example, logo.bmp will generate the array `u8 logo_bmp[]` and its size `logo_bmp_size`. By linking this library, you
# will also have access to a generated header file called `logo_bmp.h` which contains the declarations you need to use it.
#
# Note : All dots in the filename are converted to `_`, and if it starts with a number, `_` will be prepended.
# For example 8x8.gas.tex would give the name _8x8_gas_tex.
#
# target_embed_file(target input1 [input2 ...])
# ^^^^^^^^^^^^^^^^^
#
# Same as add_binary_library(tempbinlib input1 [input2 ...]) + target_link_libraries(target tempbinlib)
#
# add_shbin(output input [entrypoint] [shader_type])
# ^^^^^^^^^^^^^^^^^^^^^^^
#
# Assembles the shader given as `input` into the file `output`. No file extension is added.
# You can choose the shader assembler by setting SHADER_AS to `picasso` or `nihstro`.
#
# If `nihstro` is set as the assembler, entrypoint and shader_type will be used.
# entrypoint is set to `main` by default
# shader_type can be either VSHADER or GSHADER. By default it is VSHADER.
#
# generate_shbins(input1 [input2 ...])
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#
# Assemble all the shader files given as input into .shbin files. Those will be located in the folder `shaders` of the build directory.
# The names of the output files will be <name of input without longest extension>.shbin. vshader.pica will output shader.shbin but shader.vertex.pica will output shader.shbin too.
#
# add_shbin_library(target input1 [input2 ...])
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#
# /!\ Requires ASM to be enabled ( `enable_language(ASM)` or `project(yourprojectname C CXX ASM)`)
#
# This is the same as calling generate_shbins and add_binary_library. This is the function to be used to reproduce devkitArm makefiles behaviour.
# For example, add_shbin_library(shaders data/my1stshader.vsh.pica) will generate the target library `shaders` and you
# will be able to use the shbin in your program by linking it, including `my1stshader_pica.h` and using `my1stshader_pica[]` and `my1stshader_pica_size`.
#
# target_embed_shader(target input1 [input2 ...])
# ^^^^^^^^^^^^^^^^^
#
# Same as add_shbin_library(tempbinlib input1 [input2 ...]) + target_link_libraries(target tempbinlib)
#
############################################################################
if(NOT 3DS)
message(WARNING "Those tools can only be used if you are using the 3DS toolchain file. Please erase this build directory or create another one, and then use -DCMAKE_TOOLCHAIN_FILE=DevkitArm3DS.cmake when calling cmake for the 1st time. For more information, see the Readme.md for more information.")
endif()
get_filename_component(__tools3dsdir ${CMAKE_CURRENT_LIST_FILE} PATH) # Used to locate files to be used with configure_file
message(STATUS "Looking for 3ds tools...")
##############
## 3DSXTOOL ##
##############
if(NOT _3DSXTOOL)
# message(STATUS "Looking for 3dsxtool...")
find_program(_3DSXTOOL 3dsxtool ${DEVKITARM}/bin)
if(_3DSXTOOL)
message(STATUS "3dsxtool: ${_3DSXTOOL} - found")
else()
message(WARNING "3dsxtool - not found")
endif()
endif()
##############
## SMDHTOOL ##
##############
if(NOT SMDHTOOL)
# message(STATUS "Looking for smdhtool...")
find_program(SMDHTOOL smdhtool ${DEVKITARM}/bin)
if(SMDHTOOL)
message(STATUS "smdhtool: ${SMDHTOOL} - found")
else()
message(WARNING "smdhtool - not found")
endif()
endif()
################
## BANNERTOOL ##
################
if(NOT BANNERTOOL)
# message(STATUS "Looking for bannertool...")
find_program(BANNERTOOL bannertool ${DEVKITARM}/bin)
if(BANNERTOOL)
message(STATUS "bannertool: ${BANNERTOOL} - found")
else()
message(WARNING "bannertool - not found")
endif()
endif()
set(FORCE_SMDHTOOL FALSE CACHE BOOL "Force the use of smdhtool instead of bannertool")
#############
## MAKEROM ##
#############
if(NOT MAKEROM)
# message(STATUS "Looking for makerom...")
find_program(MAKEROM makerom ${DEVKITARM}/bin)
if(MAKEROM)
message(STATUS "makerom: ${MAKEROM} - found")
else()
message(WARNING "makerom - not found")
endif()
endif()
#############
## STRIP ##
#############
if(NOT STRIP)
# message(STATUS "Looking for strip...")
find_program(STRIP arm-none-eabi-strip ${DEVKITARM}/bin)
if(STRIP)
message(STATUS "strip: ${STRIP} - found")
else()
message(WARNING "strip - not found")
endif()
endif()
#############
## BIN2S ##
#############
if(NOT BIN2S)
# message(STATUS "Looking for bin2s...")
find_program(BIN2S bin2s ${DEVKITARM}/bin)
if(BIN2S)
message(STATUS "bin2s: ${BIN2S} - found")
else()
message(WARNING "bin2s - not found")
endif()
endif()
###############
## 3DSLINK ##
###############
if(NOT _3DSLINK)
# message(STATUS "Looking for 3dslink...")
find_program(_3DSLINK 3dslink ${DEVKITARM}/bin)
if(_3DSLINK)
message(STATUS "3dslink: ${_3DSLINK} - found")
else()
message(WARNING "3dslink - not found")
endif()
endif()
#############
## PICASSO ##
#############
if(NOT PICASSO_EXE)
# message(STATUS "Looking for Picasso...")
find_program(PICASSO_EXE picasso ${DEVKITARM}/bin)
if(PICASSO_EXE)
message(STATUS "Picasso: ${PICASSO_EXE} - found")
set(SHADER_AS picasso CACHE STRING "The shader assembler to be used. Allowed values are 'none', 'picasso' or 'nihstro'")
else()
message(STATUS "Picasso - not found")
endif()
endif()
#############
## NIHSTRO ##
#############
if(NOT NIHSTRO_AS)
# message(STATUS "Looking for nihstro...")
find_program(NIHSTRO_AS nihstro ${DEVKITARM}/bin)
if(NIHSTRO_AS)
message(STATUS "nihstro: ${NIHSTRO_AS} - found")
set(SHADER_AS nihstro CACHE STRING "The shader assembler to be used. Allowed values are 'none', 'picasso' or 'nihstro'")
else()
message(STATUS "nihstro - not found")
endif()
endif()
set(SHADER_AS none CACHE STRING "The shader assembler to be used. Allowed values are 'none', 'picasso' or 'nihstro'")
###############################
###############################
######## MACROS #########
###############################
###############################
###################
### EXECUTABLES ###
###################
function(__add_smdh target APP_TITLE APP_DESCRIPTION APP_AUTHOR APP_ICON)
if(BANNERTOOL AND NOT FORCE_SMDHTOOL)
set(__SMDH_COMMAND ${BANNERTOOL} makesmdh -s ${APP_TITLE} -l ${APP_DESCRIPTION} -p ${APP_AUTHOR} -i ${APP_ICON} -o ${CMAKE_CURRENT_BINARY_DIR}/${target})
else()
set(__SMDH_COMMAND ${SMDHTOOL} --create ${APP_TITLE} ${APP_DESCRIPTION} ${APP_AUTHOR} ${APP_ICON} ${CMAKE_CURRENT_BINARY_DIR}/${target})
endif()
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target}
COMMAND ${__SMDH_COMMAND}
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
DEPENDS ${APP_ICON}
VERBATIM
)
endfunction()
function(add_3dsx_target target)
get_filename_component(target_we ${target} NAME_WE)
if((NOT (${ARGC} GREATER 1 AND "${ARGV1}" STREQUAL "NO_SMDH") ) OR (${ARGC} GREATER 3) )
if(${ARGC} GREATER 3)
set(APP_TITLE ${ARGV1})
set(APP_DESCRIPTION ${ARGV2})
set(APP_AUTHOR ${ARGV3})
endif()
if(${ARGC} EQUAL 5)
set(APP_ICON ${ARGV4})
endif()
if(NOT APP_TITLE)
set(APP_TITLE ${target})
endif()
if(NOT APP_DESCRIPTION)
set(APP_DESCRIPTION "Built with devkitARM & libctru")
endif()
if(NOT APP_AUTHOR)
set(APP_AUTHOR "Unspecified Author")
endif()
if(NOT APP_ICON)
if(EXISTS ${target}.png)
set(APP_ICON ${target}.png)
elseif(EXISTS icon.png)
set(APP_ICON icon.png)
elseif(CTRULIB)
set(APP_ICON ${CTRULIB}/default_icon.png)
else()
message(FATAL_ERROR "No icon found ! Please use NO_SMDH or provide some icon.")
endif()
endif()
if( NOT ${target_we}.smdh)
__add_smdh(${target_we}.smdh ${APP_TITLE} ${APP_DESCRIPTION} ${APP_AUTHOR} ${APP_ICON})
endif()
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.3dsx
COMMAND ${_3DSXTOOL} $<TARGET_FILE:${target}> ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.3dsx --smdh=${CMAKE_CURRENT_BINARY_DIR}/${target_we}.smdh
DEPENDS ${target} ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.smdh
VERBATIM
)
else()
message(STATUS "No smdh file will be generated")
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.3dsx
COMMAND ${_3DSXTOOL} $<TARGET_FILE:${target}> ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.3dsx
DEPENDS ${target}
VERBATIM
)
endif()
add_custom_target(${target_we}_3dsx ALL SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.3dsx)
set_target_properties(${target} PROPERTIES LINK_FLAGS "-specs=3dsx.specs")
endfunction()
function(__add_ncch_banner target IMAGE SOUND)
if(IMAGE MATCHES ".*\\.png$")
set(IMG_PARAM -i ${IMAGE})
else()
set(IMG_PARAM -ci ${IMAGE})
endif()
if(SOUND MATCHES ".*\\.wav$")
set(SND_PARAM -a ${SOUND})
else()
set(SND_PARAM -ca ${SOUND})
endif()
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target}
COMMAND ${BANNERTOOL} makebanner -o ${CMAKE_CURRENT_BINARY_DIR}/${target} ${IMG_PARAM} ${SND_PARAM}
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
DEPENDS ${IMAGE} ${SOUND}
VERBATIM
)
endfunction()
function(add_cia_target target RSF IMAGE SOUND )
get_filename_component(target_we ${target} NAME_WE)
if(${ARGC} GREATER 6)
set(APP_TITLE ${ARGV4})
set(APP_DESCRIPTION ${ARGV5})
set(APP_AUTHOR ${ARGV6})
endif()
if(${ARGC} EQUAL 8)
set(APP_ICON ${ARGV7})
endif()
if(NOT APP_TITLE)
set(APP_TITLE ${target})
endif()
if(NOT APP_DESCRIPTION)
set(APP_DESCRIPTION "Built with devkitARM & libctru")
endif()
if(NOT APP_AUTHOR)
set(APP_AUTHOR "Unspecified Author")
endif()
if(NOT APP_ICON)
if(EXISTS ${target}.png)
set(APP_ICON ${target}.png)
elseif(EXISTS icon.png)
set(APP_ICON icon.png)
elseif(CTRULIB)
set(APP_ICON ${CTRULIB}/default_icon.png)
else()
message(FATAL_ERROR "No icon found ! Please use NO_SMDH or provide some icon.")
endif()
endif()
if( NOT ${target_we}.smdh)
__add_smdh(${target_we}.smdh ${APP_TITLE} ${APP_DESCRIPTION} ${APP_AUTHOR} ${APP_ICON})
endif()
__add_ncch_banner(${target_we}.bnr ${IMAGE} ${SOUND})
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.cia
COMMAND ${STRIP} -o $<TARGET_FILE:${target}>-stripped $<TARGET_FILE:${target}>
COMMAND ${MAKEROM} -f cia
-target t
-exefslogo
-o ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.cia
-elf $<TARGET_FILE:${target}>-stripped
-rsf ${RSF}
-banner ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.bnr
-icon ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.smdh
DEPENDS ${target} ${RSF} ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.bnr ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.smdh
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
VERBATIM
)
add_custom_target(${target_we}_cia ALL SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.cia)
set_target_properties(${target} PROPERTIES LINK_FLAGS "-specs=3dsx.specs")
endfunction()
macro(add_netload_target name target)
set(NETLOAD_IP "" CACHE STRING "The ip address of the 3ds when using netload.")
if(NETLOAD_IP)
set(__NETLOAD_IP_OPTION -a ${NETLOAD_IP})
endif()
if(NOT TARGET ${target})
message("NOT ${target}")
set(FILE ${target})
else()
set(FILE ${CMAKE_CURRENT_BINARY_DIR}/${target}.3dsx)
endif()
add_custom_target(${name}
COMMAND ${_3DSLINK} ${FILE} ${__NETLOAD_IP_OPTION}
DEPENDS ${FILE}
)
endmacro()
######################
### File embedding ###
######################
macro(add_binary_library libtarget)
if(NOT ${ARGC} GREATER 1)
message(FATAL_ERROR "add_binary_library : Argument error (no input files)")
endif()
get_cmake_property(ENABLED_LANGUAGES ENABLED_LANGUAGES)
if(NOT ENABLED_LANGUAGES MATCHES ".*ASM.*")
message(FATAL_ERROR "You have to enable ASM in order to use add_binary_library (or any target_embed_* which relies on it). Use enable_language(ASM) in your CMakeLists. Currently enabled languages are ${ENABLED_LANGUAGES}")
endif()
foreach(__file ${ARGN})
get_filename_component(__file_wd ${__file} NAME)
string(REGEX REPLACE "^([0-9])" "_\\1" __BIN_FILE_NAME ${__file_wd}) # add '_' if the file name starts by a number
string(REGEX REPLACE "[-./]" "_" __BIN_FILE_NAME ${__BIN_FILE_NAME})
#Generate the header file
configure_file(${__tools3dsdir}/bin2s_header.h.in ${CMAKE_CURRENT_BINARY_DIR}/${libtarget}_include/${__BIN_FILE_NAME}.h)
endforeach()
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/binaries_asm)
# Generate the assembly file, and create the new target
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/binaries_asm/${libtarget}.s
COMMAND ${BIN2S} ${ARGN} > ${CMAKE_CURRENT_BINARY_DIR}/binaries_asm/${libtarget}.s
DEPENDS ${ARGN}
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
)
add_library(${libtarget} ${CMAKE_CURRENT_BINARY_DIR}/binaries_asm/${libtarget}.s)
target_include_directories(${libtarget} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/${libtarget}_include)
endmacro()
macro(target_embed_file _target)
if(NOT ${ARGC} GREATER 1)
message(FATAL_ERROR "target_embed_file : Argument error (no input files)")
endif()
get_filename_component(__1st_file_wd ${ARGV1} NAME)
add_binary_library(__${_target}_embed_${__1st_file_wd} ${ARGN})
target_link_libraries(${_target} __${_target}_embed_${__1st_file_wd})
endmacro()
###################
##### SHADERS #####
###################
macro(add_shbin OUTPUT INPUT )
if(SHADER_AS STREQUAL "picasso")
if(${ARGC} GREATER 2)
message(WARNING "Picasso doesn't support changing the entrypoint or shader type")
endif()
add_custom_command(OUTPUT ${OUTPUT} COMMAND ${PICASSO_EXE} -o ${OUTPUT} ${INPUT} WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
elseif(SHADER_AS STREQUAL "nihstro")
if(NOT NIHSTRO_AS)
message(SEND_ERROR "SHADER_AS is set to nihstro, but nihstro wasn't found. Please set NIHSTRO_AS.")
endif()
if(${ARGC} GREATER 2)
if(${ARGV2} EQUAL GSHADER)
set(SHADER_TYPE_FLAG "-g")
elseif(NOT ${ARGV2} EQUAL VSHADER)
set(_ENTRYPOINT ${ARGV2})
endif()
endif()
if(${ARGC} GREATER 3)
if(${ARGV2} EQUAL GSHADER)
set(SHADER_TYPE_FLAG "-g")
elseif(NOT ${ARGV3} EQUAL VSHADER)
set(_ENTRYPOINT ${ARGV3})
endif()
endif()
if(NOT _ENTRYPOINT)
set(_ENTRYPOINT "main")
endif()
add_custom_command(OUTPUT ${OUTPUT} COMMAND ${NIHSTRO_AS} ${INPUT} -o ${OUTPUT} -e ${_ENTRYPOINT} ${SHADER_TYPE_FLAG} WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
else()
message(FATAL_ERROR "Please set SHADER_AS to 'picasso' or 'nihstro' if you use the shbin feature.")
endif()
endmacro()
function(generate_shbins)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/shaders)
foreach(__shader_file ${ARGN})
get_filename_component(__shader_file_we ${__shader_file} NAME_WE)
#Generate the shbin file
list(APPEND __SHADERS_BIN_FILES ${CMAKE_CURRENT_BINARY_DIR}/shaders/${__shader_file_we}.shbin)
add_shbin(${CMAKE_CURRENT_BINARY_DIR}/shaders/${__shader_file_we}.shbin ${__shader_file})
endforeach()
endfunction()
function(add_shbin_library libtarget)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/shaders)
foreach(__shader_file ${ARGN})
get_filename_component(__shader_file_we ${__shader_file} NAME_WE)
#Generate the shbin file
list(APPEND __SHADERS_BIN_FILES ${CMAKE_CURRENT_BINARY_DIR}/shaders/${__shader_file_we}.shbin)
add_shbin(${CMAKE_CURRENT_BINARY_DIR}/shaders/${__shader_file_we}.shbin ${__shader_file})
endforeach()
add_binary_library(${libtarget} ${__SHADERS_BIN_FILES})
endfunction()
macro(target_embed_shader _target)
if(NOT ${ARGC} GREATER 1)
message(FATAL_ERROR "target_embed_shader : Argument error (no input files)")
endif()
get_filename_component(__1st_file_wd ${ARGV1} NAME)
add_shbin_library(__${_target}_embed_${__1st_file_wd} ${ARGN})
target_link_libraries(${_target} __${_target}_embed_${__1st_file_wd})
endmacro()

3
CMake/ctr/bin2s_header.h.in

@ -0,0 +1,3 @@
extern const u8 @__BIN_FILE_NAME@_end[];
extern const u8 @__BIN_FILE_NAME@[];
extern const u32 @__BIN_FILE_NAME@_size;

63
CMake/ctr/devkitarm-libctru.cmake

@ -0,0 +1,63 @@
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR armv6k)
set(3DS TRUE) # To be used for multiplatform projects
# DevkitPro Paths are broken on windows, so we have to fix those
macro(msys_to_cmake_path MsysPath ResultingPath)
if(WIN32)
string(REGEX REPLACE "^/([a-zA-Z])/" "\\1:/" ${ResultingPath} "${MsysPath}")
else()
set(${ResultingPath} "${MsysPath}")
endif()
endmacro()
msys_to_cmake_path("$ENV{DEVKITPRO}" DEVKITPRO)
if(NOT IS_DIRECTORY ${DEVKITPRO})
message(FATAL_ERROR "Please set DEVKITPRO in your environment")
endif()
msys_to_cmake_path("$ENV{DEVKITARM}" DEVKITARM)
if(NOT IS_DIRECTORY ${DEVKITARM})
message(FATAL_ERROR "Please set DEVKITARM in your environment")
endif()
# Prefix detection only works with compiler id "GNU"
# CMake will look for prefixed g++, cpp, ld, etc. automatically
if(WIN32)
set(CMAKE_C_COMPILER "${DEVKITARM}/bin/arm-none-eabi-gcc.exe")
set(CMAKE_CXX_COMPILER "${DEVKITARM}/bin/arm-none-eabi-g++.exe")
set(CMAKE_AR "${DEVKITARM}/bin/arm-none-eabi-gcc-ar.exe" CACHE STRING "")
set(CMAKE_RANLIB "${DEVKITARM}/bin/arm-none-eabi-gcc-ranlib.exe" CACHE STRING "")
else()
set(CMAKE_C_COMPILER "${DEVKITARM}/bin/arm-none-eabi-gcc")
set(CMAKE_CXX_COMPILER "${DEVKITARM}/bin/arm-none-eabi-g++")
set(CMAKE_AR "${DEVKITARM}/bin/arm-none-eabi-gcc-ar" CACHE STRING "")
set(CMAKE_RANLIB "${DEVKITARM}/bin/arm-none-eabi-gcc-ranlib" CACHE STRING "")
endif()
set(WITH_PORTLIBS ON CACHE BOOL "use portlibs ?")
if(WITH_PORTLIBS)
set(CMAKE_FIND_ROOT_PATH ${DEVKITARM} ${DEVKITPRO} ${DEVKITPRO}/portlibs/3ds)
else()
set(CMAKE_FIND_ROOT_PATH ${DEVKITARM} ${DEVKITPRO})
endif()
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
SET(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Shared libs not available" )
add_definitions(-D__3DS__ -D_3DS)
set(ARCH "-march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft ")
set(CMAKE_C_FLAGS " -mword-relocations ${ARCH}" CACHE STRING "C flags")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "C++ flags")
set(DKA_SUGGESTED_C_FLAGS "-fomit-frame-pointer")
set(DKA_SUGGESTED_CXX_FLAGS "${DKA_SUGGESTED_C_FLAGS} -fno-rtti -fno-exceptions -std=gnu++11")
set(CMAKE_INSTALL_PREFIX ${DEVKITPRO}/portlibs/3ds
CACHE PATH "Install libraries in the portlibs dir")

61
CMake/ctr/modules/FindCITRO3D.cmake

@ -0,0 +1,61 @@
# - Try to find citro3d
# You can set CITRO3D_ROOT to specify a certain directory to look in first.
# Once done this will define
# CITRO3D_FOUND - System has citro3d
# CITRO3D_INCLUDE_DIRS - The citro3d include directories
# CITRO3D_LIBRARIES - The libraries needed to use citro3d
# Unless we are unable to find CTRULIB
# It also adds an imported target named `3ds::citro3d`, Linking against it is
# equivalent to:
# target_link_libraries(mytarget ${CITRO3D_LIBRARIES})
# target_include_directories(mytarget PRIVATE ${CITRO3D_INCLUDE_DIRS})
if(NOT 3DS)
message(FATAL_ERROR "This module can only be used if you are using the 3DS toolchain file. Please erase this build directory or create another one, and then use -DCMAKE_TOOLCHAIN_FILE=DevkitArm3DS.cmake when calling cmake for the 1st time. For more information, see the Readme.md for more information.")
endif()
include(LibFindMacros)
include(try_add_imported_target)
# citro3d requires ctrulib
libfind_package(CITRO3D CTRULIB)
set(_CITRO3D_SEARCHES)
# Search CITRO3D_ROOT first if it is set.
if(CITRO3D_ROOT)
set(_CITRO3D_SEARCH_ROOT
PATHS ${CITRO3D_ROOT}
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH)
list(APPEND _CITRO3D_SEARCHES _CITRO3D_SEARCH_ROOT)
endif()
# Search below ${DEVKITPRO}, ${DEVKITARM} etc.
set(_CITRO3D_SEARCH_NORMAL
PATHS / /citro3d /libctru /ctrulib
NO_DEFAULT_PATH
ONLY_CMAKE_FIND_ROOT_PATH)
list(APPEND _CITRO3D_SEARCHES _CITRO3D_SEARCH_NORMAL)
foreach(search ${_CITRO3D_SEARCHES})
find_path(CITRO3D_INCLUDE_DIR NAMES citro3d.h
${${search}}
PATH_SUFFIXES include)
find_library(CITRO3D_LIBRARY NAMES citro3d libcitro3d.a
${${search}}
PATH_SUFFIXES lib)
endforeach()
#find_library(LIBM_LIBRARY NAMES m libm.a
# PATHS / /arm-none-eabi
# PATH_SUFFIXES lib/armv6k/fpu)
set(LIBM_LIBRARY m)
set(CITRO3D_PROCESS_INCLUDES CITRO3D_INCLUDE_DIR)
set(CITRO3D_PROCESS_LIBS CITRO3D_LIBRARY LIBM_LIBRARY)
libfind_process(CITRO3D)
try_add_imported_target(CITRO3D m 3ds::ctrulib)

54
CMake/ctr/modules/FindFreetype.cmake

@ -0,0 +1,54 @@
# - Try to find freetype
# You can set Freetype_ROOT to specify a certain directory to look in first.
# Once done this will define
# Freetype_FOUND - System has freetype
# Freetype_INCLUDE_DIRS - The freetype include directories
# Freetype_LIBRARIES - The libraries needed to use freetype
# Unless we are unable to find ZLIB
# It also adds an imported target named `3ds::freetype`, Linking against it is
# equivalent to:
# target_link_libraries(mytarget ${Freetype_LIBRARIES})
# target_include_directories(mytarget PRIVATE ${Freetype_INCLUDE_DIRS})
if(NOT 3DS)
message(FATAL_ERROR "This module can only be used if you are using the 3DS toolchain file. Please erase this build directory or create another one, and then use -DCMAKE_TOOLCHAIN_FILE=DevkitArm3DS.cmake when calling cmake for the 1st time. For more information, see the Readme.md for more information.")
endif()
include(LibFindMacros)
include(try_add_imported_target)
libfind_package(Freetype ZLIB)
set(_Freetype_SEARCHES)
# Search Freetype_ROOT first if it is set.
if(Freetype_ROOT)
set(_Freetype_SEARCH_ROOT
PATHS ${Freetype_ROOT}
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH)
list(APPEND _Freetype_SEARCHES _Freetype_SEARCH_ROOT)
endif()
# Search below ${DEVKITPRO}, ${DEVKITARM}, portlibs (if enabled) etc.
set(_Freetype_SEARCH_NORMAL
PATHS /
NO_DEFAULT_PATH
ONLY_CMAKE_FIND_ROOT_PATH)
list(APPEND _Freetype_SEARCHES _Freetype_SEARCH_NORMAL)
foreach(search ${_Freetype_SEARCHES})
find_path(Freetype_INCLUDE_DIR NAMES freetype/config/ftheader.h config/ftheader.h
${${search}}
PATH_SUFFIXES include/freetype2 include freetype2)
find_library(Freetype_LIBRARY NAMES freetype libfreetype.a
${${search}}
PATH_SUFFIXES lib)
endforeach()
set(Freetype_PROCESS_INCLUDES Freetype_INCLUDE_DIR)
set(Freetype_PROCESS_LIBS Freetype_LIBRARY)
libfind_process(Freetype)
try_add_imported_target(Freetype 3ds::zlib)

60
CMake/ctr/modules/FindMAD.cmake

@ -0,0 +1,60 @@
# - Try to find mad
# You can set MAD_ROOT to specify a certain directory to look in first.
# Once done this will define
# MAD_FOUND - System has mad
# MAD_INCLUDE_DIRS - The mad include directories
# MAD_LIBRARIES - The libraries needed to use mad
# Unless we are unable to find ZLIB
# It also adds an imported target named `3ds::mad`, Linking against it is
# equivalent to:
# target_link_libraries(mytarget ${MAD_LIBRARIES})
# target_include_directories(mytarget PRIVATE ${MAD_INCLUDE_DIRS})
if(NOT 3DS)
message(FATAL_ERROR "This module can only be used if you are using the 3DS toolchain file. Please erase this build directory or create another one, and then use -DCMAKE_TOOLCHAIN_FILE=DevkitArm3DS.cmake when calling cmake for the 1st time. For more information, see the Readme.md for more information.")
endif()
include(LibFindMacros)
include(try_add_imported_target)
#libfind_package(MAD)
set(_MAD_SEARCHES)
# Search MAD_ROOT first if it is set.
if(MAD_ROOT)
set(_MAD_SEARCH_ROOT
PATHS ${MAD_ROOT}
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH)
list(APPEND _MAD_SEARCHES _MAD_SEARCH_ROOT)
endif()
# Search below ${DEVKITPRO}, ${DEVKITARM}, portlibs (if enabled) etc.
set(_MAD_SEARCH_NORMAL
PATHS /
NO_DEFAULT_PATH
ONLY_CMAKE_FIND_ROOT_PATH)
list(APPEND _MAD_SEARCHES _MAD_SEARCH_NORMAL)
foreach(search ${_MAD_SEARCHES})
find_path(MAD_INCLUDE_DIR NAMES mad.h
${${search}}
PATH_SUFFIXES include)
find_library(MAD_LIBRARY NAMES mad libmad.a
${${search}}
PATH_SUFFIXES lib)
endforeach()
#find_library(LIBM_LIBRARY NAMES m libm.a
# PATHS / /arm-none-eabi
# PATH_SUFFIXES lib/armv6k/fpu)
set(LIBM_LIBRARY m)
set(MAD_PROCESS_INCLUDES MAD_INCLUDE_DIR)
set(MAD_PROCESS_LIBS MAD_LIBRARY LIBM_LIBRARY)
libfind_process(MAD)
try_add_imported_target(MAD m)

60
CMake/ctr/modules/FindMikMod.cmake

@ -0,0 +1,60 @@
# - Try to find mikmod
# You can set MIKMOD_ROOT to specify a certain directory to look in first.
# Once done this will define
# MIKMOD_FOUND - System has mikmod
# MIKMOD_INCLUDE_DIRS - The mikmod include directories
# MIKMOD_LIBRARIES - The libraries needed to use mikmod
# Unless we are unable to find ZLIB
# It also adds an imported target named `3ds::mikmod`, Linking against it is
# equivalent to:
# target_link_libraries(mytarget ${MIKMOD_LIBRARIES})
# target_include_directories(mytarget PRIVATE ${MIKMOD_INCLUDE_DIRS})
if(NOT 3DS)
message(FATAL_ERROR "This module can only be used if you are using the 3DS toolchain file. Please erase this build directory or create another one, and then use -DCMAKE_TOOLCHAIN_FILE=DevkitArm3DS.cmake when calling cmake for the 1st time. For more information, see the Readme.md for more information.")
endif()
include(LibFindMacros)
include(try_add_imported_target)
#libfind_package(MIKMOD)
set(_MIKMOD_SEARCHES)
# Search MIKMOD_ROOT first if it is set.
if(MIKMOD_ROOT)
set(_MIKMOD_SEARCH_ROOT
PATHS ${MIKMOD_ROOT}
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH)
list(APPEND _MIKMOD_SEARCHES _MIKMOD_SEARCH_ROOT)
endif()
# Search below ${DEVKITPRO}, ${DEVKITARM}, portlibs (if enabled) etc.
set(_MIKMOD_SEARCH_NORMAL
PATHS /
NO_DEFAULT_PATH
ONLY_CMAKE_FIND_ROOT_PATH)
list(APPEND _MIKMOD_SEARCHES _MIKMOD_SEARCH_NORMAL)
foreach(search ${_MIKMOD_SEARCHES})
find_path(MIKMOD_INCLUDE_DIR NAMES mikmod.h
${${search}}
PATH_SUFFIXES include)
find_library(MIKMOD_LIBRARY NAMES mikmod libmikmod.a
${${search}}
PATH_SUFFIXES lib)
endforeach()
#find_library(LIBM_LIBRARY NAMES m libm.a
# PATHS / /arm-none-eabi
# PATH_SUFFIXES lib/armv6k/fpu)
set(LIBM_LIBRARY m)
set(MIKMOD_PROCESS_INCLUDES MIKMOD_INCLUDE_DIR)
set(MIKMOD_PROCESS_LIBS MIKMOD_LIBRARY LIBM_LIBRARY)
libfind_process(MIKMOD)
try_add_imported_target(MIKMOD m)

60
CMake/ctr/modules/FindOgg.cmake

@ -0,0 +1,60 @@
# - Try to find ogg
# You can set OGG_ROOT to specify a certain directory to look in first.
# Once done this will define
# OGG_FOUND - System has ogg
# OGG_INCLUDE_DIRS - The ogg include directories
# OGG_LIBRARIES - The libraries needed to use ogg
# Unless we are unable to find ZLIB
# It also adds an imported target named `3ds::ogg`, Linking against it is
# equivalent to:
# target_link_libraries(mytarget ${OGG_LIBRARIES})
# target_include_directories(mytarget PRIVATE ${OGG_INCLUDE_DIRS})
if(NOT 3DS)
message(FATAL_ERROR "This module can only be used if you are using the 3DS toolchain file. Please erase this build directory or create another one, and then use -DCMAKE_TOOLCHAIN_FILE=DevkitArm3DS.cmake when calling cmake for the 1st time. For more information, see the Readme.md for more information.")
endif()
include(LibFindMacros)
include(try_add_imported_target)
#libfind_package(OGG)
set(_OGG_SEARCHES)
# Search OGG_ROOT first if it is set.
if(OGG_ROOT)
set(_OGG_SEARCH_ROOT
PATHS ${OGG_ROOT}
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH)
list(APPEND _OGG_SEARCHES _OGG_SEARCH_ROOT)
endif()
# Search below ${DEVKITPRO}, ${DEVKITARM}, portlibs (if enabled) etc.
set(_OGG_SEARCH_NORMAL
PATHS /
NO_DEFAULT_PATH
ONLY_CMAKE_FIND_ROOT_PATH)
list(APPEND _OGG_SEARCHES _OGG_SEARCH_NORMAL)
foreach(search ${_OGG_SEARCHES})
find_path(OGG_INCLUDE_DIR NAMES ogg/ogg.h
${${search}}
PATH_SUFFIXES include)
find_library(OGG_LIBRARY NAMES ogg libogg.a
${${search}}
PATH_SUFFIXES lib)
endforeach()
#find_library(LIBM_LIBRARY NAMES m libm.a
# PATHS / /arm-none-eabi
# PATH_SUFFIXES lib/armv6k/fpu)
set(LIBM_LIBRARY m)
set(OGG_PROCESS_INCLUDES OGG_INCLUDE_DIR)
set(OGG_PROCESS_LIBS OGG_LIBRARY LIBM_LIBRARY)
libfind_process(OGG)
try_add_imported_target(OGG m)

60
CMake/ctr/modules/FindPNG.cmake

@ -0,0 +1,60 @@
# - Try to find png
# You can set PNG_ROOT to specify a certain directory to look in first.
# Once done this will define
# PNG_FOUND - System has png
# PNG_INCLUDE_DIRS - The png include directories
# PNG_LIBRARIES - The libraries needed to use png
# Unless we are unable to find ZLIB
# It also adds an imported target named `3ds::png`, Linking against it is
# equivalent to:
# target_link_libraries(mytarget ${PNG_LIBRARIES})
# target_include_directories(mytarget PRIVATE ${PNG_INCLUDE_DIRS})
if(NOT 3DS)
message(FATAL_ERROR "This module can only be used if you are using the 3DS toolchain file. Please erase this build directory or create another one, and then use -DCMAKE_TOOLCHAIN_FILE=DevkitArm3DS.cmake when calling cmake for the 1st time. For more information, see the Readme.md for more information.")
endif()
include(LibFindMacros)
include(try_add_imported_target)
libfind_package(PNG ZLIB)
set(_PNG_SEARCHES)
# Search PNG_ROOT first if it is set.
if(PNG_ROOT)
set(_PNG_SEARCH_ROOT
PATHS ${PNG_ROOT}
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH)
list(APPEND _PNG_SEARCHES _PNG_SEARCH_ROOT)
endif()
# Search below ${DEVKITPRO}, ${DEVKITARM}, portlibs (if enabled) etc.
set(_PNG_SEARCH_NORMAL
PATHS /
NO_DEFAULT_PATH
ONLY_CMAKE_FIND_ROOT_PATH)
list(APPEND _PNG_SEARCHES _PNG_SEARCH_NORMAL)
foreach(search ${_PNG_SEARCHES})
find_path(PNG_INCLUDE_DIR NAMES png.h
${${search}}
PATH_SUFFIXES include)
find_library(PNG_LIBRARY NAMES png libpng.a
${${search}}
PATH_SUFFIXES lib)
endforeach()
#find_library(LIBM_LIBRARY NAMES m libm.a
# PATHS / /arm-none-eabi
# PATH_SUFFIXES lib/armv6k/fpu)
set(LIBM_LIBRARY m)
set(PNG_PROCESS_INCLUDES PNG_INCLUDE_DIR)
set(PNG_PROCESS_LIBS PNG_LIBRARY LIBM_LIBRARY)
libfind_process(PNG)
try_add_imported_target(PNG m 3ds::zlib)

66
CMake/ctr/modules/FindVorbis.cmake

@ -0,0 +1,66 @@
# Phaethon - A FLOSS resource explorer for BioWare's Aurora engine games
#
# Phaethon is the legal property of its developers, whose names
# can be found in the AUTHORS file distributed with this source
# distribution.
#
# Phaethon is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# Phaethon is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Phaethon. If not, see <http://www.gnu.org/licenses/>.
# Try to find vorbis library and include path.
# Once done this will define
#
# VORBIS_INCLUDE_DIRS - where to find vorbis/vorbisfile.h, etc.
# VORBIS_LIBRARIES - List of libraries when using libvorbisfile.
# VORBIS_FOUND - True if libvorbisfile found.
if(WIN32)
find_path(VORBIS_INCLUDE_DIR vorbis/vorbisfile.h $ENV{PROGRAMFILES}/vorbis/include DOC "The directory where vorbis/vorbisfile.h resides")
find_library(VORBIS_LIBRARY NAMES vorbis PATHS $ENV{PROGRAMFILES}/vorbis/lib DOC "The libvorbis library")
find_library(VORBISFILE_LIBRARY NAMES vorbisfile PATHS $ENV{PROGRAMFILES}/vorbis/lib DOC "The libvorbisfile library")
else(WIN32)
find_path(VORBIS_INCLUDE_DIR vorbis/vorbisfile.h DOC "The directory where vorbis/vorbisfile.h resides")
find_library(VORBIS_LIBRARY NAMES vorbis DOC "The libvorbis library")
find_library(VORBISFILE_LIBRARY NAMES vorbisfile DOC "The libvorbisfile library")
endif(WIN32)
if(VORBIS_INCLUDE_DIR AND VORBIS_LIBRARY AND VORBISFILE_LIBRARY)
set(VORBIS_FOUND 1)
set(VORBIS_LIBRARIES ${VORBIS_LIBRARY} ${VORBISFILE_LIBRARY})
set(VORBIS_INCLUDE_DIRS ${VORBIS_INCLUDE_DIR})
else(VORBIS_INCLUDE_DIR AND VORBIS_LIBRARY AND VORBISFILE_LIBRARY)
set(VORBIS_FOUND 0)
set(VORBIS_LIBRARIES)
set(VORBIS_INCLUDE_DIRS)
endif(VORBIS_INCLUDE_DIR AND VORBIS_LIBRARY AND VORBISFILE_LIBRARY)
mark_as_advanced(VORBIS_INCLUDE_DIR)
mark_as_advanced(VORBIS_LIBRARY)
mark_as_advanced(VORBISFILE_LIBRARY)
mark_as_advanced(VORBIS_FOUND)
if(NOT VORBIS_FOUND)
set(VORBIS_DIR_MESSAGE "libvorbis and libvorbisfile were not found. Make sure VORBIS_LIBRARY, VORBISFILE_LIBRARY and VORBIS_INCLUDE_DIR are set.")
if(NOT VORBIS_FIND_QUIETLY)
message(STATUS "${VORBIS_DIR_MESSAGE}")
else(NOT VORBIS_FIND_QUIETLY)
if(VORBIS_FIND_REQUIRED)
message(FATAL_ERROR "${VORBIS_DIR_MESSAGE}")
endif(VORBIS_FIND_REQUIRED)
endif(NOT VORBIS_FIND_QUIETLY)
else(NOT VORBIS_FOUND)
message(STATUS "Found libvorbis: ${VORBIS_LIBRARY}")
message(STATUS "Found libvorbisfile: ${VORBISFILE_LIBRARY}")
endif(NOT VORBIS_FOUND)

51
CMake/ctr/modules/FindZLIB.cmake

@ -0,0 +1,51 @@
# - Try to find zlib
# You can set ZLIB_ROOT to specify a certain directory to look in first.
# Once done this will define
# ZLIB_FOUND - System has zlib
# ZLIB_INCLUDE_DIRS - The zlib include directories
# ZLIB_LIBRARIES - The libraries needed to use zlib
# It also adds an imported target named `3ds::zlib`, Linking against it is
# equivalent to:
# target_link_libraries(mytarget ${ZLIB_LIBRARY})
# target_include_directories(mytarget PRIVATE ${ZLIB_INCLUDE_DIRS})
if(NOT 3DS)
message(FATAL_ERROR "This module can only be used if you are using the 3DS toolchain file. Please erase this build directory or create another one, and then use -DCMAKE_TOOLCHAIN_FILE=DevkitArm3DS.cmake when calling cmake for the 1st time. For more information, see the Readme.md for more information.")
endif()
include(LibFindMacros)
include(try_add_imported_target)
set(_ZLIB_SEARCHES)
# Search ZLIB_ROOT first if it is set.
if(ZLIB_ROOT)
set(_ZLIB_SEARCH_ROOT
PATHS ${ZLIB_ROOT}
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH)
list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_ROOT)
endif()
# Search below ${DEVKITPRO}, ${DEVKITARM}, portlibs (if enabled) etc.
set(_ZLIB_SEARCH_NORMAL
PATHS /
NO_DEFAULT_PATH
ONLY_CMAKE_FIND_ROOT_PATH)
list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_NORMAL)
foreach(search ${_ZLIB_SEARCHES})
find_path(ZLIB_INCLUDE_DIR NAMES zlib.h
${${search}}
PATH_SUFFIXES include)
find_library(ZLIB_LIBRARY NAMES z libz.a
${${search}}
PATH_SUFFIXES lib)
endforeach()
set(ZLIB_PROCESS_INCLUDES ZLIB_INCLUDE_DIR)
set(ZLIB_PROCESS_LIBS ZLIB_LIBRARY)
libfind_process(ZLIB)
try_add_imported_target(ZLIB)

265
CMake/ctr/modules/LibFindMacros.cmake

@ -0,0 +1,265 @@
# Version 2.2
# Public Domain, originally written by Lasse Kärkkäinen <tronic>
# Maintained at https://github.com/Tronic/cmake-modules
# Please send your improvements as pull requests on Github.
# Find another package and make it a dependency of the current package.
# This also automatically forwards the "REQUIRED" argument.
# Usage: libfind_package(<prefix> <another package> [extra args to find_package])
macro (libfind_package PREFIX PKG)
set(${PREFIX}_args ${PKG} ${ARGN})
if (${PREFIX}_FIND_REQUIRED)
set(${PREFIX}_args ${${PREFIX}_args} REQUIRED)
endif()
find_package(${${PREFIX}_args})
set(${PREFIX}_DEPENDENCIES ${${PREFIX}_DEPENDENCIES};${PKG})
unset(${PREFIX}_args)
endmacro()
# A simple wrapper to make pkg-config searches a bit easier.
# Works the same as CMake's internal pkg_check_modules but is always quiet.
macro (libfind_pkg_check_modules)
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_check_modules(${ARGN} QUIET)
endif()
endmacro()
# Avoid useless copy&pasta by doing what most simple libraries do anyway:
# pkg-config, find headers, find library.
# Usage: libfind_pkg_detect(<prefix> <pkg-config args> FIND_PATH <name> [other args] FIND_LIBRARY <name> [other args])
# E.g. libfind_pkg_detect(SDL2 sdl2 FIND_PATH SDL.h PATH_SUFFIXES SDL2 FIND_LIBRARY SDL2)
function (libfind_pkg_detect PREFIX)
# Parse arguments
set(argname pkgargs)
foreach (i ${ARGN})
if ("${i}" STREQUAL "FIND_PATH")
set(argname pathargs)
elseif ("${i}" STREQUAL "FIND_LIBRARY")
set(argname libraryargs)
else()
set(${argname} ${${argname}} ${i})
endif()
endforeach()
if (NOT pkgargs)
message(FATAL_ERROR "libfind_pkg_detect requires at least a pkg_config package name to be passed.")
endif()
# Find library
libfind_pkg_check_modules(${PREFIX}_PKGCONF ${pkgargs})
if (pathargs)
find_path(${PREFIX}_INCLUDE_DIR NAMES ${pathargs} HINTS ${${PREFIX}_PKGCONF_INCLUDE_DIRS})
endif()
if (libraryargs)
find_library(${PREFIX}_LIBRARY NAMES ${libraryargs} HINTS ${${PREFIX}_PKGCONF_LIBRARY_DIRS})
endif()
endfunction()
# Extracts a version #define from a version.h file, output stored to <PREFIX>_VERSION.
# Usage: libfind_version_header(Foobar foobar/version.h FOOBAR_VERSION_STR)
# Fourth argument "QUIET" may be used for silently testing different define names.
# This function does nothing if the version variable is already defined.
function (libfind_version_header PREFIX VERSION_H DEFINE_NAME)
# Skip processing if we already have a version or if the include dir was not found
if (${PREFIX}_VERSION OR NOT ${PREFIX}_INCLUDE_DIR)
return()
endif()
set(quiet ${${PREFIX}_FIND_QUIETLY})
# Process optional arguments
foreach(arg ${ARGN})
if (arg STREQUAL "QUIET")
set(quiet TRUE)
else()
message(AUTHOR_WARNING "Unknown argument ${arg} to libfind_version_header ignored.")
endif()
endforeach()
# Read the header and parse for version number
set(filename "${${PREFIX}_INCLUDE_DIR}/${VERSION_H}")
if (NOT EXISTS ${filename})
if (NOT quiet)
message(AUTHOR_WARNING "Unable to find ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}")
endif()
return()
endif()
file(READ "${filename}" header)
string(REGEX REPLACE ".*#[ \t]*define[ \t]*${DEFINE_NAME}[ \t]*\"([^\n]*)\".*" "\\1" match "${header}")
# No regex match?
if (match STREQUAL header)
if (NOT quiet)
message(AUTHOR_WARNING "Unable to find \#define ${DEFINE_NAME} \"<version>\" from ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}")
endif()
return()
endif()
# Export the version string
set(${PREFIX}_VERSION "${match}" PARENT_SCOPE)
endfunction()
# Do the final processing once the paths have been detected.
# If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain
# all the variables, each of which contain one include directory.
# Ditto for ${PREFIX}_PROCESS_LIBS and library files.
# Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES.
# Also handles errors in case library detection was required, etc.
function (libfind_process PREFIX)
# Skip processing if already processed during this configuration run
if (${PREFIX}_FOUND)
return()
endif()
set(found TRUE) # Start with the assumption that the package was found
# Did we find any files? Did we miss includes? These are for formatting better error messages.
set(some_files FALSE)
set(missing_headers FALSE)
# Shorthands for some variables that we need often
set(quiet ${${PREFIX}_FIND_QUIETLY})
set(required ${${PREFIX}_FIND_REQUIRED})
set(exactver ${${PREFIX}_FIND_VERSION_EXACT})
set(findver "${${PREFIX}_FIND_VERSION}")
set(version "${${PREFIX}_VERSION}")
# Lists of config option names (all, includes, libs)
unset(configopts)
set(includeopts ${${PREFIX}_PROCESS_INCLUDES})
set(libraryopts ${${PREFIX}_PROCESS_LIBS})
# Process deps to add to
foreach (i ${PREFIX} ${${PREFIX}_DEPENDENCIES})
if (DEFINED ${i}_INCLUDE_OPTS OR DEFINED ${i}_LIBRARY_OPTS)
# The package seems to export option lists that we can use, woohoo!
list(APPEND includeopts ${${i}_INCLUDE_OPTS})
list(APPEND libraryopts ${${i}_LIBRARY_OPTS})
else()
# If plural forms don't exist or they equal singular forms
if ((NOT DEFINED ${i}_INCLUDE_DIRS AND NOT DEFINED ${i}_LIBRARIES) OR
(${i}_INCLUDE_DIR STREQUAL ${i}_INCLUDE_DIRS AND ${i}_LIBRARY STREQUAL ${i}_LIBRARIES))
# Singular forms can be used
if (DEFINED ${i}_INCLUDE_DIR)
list(APPEND includeopts ${i}_INCLUDE_DIR)
endif()
if (DEFINED ${i}_LIBRARY)
list(APPEND libraryopts ${i}_LIBRARY)
endif()
else()
# Oh no, we don't know the option names
message(FATAL_ERROR "We couldn't determine config variable names for ${i} includes and libs. Aieeh!")
endif()
endif()
endforeach()
if (includeopts)
list(REMOVE_DUPLICATES includeopts)
endif()
if (libraryopts)
list(REMOVE_DUPLICATES libraryopts)
endif()
string(REGEX REPLACE ".*[ ;]([^ ;]*(_INCLUDE_DIRS|_LIBRARIES))" "\\1" tmp "${includeopts} ${libraryopts}")
if (NOT tmp STREQUAL "${includeopts} ${libraryopts}")
message(AUTHOR_WARNING "Plural form ${tmp} found in config options of ${PREFIX}. This works as before but is now deprecated. Please only use singular forms INCLUDE_DIR and LIBRARY, and update your find scripts for LibFindMacros > 2.0 automatic dependency system (most often you can simply remove the PROCESS variables entirely).")
endif()
# Include/library names separated by spaces (notice: not CMake lists)
unset(includes)
unset(libs)
# Process all includes and set found false if any are missing
foreach (i ${includeopts})
list(APPEND configopts ${i})
if (NOT "${${i}}" STREQUAL "${i}-NOTFOUND")
list(APPEND includes "${${i}}")
else()
set(found FALSE)
set(missing_headers TRUE)
endif()
endforeach()
# Process all libraries and set found false if any are missing
foreach (i ${libraryopts})
list(APPEND configopts ${i})
if (NOT "${${i}}" STREQUAL "${i}-NOTFOUND")
list(APPEND libs "${${i}}")
else()
set (found FALSE)
endif()
endforeach()
# Version checks
if (found AND findver)
if (NOT version)
message(WARNING "The find module for ${PREFIX} does not provide version information, so we'll just assume that it is OK. Please fix the module or remove package version requirements to get rid of this warning.")
elseif (version VERSION_LESS findver OR (exactver AND NOT version VERSION_EQUAL findver))
set(found FALSE)
set(version_unsuitable TRUE)
endif()
endif()
# If all-OK, hide all config options, export variables, print status and exit
if (found)
foreach (i ${configopts})
mark_as_advanced(${i})
endforeach()
if (NOT quiet)
message(STATUS "Found ${PREFIX} ${${PREFIX}_LIBRARY} ${${PREFIX}_VERSION}")
if (LIBFIND_DEBUG)
message(STATUS " ${PREFIX}_DEPENDENCIES=${${PREFIX}_DEPENDENCIES}")
message(STATUS " ${PREFIX}_INCLUDE_OPTS=${includeopts}")
message(STATUS " ${PREFIX}_INCLUDE_DIRS=${includes}")
message(STATUS " ${PREFIX}_LIBRARY_OPTS=${libraryopts}")
message(STATUS " ${PREFIX}_LIBRARIES=${libs}")
endif()
endif()
set (${PREFIX}_INCLUDE_OPTS ${includeopts} PARENT_SCOPE)
set (${PREFIX}_LIBRARY_OPTS ${libraryopts} PARENT_SCOPE)
set (${PREFIX}_INCLUDE_DIRS ${includes} PARENT_SCOPE)
set (${PREFIX}_LIBRARIES ${libs} PARENT_SCOPE)
set (${PREFIX}_FOUND TRUE PARENT_SCOPE)
return()
endif()
# Format messages for debug info and the type of error
set(vars "Relevant CMake configuration variables:\n")
foreach (i ${configopts})
mark_as_advanced(CLEAR ${i})
set(val ${${i}})
if ("${val}" STREQUAL "${i}-NOTFOUND")
set (val "<not found>")
elseif (val AND NOT EXISTS ${val})
set (val "${val} (does not exist)")
else()
set(some_files TRUE)
endif()
set(vars "${vars} ${i}=${val}\n")
endforeach()
set(vars "${vars}You may use CMake GUI, cmake -D or ccmake to modify the values. Delete CMakeCache.txt to discard all values and force full re-detection if necessary.\n")
if (version_unsuitable)
set(msg "${PREFIX} ${${PREFIX}_VERSION} was found but")
if (exactver)
set(msg "${msg} only version ${findver} is acceptable.")
else()
set(msg "${msg} version ${findver} is the minimum requirement.")
endif()
else()
if (missing_headers)
set(msg "We could not find development headers for ${PREFIX}. Do you have the necessary dev package installed?")
elseif (some_files)
set(msg "We only found some files of ${PREFIX}, not all of them. Perhaps your installation is incomplete or maybe we just didn't look in the right place?")
if(findver)
set(msg "${msg} This could also be caused by incompatible version (if it helps, at least ${PREFIX} ${findver} should work).")
endif()
else()
set(msg "We were unable to find package ${PREFIX}.")
endif()
endif()
# Fatal error out if REQUIRED
if (required)
set(msg "REQUIRED PACKAGE NOT FOUND\n${msg} This package is REQUIRED and you need to install it or adjust CMake configuration in order to continue building ${CMAKE_PROJECT_NAME}.")
message(FATAL_ERROR "${msg}\n${vars}")
endif()
# Otherwise just print a nasty warning
if (NOT quiet)
message(WARNING "WARNING: MISSING PACKAGE\n${msg} This package is NOT REQUIRED and you may ignore this warning but by doing so you may miss some functionality of ${CMAKE_PROJECT_NAME}. \n${vars}")
endif()
endfunction()

15
CMake/ctr/modules/try_add_imported_target.cmake

@ -0,0 +1,15 @@
macro(try_add_imported_target LIBNAME)
string(TOLOWER ${LIBNAME} ${LIBNAME}_lwr)
set(${LIBNAME}_TARGET 3ds::${${LIBNAME}_lwr})
if(${LIBNAME}_FOUND AND NOT TARGET ${${LIBNAME}_TARGET})
add_library(${${LIBNAME}_TARGET} STATIC IMPORTED GLOBAL)
set_target_properties(${${LIBNAME}_TARGET} PROPERTIES
IMPORTED_LOCATION "${${LIBNAME}_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${${LIBNAME}_INCLUDE_DIR}")
if(${ARGC} GREATER 1)
target_link_libraries(${${LIBNAME}_TARGET} INTERFACE ${ARGN})
endif()
endif()
endmacro()

63
CMakeLists.txt

@ -118,6 +118,11 @@ if(AMIGA)
include(amiga_defs)
endif()
if(N3DS)
list(APPEND CMAKE_MODULE_PATH "${DevilutionX_SOURCE_DIR}/CMake/ctr")
include(n3ds_defs)
endif()
if(DIST)
set(sodium_USE_STATIC_LIBS ON)
endif()
@ -132,7 +137,10 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_THREAD_PREFER_PTHREAD ON)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
if(NOT N3DS)
find_package(Threads REQUIRED)
endif()
if(NOT NONET)
find_package(sodium REQUIRED)
endif()
@ -324,6 +332,16 @@ if(SWITCH)
set(BIN_TARGET devilutionx.elf)
endif()
if(N3DS)
list(APPEND devilutionx_SRCS
SourceX/platform/ctr/system.cpp
SourceX/platform/ctr/keyboard.cpp)
if(HELLFIRE)
set(BIN_TARGET hellfire)
endif()
set(BIN_TARGET ${BIN_TARGET}.elf)
endif()
if(RUN_TESTS)
list(APPEND devilutionx_SRCS
SourceT/appfat_test.cpp
@ -388,10 +406,15 @@ target_include_directories(${BIN_TARGET} PRIVATE
3rdParty/Radon/Radon/include
3rdParty/libsmacker)
target_link_libraries(devilution PUBLIC
if(N3DS)
target_link_libraries(devilution PUBLIC
SourceS)
else()
target_link_libraries(devilution PUBLIC
Threads::Threads
SourceS
)
SourceS)
endif()
target_link_libraries(${BIN_TARGET} PRIVATE
devilution
SourceS
@ -514,6 +537,13 @@ foreach(target devilution ${BIN_TARGET} SourceS)
endif()
endif()
if(N3DS)
target_link_libraries(${target} PRIVATE ${TREMOR_LIBRARIES})
target_include_directories(${target} PRIVATE ${TREMOR_INCLUDE_DIRS})
target_link_libraries(${target} PRIVATE 3ds::ogg 3ds::mikmod 3ds::mad 3ds::freetype 3ds::bzip2 3ds::png)
target_link_libraries(${target} PRIVATE 3ds::citro3d 3ds::ctrulib)
endif()
target_compile_definitions(${target} PRIVATE ${def_list})
endforeach(target)
@ -614,6 +644,31 @@ if(SWITCH)
build_switch_binaries(${BIN_TARGET})
endif()
if(N3DS)
set(APP_TITLE "DevilutionX")
set(APP_DESCRIPTION "DevilutionX port for 3DS")
set(APP_AUTHOR "Diasurgical Team")
set(APP_ICON "${PROJECT_SOURCE_DIR}/Packaging/ctr/icon.png")
set(APP_BANNER "${PROJECT_SOURCE_DIR}/Packaging/ctr/banner.png")
set(APP_AUDIO "${PROJECT_SOURCE_DIR}/Packaging/ctr/audio_silent.wav")
set(APP_RSF "${PROJECT_SOURCE_DIR}/Packaging/ctr/template.rsf")
set(APP_ROMFS "${CMAKE_BINARY_DIR}/romfs")
set(APP_ROMFS_FILES "${PROJECT_SOURCE_DIR}/Packaging/ctr/DiabloLight.ttf")
if(HELLFIRE)
set(APP_TITLE "DevilutionX: Hellfire")
set(APP_ICON "${PROJECT_SOURCE_DIR}/Packaging/ctr/icon_hellfire.png")
set(APP_BANNER "${PROJECT_SOURCE_DIR}/Packaging/ctr/banner_hellfire.png")
set(APP_RSF "${PROJECT_SOURCE_DIR}/Packaging/ctr/template_hellfire.rsf")
endif()
file(MAKE_DIRECTORY ${APP_ROMFS})
file(COPY ${APP_ROMFS_FILES}
DESTINATION ${APP_ROMFS})
set(APP_VERSION ${PROJECT_VERSION})
include(Tools3DS)
add_3dsx_target(${BIN_TARGET})
add_cia_target(${BIN_TARGET} ${APP_RSF} ${APP_BANNER} ${APP_AUDIO} ${APP_ROMFS})
endif()
if(CPACK)
if(NOT SYSTEM_BITS MATCHES x64 AND WIN32)
set(CPACK_PACKAGE_FILE_NAME "devilutionx")

57
Packaging/ctr/build.sh

@ -0,0 +1,57 @@
#!/usr/bin/env bash
set -euo pipefail
DEVKITPRO="${DEVKITPRO:-/opt/devkitpro}"
declare -r DIR="$(dirname "${BASH_SOURCE[0]}")"
cd "$DIR"
main() {
prepare_devkitpro
set -x
install_deps
build
}
build() {
mkdir -p ../../build
cd ../../build
rm -f CMakeCache.txt
DEVKITPRO="$DEVKITPRO" cmake .. -DBINARY_RELEASE=ON -DUSE_SDL1=ON -DNONET=ON \
-DSDL1_VIDEO_MODE_FLAGS='SDL_SWSURFACE|SDL_CONSOLEBOTTOM' \
-DCMAKE_TOOLCHAIN_FILE=../CMake/ctr/devkitarm-libctru.cmake
DEVKITPRO="$DEVKITPRO" make -j "$(nproc)"
cd -
}
install_deps() {
"$DEVKITPRO/pacman/bin/pacman" -S --needed --noconfirm --quiet \
3ds-sdl 3ds-sdl_ttf 3ds-sdl_mixer \
3ds-freetype 3ds-libvorbis 3ds-libmikmod\
libctru devkitARM general-tools 3ds-tools devkitpro-pkgbuild-helpers
}
prepare_devkitpro() {
if [[ -d $DEVKITPRO ]]; then
return;
fi
if which dpkg > /dev/null; then
install_devkitpro_debian
else
>&2 printf "Please set DEVKITPRO:\nhttps://devkitpro.org/wiki/Getting_Started\n"
exit 1
fi
}
install_devkitpro_debian() {
>&2 echo 'Installing devkitpro-pacman.deb from GitHub...'
local -r dpkg_path=/tmp/devkitpro-pacman.deb
set -x
\curl -L https://github.com/devkitPro/pacman/releases/download/devkitpro-pacman-1.0.1/devkitpro-pacman.deb -o "$dpkg_path"
sudo dpkg -i "$dpkg_path"
rm "$dpkg_path"
{ set +x; } 2>/dev/null
}
main

31
README.md

@ -192,6 +192,37 @@ The nro-file will be generated in the build folder. Test with an emulator (RyuJi
[Nintendo Switch manual](docs/manual/platforms/switch.md)
</details>
<details><summary>Nintendo 3DS</summary>
### Installing dependencies
https://devkitpro.org/wiki/Getting_Started
- Install (dkp-)pacman: https://devkitpro.org/wiki/devkitPro_pacman
- Install required packages with (dkp-)pacman:
```
sudo (dkp-)pacman -S devkitARM general-tools 3dstools devkitpro-pkgbuild-helpers \
libctru citro3d 3ds-sdl 3ds-sdl_ttf 3ds-sdl_mixer \
3ds-freetype 3ds-libogg 3ds-libvorbisidec 3ds-mikmod
```
- Download or compile [bannertool](https://github.com/Steveice10/bannertool/releases) and [makerom](https://github.com/jakcron/Project_CTR/releases)
- Copy binaries to: `/opt/devkitpro/tools/bin/`
### Compiling
```
cd build
cmake .. -DNIGHTLY_BUILD=ON -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/3ds.cmake
make -j$(nproc)
```
*Note:* Add `-DHELLFIRE=ON` to build the Hellfire binaries.
The output-files will be generated in the build folder.
[Nintendo 3DS manual](docs/manual/platforms/n3ds.md)
</details>
<details><summary>Haiku</summary>
### Installing dependencies on 32 bit Haiku

Loading…
Cancel
Save