Skip to content

Instantly share code, notes, and snippets.

@Eiyeron
Created January 22, 2023 18:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Eiyeron/92aba96dfb87da3fd71092ffa4d23f90 to your computer and use it in GitHub Desktop.
Save Eiyeron/92aba96dfb87da3fd71092ffa4d23f90 to your computer and use it in GitHub Desktop.
PlayDate CMake template
cmake_minimum_required(VERSION 3.14)
set(CMAKE_C_STANDARD 11)
set(ENVSDK $ENV{PLAYDATE_SDK_PATH})
if (NOT ${ENVSDK} STREQUAL "")
# Convert path from Windows
file(TO_CMAKE_PATH ${ENVSDK} SDK)
else()
execute_process(
COMMAND bash -c "egrep '^\\s*SDKRoot' $HOME/.Playdate/config"
COMMAND head -n 1
COMMAND cut -c9-
OUTPUT_VARIABLE SDK
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()
if (NOT EXISTS ${SDK})
message(FATAL_ERROR "SDK Path not found; set ENV value PLAYDATE_SDK_PATH")
return()
endif()
set(CMAKE_CONFIGURATION_TYPES "Debug;Release")
# Compilation-time sprite generation
# If you don't have Aseprite in your Path, you can uncomment this line and hardcode your executable's path here.
# I don't know yet how to make configurable variables.
# set(ASEPRITE "C:/Program Files/Aseprite/Aseprite.exe")
find_program(ASEPRITE "aseprite")
if (NOT EXISTS ${ASEPRITE})
message(FATAL_ERROR "Aseprite not found. Please set in your PATH or configure it manually.")
return()
endif()
# The source folder is processed by the PlayDate SDK to create the assets in the .pdx folder.
# I usually keep my assets' "source files" into another folder.
# Those two paths are freely editable as long as you don't put them in the project's PDX folder.
set (ASSET_SOURCE "${CMAKE_SOURCE_DIR}/assets_source")
set (SPRITE_FOLDER "${CMAKE_SOURCE_DIR}/Source/img")
add_library(sprites INTERFACE)
# Create build step to convert an .aseprite file into one or multiple .PNGs.
function(add_sprites)
cmake_parse_arguments(
PARSE_ARGV 0
"ARGS"
"BITMAP_TABLE" # list of names of the boolean arguments (only defined ones will be true)
"IN_FILE;OUT_PATH" # list of names of mono-valued arguments
"LAYERS" # list of names of multi-valued arguments (output variables are lists)
)
if (ARGS_UNPARSED_ARGUMENTS)
message(ERROR "Remaining : ${ARGS_UNPARSED_ARGUMENTS}")
endif(ARGS_UNPARSED_ARGUMENTS)
if (NOT ARGS_IN_FILE)
message(FATAL_ERROR "Missing sprite input file")
endif(NOT ARGS_IN_FILE)
if (NOT ARGS_OUT_PATH)
message(FATAL_ERROR "Missing sprite output path")
endif(NOT ARGS_OUT_PATH)
if(ARGS_LAYERS)
list(TRANSFORM ARGS_LAYERS PREPEND "--layer=\"")
list(TRANSFORM ARGS_LAYERS APPEND "\"")
endif(ARGS_LAYERS)
if (ARGS_BITMAP_TABLE)
# Create JSON file and open up
file(RELATIVE_PATH local_path "${CMAKE_SOURCE_DIR}/Source" ${ARGS_OUT_PATH})
get_filename_component(json_path "${CMAKE_CURRENT_BINARY_DIR}/${local_path}.json" ABSOLUTE)
get_filename_component(json_dir "${json_path}" DIRECTORY)
make_directory(${json_dir})
execute_process(COMMAND "${ASEPRITE}" -b "${ARGS_IN_FILE}" "--data=${json_path}" --format=json)
file(READ ${json_path} sprite_data)
string(JSON sprite_num_frames LENGTH ${sprite_data} "frames")
# Append sprites to lists (global for dependency and local for rule)
foreach(i RANGE 1 ${sprite_num_frames})
list(APPEND sprite_frames "${ARGS_OUT_PATH}-${i}.png")
set(tiles "${tiles}" "${ARGS_OUT_PATH}-${i}.png" PARENT_SCOPE)
endforeach()
# Create command
add_custom_command(
OUTPUT ${sprite_frames}
COMMAND "${ASEPRITE}" -b "${ARGS_IN_FILE}" ${ARGS_LAYERS} --save-as="${ARGS_OUT_PATH}"-{frame1}.png
DEPENDS "${ARGS_IN_FILE}")
else()
set (single_sprites ${single_sprites} "${ARGS_OUT_PATH}.png" PARENT_SCOPE)
add_custom_command(
OUTPUT ${ARGS_OUT_PATH}.png
COMMAND "${ASEPRITE}" -b "${ARGS_IN_FILE}" ${ARGS_LAYERS} --save-as="${ARGS_OUT_PATH}".png
DEPENDS "${ARGS_IN_FILE}")
endif(ARGS_BITMAP_TABLE)
endfunction()
# Sample add_sprites example
add_sprites(BITMAP_TABLE
IN_FILE "${ASSET_SOURCE}/bitmap_table.aseprite"
OUT_PATH "${SPRITE_FOLDER}/my-filtered-sprite-as-a-table"
LAYERS "ALayer" "AnotherLayer"
)
add_sprites(
IN_FILE "${ASSET_SOURCE}/single_sprite.aseprite"
OUT_PATH "${SPRITE_FOLDER}/a-single-sprite-with-all-visible-layers")
add_sprites(
IN_FILE "${ASSET_SOURCE}/single_sprite.aseprite"
OUT_PATH "${SPRITE_FOLDER}/a-single-sprite-with-one-layer"
LAYERS "SomeLayer")
target_sources(sprites PRIVATE ${tiles} ${single_sprites})
# Game Name Customization
set(PLAYDATE_GAME_NAME <put_your_project_name_here>)
set(PLAYDATE_GAME_DEVICE <put_your_project_name_here>_DEVICE)
project(${PLAYDATE_GAME_NAME} C ASM)
set(PROJECT_SRC
<add_your_source_here>
)
if (TOOLCHAIN STREQUAL "armgcc")
# Coming from https://devforum.play.date/t/doom-on-playdate/852/27
# On Windows I have linking issues revolving around missing libc symbols.
# I hope this will fix the issue without breaking everything.
add_link_options(-specs=nano.specs -specs=nosys.specs)
add_executable(${PLAYDATE_GAME_DEVICE} ${SDK}/C_API/buildsupport/setup.c ${PROJECT_SRC})
add_dependencies(${PLAYDATE_GAME_DEVICE} sprites)
else()
add_library(${PLAYDATE_GAME_NAME} SHARED ${PROJECT_SRC})
add_dependencies(${PLAYDATE_GAME_NAME} sprites)
# I'm tired to hear about Spectre mitigation on a PlayDate DLL.
target_compile_options(${PLAYDATE_GAME_NAME} PRIVATE -Qspectre- -wd5045 -wd4820)
endif()
include(${SDK}/C_API/buildsupport/playdate_game.cmake)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment