changeset 116:0a6683615c73

cmake: change build system, continue #2487 @3h
author David Demelier <markand@malikania.fr>
date Sat, 03 Oct 2020 18:32:01 +0200
parents 3bd0d3a39e30
children 445035ace840
files .hgignore CMakeLists.txt Makefile assets/CMakeLists.txt cmake/FindJansson.cmake cmake/FindSDL2.cmake dist/package-mingw64.sh doxygen/CMakeLists.txt extern/libgreatest/CMakeLists.txt extern/libsqlite/CMakeLists.txt src/adventure/CMakeLists.txt src/adventure/main.c src/core/CMakeLists.txt src/core/theme.c src/molko/CMakeLists.txt src/molko/main.c tools/bcc/CMakeLists.txt tools/bcc/bcc.c tools/map/CMakeLists.txt tools/map/map.c tools/molko-bcc.c tools/molko-map.c
diffstat 22 files changed, 1194 insertions(+), 1030 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Sun Jul 12 09:44:27 2020 +0200
+++ b/.hgignore	Sat Oct 03 18:32:01 2020 +0200
@@ -7,28 +7,3 @@
 
 # macOS specific.
 \.DS_Store$
-
-# object files.
-\.d$
-\.o$
-\.a$
-^assets/.*\.h$
-^examples/example-inventory(\.exe)?$
-^examples/example-message(\.exe)?$
-^examples/example-sound(\.exe)?$
-^examples/assets/.*\.h$
-^molko(\.exe)?$
-^tests/test-color(\.exe)?$
-^tests/test-error(\.exe)?$
-^tests/test-inventory(\.exe)?$
-^tests/test-map(\.exe)?$
-^tests/test-panic(\.exe)?$
-^tests/test-save(\.exe)?$
-^tests/test-script(\.exe)?$
-^tools/molko-bcc(\.exe)?$
-^tools/molko-map(\.exe)?$
-
-# doxygen stuff.
-^doxygen/html$
-^doxygen/man$
-^doxygen/doxygen_sqlite3\.db$
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CMakeLists.txt	Sat Oct 03 18:32:01 2020 +0200
@@ -0,0 +1,44 @@
+#
+# CMakeLists.txt -- CMake build system for molko
+#
+# Copyright (c) 2020 David Demelier <markand@malikania.fr>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+cmake_minimum_required(VERSION 3.18)
+project(molko)
+
+include(GNUInstallDirs)
+
+set(CMAKE_C_STANDARD 11)
+set(CMAKE_C_STANDARD_REQUIRED On)
+set(CMAKE_C_EXTENSIONS Off)
+set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
+
+find_package(Jansson REQUIRED)
+find_package(SDL2 REQUIRED COMPONENTS image mixer ttf)
+
+add_subdirectory(extern/libsqlite)
+add_subdirectory(extern/libgreatest)
+
+add_subdirectory(doxygen)
+
+add_subdirectory(tools/bcc)
+add_subdirectory(tools/map)
+
+add_subdirectory(assets)
+
+add_subdirectory(src/core)
+add_subdirectory(src/adventure)
+add_subdirectory(src/molko)
--- a/Makefile	Sun Jul 12 09:44:27 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,271 +0,0 @@
-#
-# Makefile -- basic Makefile for Molko's Adventure
-#
-# Copyright (c) 2020 David Demelier <markand@malikania.fr>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-.POSIX:
-
-#
-# User options begin here.
-# -------------------------------------------------------------------
-#
-# CC:           C compiler
-# AR:           Archiver
-# CFLAGS:       General C flags
-# LDFLAGS:      General linker flags
-#
-# PREFIX:       Installation prefix
-# BINDIR:       Where to install binaries
-# SHAREDIR:     Where to install resources
-#
-
-CC=             cc
-AR=             ar
-CFLAGS=         -O0 -std=c11 -g
-
-PREFIX=         /usr/local
-BINDIR=         ${PREFIX}/bin
-SHAREDIR=       ${PREFIX}/share
-
-# End of user options.
-
-SQLITE_SRC=     extern/libsqlite/sqlite3.c
-SQLITE_OBJ=     extern/libsqlite/sqlite3.o
-SQLITE_LIB=     extern/libsqlite/libsqlite3.a
-SQLITE_FLAGS=   -DSQLITE_THREADSAFE=0 \
-                -DSQLITE_OMIT_LOAD_EXTENSION \
-                -DSQLITE_OMIT_DEPRECATED \
-                -DSQLITE_DEFAULT_FOREIGN_KEYS=1
-
-CORE_SRCS=      src/core/animation.c                    \
-                src/core/button.c                       \
-                src/core/checkbox.c                     \
-                src/core/clock.c                        \
-                src/core/debug.c                        \
-                src/core/error.c                        \
-                src/core/event.c                        \
-                src/core/font.c                         \
-                src/core/frame.c                        \
-                src/core/game.c                         \
-                src/core/image.c                        \
-                src/core/inhibit.c                      \
-                src/core/inventory.c                    \
-                src/core/inventory_dialog.c             \
-                src/core/label.c                        \
-                src/core/map.c                          \
-                src/core/map_state.c                    \
-                src/core/maths.c                        \
-                src/core/message.c                      \
-                src/core/painter.c                      \
-                src/core/panic.c                        \
-                src/core/save.c                         \
-                src/core/script.c                       \
-                src/core/sound.c                        \
-                src/core/sprite.c                       \
-                src/core/sys.c                          \
-                src/core/texture.c                      \
-                src/core/theme.c                        \
-                src/core/util.c                         \
-                src/core/walksprite.c                   \
-                src/core/wait.c                         \
-                src/core/window.c
-CORE_OBJS=      ${CORE_SRCS:.c=.o}
-CORE_DEPS=      ${CORE_SRCS:.c=.d}
-CORE_ASTS=      assets/fonts/ComicNeue-Regular.h
-
-ADV_SRCS=       src/adventure/main.c                    \
-                src/adventure/panic_state.c             \
-                src/adventure/splashscreen_state.c      \
-                src/adventure/mainmenu_state.c
-ADV_OBJS=       ${ADV_SRCS:.c=.o}
-ADV_DEPS=       ${ADV_SRCS:.c=.d}
-
-SDL_CFLAGS=     `pkg-config --cflags sdl2 SDL2_image SDL2_mixer SDL2_ttf`
-SDL_LDFLAGS=    `pkg-config --libs sdl2 SDL2_image SDL2_mixer SDL2_ttf`
-
-JANSSON_CFLAGS= `pkg-config --cflags jansson`
-JANSSON_LDFLAGS=`pkg-config --libs jansson`
-
-EXAMPLES=       examples/example-message.c              \
-                examples/example-inventory.c            \
-                examples/example-sound.c
-EXAMPLES_PRGS=  ${EXAMPLES:.c=}
-EXAMPLES_OBJS=  ${EXAMPLES:.c=.o}
-EXAMPLES_DEPS=  ${EXAMPLES:.c=.d}
-EXAMPLES_ASTS=  examples/assets/sounds/vabsounds-romance.h \
-                examples/assets/images/fish.h \
-                examples/assets/images/potion.h \
-                examples/assets/images/sword.h
-
-TESTS=          tests/test-color.c                      \
-                tests/test-error.c                      \
-                tests/test-inventory.c                  \
-                tests/test-map.c                        \
-                tests/test-panic.c                      \
-                tests/test-save.c                       \
-                tests/test-script.c
-TESTS_INCS=     -I extern/libgreatest -I src/core ${SDL_CFLAGS}
-TESTS_PRGS=     ${TESTS:.c=}
-TESTS_OBJS=     ${TESTS:.c=.o}
-TESTS_DEPS=     ${TESTS:.c=.d}
-
-TOOLS=          tools/molko-map.c                       \
-                tools/molko-bcc.c
-TOOLS_PRGS=     ${TOOLS:.c=}
-TOOLS_DEPS=     ${TOOLS:.c=.d}
-
-MY_CFLAGS=      -D_XOPEN_SOURCE=700 \
-                -DPREFIX=\""${PREFIX}"\" \
-                -DBINDIR=\""${BINDIR}"\" \
-                -DSHAREDIR=\""${SHAREDIR}"\" \
-                -I. \
-                -Iextern/libsqlite \
-                -Iextern/libgreatest \
-                -Isrc/core \
-                -Isrc/adventure
-MY_LDFLAGS=     -lm
-
-.SUFFIXES:
-.SUFFIXES: .o .c .h .ogg .png .ttf
-
-all: molko
-
--include ${CORE_DEPS} ${ADV_DEPS} ${TESTS_DEPS} ${TOOLS_DEPS}
-
-.c.o:
-	${CC} ${MY_CFLAGS} ${SDL_CFLAGS} ${CFLAGS} -MMD -c $< -o $@
-
-.c:
-	${CC} ${MY_CFLAGS} -o $@ ${CFLAGS} $< libmolko.a ${SQLITE_LIB} ${SDL_LDFLAGS} ${MY_LDFLAGS} ${LDFLAGS}
-
-.o:
-	${CC} -o $@ $< libmolko.a ${SQLITE_LIB} ${SDL_LDFLAGS} ${MY_LDFLAGS} ${LDFLAGS}
-
-.ogg.h .png.h .ttf.h:
-	tools/molko-bcc -s $< ${<F} > $@
-
-# {{{ Core
-
-${CORE_OBJS}: tools/molko-bcc ${CORE_ASTS}
-
-${SQLITE_OBJ}: ${SQLITE_SRC}
-	${CC} ${CFLAGS} ${SQLITE_FLAGS} -c ${SQLITE_SRC} -o $@
-
-${SQLITE_LIB}: ${SQLITE_OBJ}
-	${AR} -rc $@ ${SQLITE_OBJ}
-
-libmolko.a: ${CORE_OBJS} ${SQLITE_LIB}
-	${AR} -rc $@ ${CORE_OBJS}
-
-# }}}
-
-# {{{ Molko's Adventure
-
-molko: libmolko.a ${ADV_OBJS}
-	${CC} -o $@ ${ADV_OBJS} libmolko.a ${SQLITE_LIB} ${SDL_LDFLAGS} ${MY_LDFLAGS} ${LDFLAGS}
-
-# }}}
-
-# {{{ Examples
-
-${EXAMPLES_OBJS}: libmolko.a ${EXAMPLES_ASTS}
-
-examples: ${EXAMPLES_PRGS}
-
-# }}}
-
-# {{{ Tests
-
-${TESTS_OBJS}: libmolko.a
-
-tests: ${TESTS_PRGS}
-	for t in ${TESTS_PRGS}; do ./$$t; done
-
-# }}}
-
-# {{{ Tools
-
-tools: ${TOOLS_PRGS}
-
-# Custom rule: does not depend on anything else than jansson.
-tools/molko-map: tools/molko-map.c
-	${CC} ${MY_CFLAGS} -o $@ tools/molko-map.c ${CFLAGS} ${JANSSON_CFLAGS} ${JANSSON_LDFLAGS} ${LDFLAGS}
-
-# Custom rule: does not depend on anything.
-tools/molko-bcc: tools/molko-bcc.c
-	${CC} ${MY_CFLAGS} -o $@ tools/molko-bcc.c ${LDFLAGS}
-
-# }}}
-
-# {{{ Docs
-
-doxygen:
-	doxygen doxygen/Doxyfile
-
-# }}}
-
-# {{{ Misc
-
-everything: molko ${EXAMPLES_PRGS} ${TOOLS_PRGS} ${TESTS_PRGS}
-
-install:
-	mkdir -p ${DESTDIR}${BINDIR}
-	cp molko ${DESTDIR}${BINDIR}
-	chmod 755 ${DESTDIR}${BINDIR}/molko
-	mkdir -p ${DESTDIR}${SHAREDIR}/molko
-	cp -R assets/* ${DESTDIR}${SHAREDIR}/molko
-
-clean-core:
-	rm -f ${SQLITE_OBJ} ${SQLITE_LIB}
-	rm -f libmolko.a
-	rm -f ${CORE_OBJS} ${CORE_DEPS} ${CORE_ASTS}
-
-clean-doxygen:
-	rm -rf doxygen/html doxygen/man
-
-clean-examples:
-	rm -f ${EXAMPLES_PRGS} ${EXAMPLES_OBJS} ${EXAMPLES_DEPS} ${EXAMPLES_ASTS}
-
-clean-molko:
-	rm -f molko ${ADV_OBJS} ${ADV_DEPS}
-
-clean-tests:
-	rm -f ${TESTS_PRGS} ${TESTS_OBJS} ${TESTS_DEPS}
-
-clean-tools:
-	rm -f ${TOOLS_PRGS} ${TOOLS_DEPS}
-
-clean: clean-core \
-       clean-doxygen \
-       clean-examples \
-       clean-molko \
-       clean-tests \
-       clean-tools
-
-# }}}
-
-.PHONY: all \
-        clean-core \
-        clean-doxygen \
-        clean-examples \
-        clean-molko \
-        clean-tests \
-        clean-tools \
-        doxygen \
-        everything \
-        examples \
-        tests \
-        tools
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/assets/CMakeLists.txt	Sat Oct 03 18:32:01 2020 +0200
@@ -0,0 +1,83 @@
+#
+# CMakeLists.txt -- CMake build system for assets
+#
+# Copyright (c) 2020 David Demelier <markand@malikania.fr>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+project(libassets)
+
+set(
+	FONTS
+	ComicNeue-Regular.ttf
+	DejaVuSans.ttf
+	DejaVuSansCondensed.ttf
+	Lato-Regular.ttf
+	knights-quest.ttf
+	pirata-one.ttf
+	teutonic1.ttf
+)
+
+set(
+	IMAGES
+	message.png
+)
+
+set(
+	MAPS
+	test.map
+)
+
+set(
+	SPRITES
+	test-walk.png
+)
+
+set(
+	TILESETS
+	test.png 
+)
+
+macro (gen basedir list)
+	file(MAKE_DIRECTORY ${libassets_BINARY_DIR}/assets/${basedir})
+
+	foreach (i ${list})
+		get_filename_component(basename ${i} NAME_WE)
+
+		set(input ${libassets_SOURCE_DIR}/${basedir}/${i})
+		set(output ${libassets_BINARY_DIR}/assets/${basedir}/${basename}.h)
+
+		add_custom_command(
+			OUTPUT ${output}
+			COMMAND $<TARGET_FILE:bcc> -s ${input} ${basename} > ${output}
+			DEPENDS $<TARGET_FILE:bcc>
+		)
+
+		list(APPEND OUTPUTS ${output})
+	endforeach ()
+endmacro ()
+
+gen(fonts "${FONTS}")
+gen(images "${IMAGES}")
+gen(maps "${MAPS}")
+gen(sprites "${SPRITES}")
+gen(tilesets "${TILESETS}")
+
+add_library(libassets OBJECT ${OUTPUTS})
+target_include_directories(
+	libassets
+	PUBLIC
+		$<BUILD_INTERFACE:${libassets_BINARY_DIR}>
+)
+set_target_properties(libassets PROPERTIES LINKER_LANGUAGE "C")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake/FindJansson.cmake	Sat Oct 03 18:32:01 2020 +0200
@@ -0,0 +1,42 @@
+# FindJansson
+# -----------
+#
+# Find Jansson library, this modules defines:
+#
+# Jansson_INCLUDE_DIRS, where to find jansson.h
+# Jansson_LIBRARIES, where to find library
+# Jansson_FOUND, if it is found
+#
+# The following imported targets will be available:
+#
+# Jansson::Jansson, if found.
+#
+
+find_path(Jansson_INCLUDE_DIR NAMES jansson.h)
+find_library(Jansson_LIBRARY NAMES libjansson jansson)
+
+include(FindPackageHandleStandardArgs)
+
+find_package_handle_standard_args(
+	Jansson
+	FOUND_VAR Jansson_FOUND
+	REQUIRED_VARS Jansson_LIBRARY Jansson_INCLUDE_DIR
+)
+
+if (Jansson_FOUND)
+	set(Jansson_LIBRARIES ${Jansson_LIBRARY})
+	set(Jansson_INCLUDE_DIRS ${Jansson_INCLUDE_DIR})
+
+	if (NOT TARGET Jansson::Jansson)
+		add_library(Jansson::Jansson UNKNOWN IMPORTED)
+		set_target_properties(
+			Jansson::Jansson
+			PROPERTIES
+				IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+				IMPORTED_LOCATION "${Jansson_LIBRARY}"
+				INTERFACE_INCLUDE_DIRECTORIES "${Jansson_INCLUDE_DIRS}"
+		)
+	endif ()
+endif ()
+
+mark_as_advanced(Jansson_INCLUDE_DIR Jansson_LIBRARY)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake/FindSDL2.cmake	Sat Oct 03 18:32:01 2020 +0200
@@ -0,0 +1,101 @@
+# FindSDL2
+# --------
+#
+# Find SDL2 library and components, this modules defines:
+#
+#  SDL2_LIBRARY, the name of the library to link against.
+#  SDL2_MAIN_LIBRARY, for SDL2main (if present).
+#  SDL2_LIBRARIES, alias to SDL2_LIBRARY.
+#  SDL2_FOUND, true if found.
+#  SDL2_INCLUDE_DIR, where to find SDL.h.
+#
+# The following imported targets will be defined:
+#
+# SDL2::SDL2
+# SDL2::SDL2main (if present)
+#
+# This module also handle the following official SDL addons:
+#
+# - image
+# - mixer
+# - net
+# - ttf
+#
+# And thus, variables SDL2_<C>_LIBRARY, SDL2_<C>_INCLUDE_DIRS and SDL2::<C>
+# imported targets will be defined if they are found.
+#
+
+include(FindPackageHandleStandardArgs)
+
+# The official include convention is <SDL.h> not <SDL/SDL.h>.
+find_path(
+	SDL2_INCLUDE_DIR
+	NAMES SDL.h
+	PATH_SUFFIXES include/SDL2 include
+)
+
+find_library(SDL2_LIBRARY NAMES SDL2 libSDL2)
+find_library(SDL2_MAIN_LIBRARY NAMES SDL2main libSDL2main)
+
+# Standard components.
+foreach (c ${SDL2_FIND_COMPONENTS})
+	find_path(
+		SDL2_${c}_INCLUDE_DIR
+		NAMES SDL.h
+		PATH_SUFFIXES include/SDL2 include
+	)
+
+	find_library(
+		SDL2_${c}_LIBRARY
+		NAMES SDL2_${c} libSDL2_${c}
+	)
+
+	if (NOT TARGET SDL2::${c} AND SDL2_${c}_LIBRARY)
+		set(SDL2_${c}_FOUND TRUE)
+		add_library(SDL2::${c} UNKNOWN IMPORTED)
+		set_target_properties(
+			SDL2::${c}
+			PROPERTIES
+				IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+				IMPORTED_LOCATION "${SDL2_${c}_LIBRARY}"
+				INTERFACE_INCLUDE_DIRECTORIES "${SDL2_${c}_INCLUDE_DIRS}"
+		)
+	endif ()
+
+	mark_as_advanced(SDL2_${c}_INCLUDE_DIR SDL2_${c}_LIBRARY)
+endforeach ()
+
+find_package_handle_standard_args(
+	SDL2
+	REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR
+	HANDLE_COMPONENTS
+)
+
+if (SDL2_FOUND)
+	set(SDL2_LIBRARIES ${SDL2_LIBRARY})
+	set(SDL2_INCLUDE_DIRS ${SDL2_INCLUDE_DIR})
+
+	if (NOT TARGET SDL2::SDL2)
+		add_library(SDL2::SDL2 UNKNOWN IMPORTED)
+		set_target_properties(
+			SDL2::SDL2
+			PROPERTIES
+				IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+				IMPORTED_LOCATION "${SDL2_LIBRARY}"
+				INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIRS}"
+		)
+	endif ()
+
+	if (NOT TARGET SDL2::main AND SDL2_MAIN_LIBRARY)
+		add_library(SDL2::main UNKNOWN IMPORTED)
+		set_target_properties(
+			SDL2::main
+			PROPERTIES
+				IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+				IMPORTED_LOCATION "${SDL2_MAIN_LIBRARY}"
+				INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIRS}"
+		)
+	endif ()
+endif ()
+
+mark_as_advanced(SDL2_INCLUDE_DIR SDL2_LIBRARY)
--- a/dist/package-mingw64.sh	Sun Jul 12 09:44:27 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-#!/bin/sh
-#
-# package-mingw64.sh -- create fakeroot directory for MinGW-w64
-#
-# Copyright (c) 2020 David Demelier <markand@malikania.fr>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-verbose=0
-
-die()
-{
-	echo "$1" 1>&2
-	exit 1
-}
-
-info()
-{
-	if [ $verbose -eq 1 ]; then
-		echo $1
-	fi
-}
-
-depends()
-{
-	ldd molko.exe | grep -E "/mingw" | awk '{ print $3 }'
-}
-
-usage()
-{
-	echo "Create a directory suitable for packaging." 1>&2
-	echo "" 1>&2
-	echo "usage: $(basename $0) [-v] output-directory" 1>&2
-	exit 1
-}
-
-if [ ! -f Makefile ]; then
-	die "abort: must be ran from top directory"
-fi
-
-if [ ! -f molko.exe ]; then
-	die "abort: no molko.exe binary found, did you build?"
-fi
-
-while getopts "v" opt; do
-	case $opt in
-	v)
-		verbose=1
-		;;
-	*)
-		usage
-		;;
-	esac
-done
-
-shift $((OPTIND - 1))
-
-if [ $# -eq 0 ] || [ -z $1 ]; then
-	usage
-fi
-
-output=${1:-package}
-
-info "Creating package in $output"
-
-rm -rf "$output"
-mkdir -p "$output"
-
-info "Copying molko.exe"
-cp molko.exe "$output"
-
-info "Copying assets"
-cp -R assets "$output"
-
-depends | while read -r file; do
-	info "Copying dependency $file"
-	cp -f "$file" "$output"
-done
-
-info "Molko's Adventure is ready in $output"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doxygen/CMakeLists.txt	Sat Oct 03 18:32:01 2020 +0200
@@ -0,0 +1,60 @@
+#
+# CMakeLists.txt -- CMake build system for doxygen
+#
+# Copyright (c) 2020 David Demelier <markand@malikania.fr>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+project(doxygen)
+
+find_package(Doxygen QUIET)
+
+if (DOXYGEN_FOUND)
+	set(
+		INPUT
+		doxygen/groups.c
+		doxygen/mainpage.c
+		doxygen/page-howto-initialization.c
+		doxygen/page-faq.c
+		doxygen/page-examples.c
+		src
+	)
+	set(DOXYGEN_ALLOW_UNICODE_NAMES YES)
+	set(DOXYGEN_AUTOLINK_SUPPORT NO)
+	set(DOXYGEN_ENABLE_PREPROCESSING YES)
+	set(DOXYGEN_EXAMPLE_PATH examples)
+	set(DOXYGEN_EXCLUDE_PATTERNS *_p.h)
+	set(DOXYGEN_FILE_PATTERNS *.h)
+	set(DOXYGEN_GENERATE_LATEX NO)
+	set(DOXYGEN_GENERATE_MAN YES)
+	set(DOXYGEN_INPUT_ENCODING UTF-8)
+	set(DOXYGEN_MAX_INITIALIZER_LINES 0)
+	set(DOXYGEN_OPTIMIZE_OUTPUT_FOR_C YES)
+	set(DOXYGEN_OUTPUT_DIRECTORY doxygen)
+	set(DOXYGEN_PREDEFINED DOXYGEN)
+	set(DOXYGEN_PROJECT_BRIEF "2D RPG game in C")
+	set(DOXYGEN_PROJECT_NAME "Molko's Adventure")
+	set(DOXYGEN_QUIET YES)
+	set(DOXYGEN_RECURSIVE YES)
+	set(DOXYGEN_STRIP_FROM_PATH src)
+	set(DOXYGEN_TAB_SIZE 8)
+	set(DOXYGEN_WARNINGS YES)
+
+	doxygen_add_docs(
+		doxygen
+		${INPUT}
+		ALL
+		WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
+	)
+endif ()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extern/libgreatest/CMakeLists.txt	Sat Oct 03 18:32:01 2020 +0200
@@ -0,0 +1,27 @@
+#
+# CMakeLists.txt -- CMake build system for libgreatest
+#
+# Copyright (c) 2020 David Demelier <markand@malikania.fr>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+project(libgreatest)
+add_library(libgreatest INTERFACE)
+target_sources(libgreatest INTERFACE greatest.h)
+target_include_directories(
+	libgreatest
+	INTERFACE
+		$<BUILD_INTERFACE:${libgreatest_SOURCE_DIR}>
+		$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extern/libsqlite/CMakeLists.txt	Sat Oct 03 18:32:01 2020 +0200
@@ -0,0 +1,27 @@
+#
+# CMakeLists.txt -- CMake build system for libsqlite
+#
+# Copyright (c) 2020 David Demelier <markand@malikania.fr>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+project(libsqlite)
+add_library(libsqlite sqlite3.c sqlite3.h)
+target_include_directories(
+	libsqlite
+	PUBLIC
+		$<BUILD_INTERFACE:${libsqlite_SOURCE_DIR}>
+		$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
+set_target_properties(libsqlite PROPERTIES PREFIX "")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/adventure/CMakeLists.txt	Sat Oct 03 18:32:01 2020 +0200
@@ -0,0 +1,37 @@
+#
+# CMakeLists.txt -- CMake build system for libadventure
+#
+# Copyright (c) 2020 David Demelier <markand@malikania.fr>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+project(libadventure)
+
+set(
+	SOURCES
+	${libadventure_SOURCE_DIR}/mainmenu_state.c 
+	${libadventure_SOURCE_DIR}/mainmenu_state.h 
+	${libadventure_SOURCE_DIR}/panic_state.c 
+	${libadventure_SOURCE_DIR}/panic_state.h 
+	${libadventure_SOURCE_DIR}/splashscreen_state.c 
+	${libadventure_SOURCE_DIR}/splashscreen_state.h 
+)
+
+add_library(libadventure ${SOURCES})
+target_link_libraries(libadventure libcore)
+target_include_directories(
+	libadventure
+	PUBLIC
+		$<BUILD_INTERFACE:${libadventure_SOURCE_DIR}>
+)
--- a/src/adventure/main.c	Sun Jul 12 09:44:27 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +0,0 @@
-/*
- * main.c -- Molko's Adventure
- *
- * Copyright (c) 2020 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdnoreturn.h>
-#include <string.h>
-
-#include "button.h"
-#include "checkbox.h"
-#include "clock.h"
-#include "debug.h"
-#include "error.h"
-#include "event.h"
-#include "font.h"
-#include "frame.h"
-#include "game.h"
-#include "image.h"
-#include "inhibit.h"
-#include "label.h"
-#include "label.h"
-#include "map.h"
-#include "map_state.h"
-#include "message.h"
-#include "painter.h"
-#include "panic.h"
-#include "panic_state.h"
-#include "script.h"
-#include "splashscreen_state.h"
-#include "sprite.h"
-#include "sys.h"
-#include "theme.h"
-#include "util.h"
-#include "wait.h"
-#include "window.h"
-
-#define WINDOW_WIDTH 1280
-#define WINDOW_HEIGHT 720
-
-static jmp_buf panic_buf;
-static struct font debug_font;
-
-static noreturn void
-unrecoverable(void)
-{
-	longjmp(panic_buf, 1);
-}
-
-static void
-init(void)
-{
-	if (!sys_init())
-		panic();
-	if (!window_init("Molko's Adventure", WINDOW_WIDTH, WINDOW_HEIGHT))
-		panic();
-	if (!theme_init())
-		panic();
-
-	/* Init unrecoverable panic state. */
-	panic_state_init();
-	panic_handler = unrecoverable;
-
-	/* Default state is splash screen */
-	game_switch(&splashscreen_state, true);
-}
-
-static void
-run(void)
-{
-	struct clock clock = { 0 };
-	struct frame mainmenu = {
-		.x = 10,
-		.y = 10,
-		.w = 200,
-		.h = 64
-	};
-	struct checkbox cb = {
-		.label = "Play hard mode",
-		.x = 20,
-		.y = 20,
-		.w = 200,
-		.h = 16
-	};
-
-	for (;;) {
-		unsigned int elapsed = clock_elapsed(&clock);
-
-		clock_start(&clock);
-
-		for (union event ev; event_poll(&ev); ) {
-			switch (ev.type) {
-			case EVENT_QUIT:
-				return;
-			default:
-				checkbox_handle(&cb, &ev);
-				break;
-			}
-		}
-
-		painter_set_color(0xffffffff);
-		painter_clear();
-
-		theme_draw_frame(NULL, &(const struct frame){ .x=10, .y=10, .w=500, .h=500 });
-		checkbox_draw(&cb);
-
-		painter_present();
-
-		if ((elapsed = clock_elapsed(&clock)) < 20)
-			delay(20 - elapsed);
-	}
-#if 0
-	union event ev;
-	struct clock clock;
-	struct font font;
-	struct texture frame;
-	int panic_trigger = 0;
-
-	if (!(font_open(&font, sys_datapath("fonts/DejaVuSans.ttf"), 15)))
-		panic();
-	if (!(font_open(&debug_font, sys_datapath("fonts/DejaVuSans.ttf"), 10)))
-		panic();
-	if (!(image_open(&frame, sys_datapath("images/message.png"))))
-		panic();
-
-	debug_options.default_font = &debug_font;
-	debug_options.enable = true;
-
-	clock_start(&clock);
-
-	while (game.state) {
-		unsigned int elapsed = clock_elapsed(&clock);
-
-		clock_start(&clock);
-
-		while (event_poll(&ev)) {
-			/* TODO: this must be handled by states. */
-			if (ev.type == EVENT_QUIT)
-				return;
-
-			/*
-			 * TODO: user panic request.
-			 */
-			if (game.state != &panic_state &&
-			    ev.type == EVENT_KEYDOWN &&
-			    ev.key.key == KEY_F12) {
-				if (++panic_trigger == 3)
-					panicf("User panic request.");
-			}
-
-			game_handle(&ev);
-		}
-
-		painter_set_color(0xffffffff);
-		painter_clear();
-
-		game_update(elapsed);
-		game_draw();
-
-		if ((elapsed = clock_elapsed(&clock)) < 20)
-			delay(20 - elapsed);
-	}
-#endif
-}
-
-static void
-close(void)
-{
-	window_finish();
-	sys_finish();
-}
-
-int
-main(int argc, char **argv)
-{
-	(void)argc;
-	(void)argv;
-
-	init();
-
-	if (setjmp(panic_buf) == 0)
-		/* Initial game run. */
-		run();
-	else {
-		/* Clear event queue to avoid accidental key presses. */
-		for (union event ev; event_poll(&ev); )
-			continue;
-
-		game_switch(&panic_state, true);
-		run();
-	}
-
-	close();
-
-	return 0;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/CMakeLists.txt	Sat Oct 03 18:32:01 2020 +0200
@@ -0,0 +1,121 @@
+#
+# CMakeLists.txt -- CMake build system for libcore
+#
+# Copyright (c) 2020 David Demelier <markand@malikania.fr>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+project(libcore)
+
+set(
+	SOURCES
+	${libcore_SOURCE_DIR}/action.h
+	${libcore_SOURCE_DIR}/animation.c
+	${libcore_SOURCE_DIR}/animation.h
+	${libcore_SOURCE_DIR}/button.c
+	${libcore_SOURCE_DIR}/button.h
+	${libcore_SOURCE_DIR}/checkbox.c
+	${libcore_SOURCE_DIR}/checkbox.h
+	${libcore_SOURCE_DIR}/clock.c
+	${libcore_SOURCE_DIR}/clock.h
+	${libcore_SOURCE_DIR}/color.h
+	${libcore_SOURCE_DIR}/debug.c
+	${libcore_SOURCE_DIR}/debug.h
+	${libcore_SOURCE_DIR}/error.c
+	${libcore_SOURCE_DIR}/error.h
+	${libcore_SOURCE_DIR}/error_p.h
+	${libcore_SOURCE_DIR}/event.c
+	${libcore_SOURCE_DIR}/event.h
+	${libcore_SOURCE_DIR}/font.c
+	${libcore_SOURCE_DIR}/font.h
+	${libcore_SOURCE_DIR}/frame.c
+	${libcore_SOURCE_DIR}/frame.h
+	${libcore_SOURCE_DIR}/game.c
+	${libcore_SOURCE_DIR}/game.h
+	${libcore_SOURCE_DIR}/image.c
+	${libcore_SOURCE_DIR}/image.h
+	${libcore_SOURCE_DIR}/inhibit.c
+	${libcore_SOURCE_DIR}/inhibit.h
+	${libcore_SOURCE_DIR}/inventory.c
+	${libcore_SOURCE_DIR}/inventory.h
+	${libcore_SOURCE_DIR}/inventory_dialog.c
+	${libcore_SOURCE_DIR}/inventory_dialog.h
+	${libcore_SOURCE_DIR}/item.h
+	${libcore_SOURCE_DIR}/key.h
+	${libcore_SOURCE_DIR}/label.c
+	${libcore_SOURCE_DIR}/label.h
+	${libcore_SOURCE_DIR}/map.c
+	${libcore_SOURCE_DIR}/map.h
+	${libcore_SOURCE_DIR}/map_state.c
+	${libcore_SOURCE_DIR}/map_state.h
+	${libcore_SOURCE_DIR}/maths.c
+	${libcore_SOURCE_DIR}/maths.h
+	${libcore_SOURCE_DIR}/message.c
+	${libcore_SOURCE_DIR}/message.h
+	${libcore_SOURCE_DIR}/mouse.h
+	${libcore_SOURCE_DIR}/painter.c
+	${libcore_SOURCE_DIR}/painter.h
+	${libcore_SOURCE_DIR}/panic.c
+	${libcore_SOURCE_DIR}/panic.h
+	${libcore_SOURCE_DIR}/plat.h
+	${libcore_SOURCE_DIR}/save.c
+	${libcore_SOURCE_DIR}/save.h
+	${libcore_SOURCE_DIR}/script.c
+	${libcore_SOURCE_DIR}/script.h
+	${libcore_SOURCE_DIR}/sound.c
+	${libcore_SOURCE_DIR}/sound.h
+	${libcore_SOURCE_DIR}/sprite.c
+	${libcore_SOURCE_DIR}/sprite.h
+	${libcore_SOURCE_DIR}/state.h
+	${libcore_SOURCE_DIR}/sys.c
+	${libcore_SOURCE_DIR}/sys.h
+	${libcore_SOURCE_DIR}/texture.c
+	${libcore_SOURCE_DIR}/texture.h
+	${libcore_SOURCE_DIR}/texture_p.h
+	${libcore_SOURCE_DIR}/theme.c
+	${libcore_SOURCE_DIR}/theme.h
+	${libcore_SOURCE_DIR}/util.c
+	${libcore_SOURCE_DIR}/util.h
+	${libcore_SOURCE_DIR}/wait.c
+	${libcore_SOURCE_DIR}/wait.h
+	${libcore_SOURCE_DIR}/walksprite.c
+	${libcore_SOURCE_DIR}/walksprite.h
+	${libcore_SOURCE_DIR}/window.c
+	${libcore_SOURCE_DIR}/window.h
+	${libcore_SOURCE_DIR}/window_p.h
+)
+
+add_library(libcore ${SOURCES})
+target_link_libraries(
+	libcore
+	libassets
+	SDL2::SDL2
+	SDL2::image
+	SDL2::mixer
+	SDL2::ttf
+)
+target_compile_definitions(
+	libcore
+	PRIVATE
+		BINDIR="${CMAKE_INSTALL_BINDIR}"
+		PREFIX="${CMAKE_INSTALL_PREFIX}"
+		SHAREDIR="${CMAKE_INSTALL_DATADIR}"
+	PUBLIC
+		_XOPEN_SOURCE=700
+)
+target_include_directories(
+	libcore
+	PUBLIC
+		$<BUILD_INTERFACE:${libcore_SOURCE_DIR}>
+)
--- a/src/core/theme.c	Sun Jul 12 09:44:27 2020 +0200
+++ b/src/core/theme.c	Sat Oct 03 18:32:01 2020 +0200
@@ -53,7 +53,6 @@
 	painter_draw_line(x + w, y, x + w, y + h);
 }
 
-
 static void
 draw_frame(struct theme *t, const struct frame *frame)
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/molko/CMakeLists.txt	Sat Oct 03 18:32:01 2020 +0200
@@ -0,0 +1,21 @@
+#
+# CMakeLists.txt -- CMake build system for molko
+#
+# Copyright (c) 2020 David Demelier <markand@malikania.fr>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+project(molko)
+add_executable(molko main.c)
+target_link_libraries(molko libadventure)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/molko/main.c	Sat Oct 03 18:32:01 2020 +0200
@@ -0,0 +1,159 @@
+/*
+ * main.c -- Molko's Adventure
+ *
+ * Copyright (c) 2020 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdnoreturn.h>
+#include <string.h>
+
+#include <button.h>
+#include <checkbox.h>
+#include <clock.h>
+#include <debug.h>
+#include <error.h>
+#include <event.h>
+#include <font.h>
+#include <frame.h>
+#include <game.h>
+#include <image.h>
+#include <inhibit.h>
+#include <label.h>
+#include <label.h>
+#include <map.h>
+#include <map_state.h>
+#include <message.h>
+#include <painter.h>
+#include <panic.h>
+#include <panic_state.h>
+#include <script.h>
+#include <splashscreen_state.h>
+#include <sprite.h>
+#include <sys.h>
+#include <theme.h>
+#include <util.h>
+#include <wait.h>
+#include <window.h>
+
+#define WINDOW_WIDTH 1280
+#define WINDOW_HEIGHT 720
+
+static jmp_buf panic_buf;
+static struct font debug_font;
+
+static noreturn void
+unrecoverable(void)
+{
+	longjmp(panic_buf, 1);
+}
+
+static void
+init(void)
+{
+	if (!sys_init())
+		panic();
+	if (!window_init("Molko's Adventure", WINDOW_WIDTH, WINDOW_HEIGHT))
+		panic();
+	if (!theme_init())
+		panic();
+
+	/* Init unrecoverable panic state. */
+	panic_state_init();
+	panic_handler = unrecoverable;
+
+	/* Default state is splash screen */
+	game_switch(&splashscreen_state, true);
+}
+
+static void
+run(void)
+{
+	struct clock clock = { 0 };
+	struct frame mainmenu = {
+		.x = 10,
+		.y = 10,
+		.w = 200,
+		.h = 64
+	};
+	struct checkbox cb = {
+		.label = "Play hard mode",
+		.x = 20,
+		.y = 20,
+		.w = 200,
+		.h = 16
+	};
+
+	for (;;) {
+		unsigned int elapsed = clock_elapsed(&clock);
+
+		clock_start(&clock);
+
+		for (union event ev; event_poll(&ev); ) {
+			switch (ev.type) {
+			case EVENT_QUIT:
+				return;
+			default:
+				checkbox_handle(&cb, &ev);
+				break;
+			}
+		}
+
+		painter_set_color(0xffffffff);
+		painter_clear();
+
+		theme_draw_frame(NULL, &(const struct frame){ .x=10, .y=10, .w=500, .h=500 });
+		checkbox_draw(&cb);
+
+		painter_present();
+
+		if ((elapsed = clock_elapsed(&clock)) < 20)
+			delay(20 - elapsed);
+	}
+}
+
+static void
+close(void)
+{
+	window_finish();
+	sys_finish();
+}
+
+int
+main(int argc, char **argv)
+{
+	(void)argc;
+	(void)argv;
+
+	init();
+
+	if (setjmp(panic_buf) == 0)
+		/* Initial game run. */
+		run();
+	else {
+		/* Clear event queue to avoid accidental key presses. */
+		for (union event ev; event_poll(&ev); )
+			continue;
+
+		game_switch(&panic_state, true);
+		run();
+	}
+
+	close();
+
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/bcc/CMakeLists.txt	Sat Oct 03 18:32:01 2020 +0200
@@ -0,0 +1,20 @@
+#
+# CMakeLists.txt -- CMake build system for molko-bcc
+#
+# Copyright (c) 2020 David Demelier <markand@malikania.fr>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+project(molko-bcc)
+add_executable(bcc bcc.c)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/bcc/bcc.c	Sat Oct 03 18:32:01 2020 +0200
@@ -0,0 +1,127 @@
+/*
+ * molko-bcc.c -- simple binary compiler
+ *
+ * Copyright (c) 2020 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdnoreturn.h>
+#include <string.h>
+#include <unistd.h>
+
+static const char *charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
+static bool fstatic;
+
+noreturn static void
+usage(void)
+{
+	fprintf(stderr, "usage: molko-bcc [-s] input varname\n");
+	exit(1);
+}
+
+noreturn static void
+die(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	fputs("abort: ", stderr);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	exit(1);
+}
+
+static char *
+mangle(char *variable)
+{
+	char *p;
+	size_t pos;
+
+	/* Remove extension. */
+	if ((p = strrchr(variable, '.')))
+		*p = '\0';
+
+	/* Remove disallowed characters. */
+	while ((pos = strspn(variable, charset)) != strlen(variable))
+		variable[pos] = '_';
+
+	return variable;
+}
+
+static void
+process(const char *input, const char *variable)
+{
+	FILE *fp;
+	int ch, idx = 0;
+
+	if (strcmp(input, "-") == 0)
+		fp = stdin;
+	else if (!(fp = fopen(input, "rb")))
+		die("%s: %s\n", input, strerror(errno));
+
+	if (fstatic)
+		printf("static ");
+
+	printf("const unsigned char %s[] = {\n", variable);
+
+	while ((ch = fgetc(fp)) != EOF) {
+		if (idx == 0)
+			putchar('\t');
+
+		printf("0x%02x", (unsigned char)ch);
+
+		if (!feof(fp))
+			printf(", ");
+
+		if (++idx == 4) {
+			idx = 0;
+			putchar('\n');
+		}
+	}
+
+	if (idx != 0)
+		printf("\n");
+
+	puts("};");
+	fclose(fp);
+}
+
+int
+main(int argc, char **argv)
+{
+	int ch;
+
+	while ((ch = getopt(argc, argv, "s")) != -1) {
+		switch (ch) {
+		case 's':
+			fstatic = true;
+			break;
+		default:
+			break;
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	if (argc < 2)
+		usage();
+
+	process(argv[0], mangle(argv[1]));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/map/CMakeLists.txt	Sat Oct 03 18:32:01 2020 +0200
@@ -0,0 +1,21 @@
+#
+# CMakeLists.txt -- CMake build system for molko-map
+#
+# Copyright (c) 2020 David Demelier <markand@malikania.fr>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+project(molko-map)
+add_executable(map map.c)
+target_link_libraries(map Jansson::Jansson)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/map/map.c	Sat Oct 03 18:32:01 2020 +0200
@@ -0,0 +1,304 @@
+/*
+ * molko-map.c -- convert tiled tiled JSON files into custom files
+ *
+ * Copyright (c) 2020 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdnoreturn.h>
+#include <string.h>
+
+#include <jansson.h>
+
+static void
+die(const char *fmt, ...)
+{
+	assert(fmt);
+
+	va_list ap;
+
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	exit(1);
+}
+
+static bool
+is_layer(const char *name)
+{
+	return strcmp(name, "background") == 0 ||
+	       strcmp(name, "foreground") == 0 ||
+	       strcmp(name, "objects") == 0;
+}
+
+static const json_t *
+find_property(const json_t *props, const char *which)
+{
+	json_t *value;
+	size_t index;
+
+	json_array_foreach(props, index, value) {
+		if (!json_is_object(value))
+			continue;
+
+		const json_t *key = json_object_get(value, "name");
+
+		if (json_is_string(key) && strcmp(json_string_value(key), which) == 0)
+			return value;
+	}
+
+	return NULL;
+}
+
+static void
+write_title(const json_t *props)
+{
+	const json_t *prop_title = find_property(props, "title");
+
+	if (!prop_title)
+		return;
+
+	const json_t *title = json_object_get(prop_title, "value");
+
+	if (title && json_is_string(title))
+		printf("title|%s\n", json_string_value(title));
+}
+
+static void
+write_origin(const json_t *props)
+{
+	const json_t *prop_origin_x = find_property(props, "origin-x");
+	const json_t *prop_origin_y = find_property(props, "origin-y");
+
+	if (!prop_origin_x || !prop_origin_y)
+		return;
+
+	const json_t *origin_x = json_object_get(prop_origin_x, "value");
+	const json_t *origin_y = json_object_get(prop_origin_y, "value");
+
+	if (!origin_x || !json_is_integer(origin_x) ||
+	    !origin_y || !json_is_integer(origin_y))
+		return;
+
+	printf("origin|%lld|%lld\n", json_integer_value(origin_x),
+	    json_integer_value(origin_y));
+}
+
+static void
+write_properties(const json_t *props)
+{
+	write_title(props);
+	write_origin(props);
+}
+
+static void
+write_metadata(const json_t *document)
+{
+	json_t *width = json_object_get(document, "width");
+	json_t *height = json_object_get(document, "height");
+	json_t *tilewidth = json_object_get(document, "tilewidth");
+	json_t *tileheight = json_object_get(document, "tileheight");
+
+	if (!width || !json_is_integer(width))
+		die("missing 'width' property\n");
+	if (!height || !json_is_integer(height))
+		die("missing 'height' property\n");
+	if (!tilewidth || !json_is_integer(tilewidth))
+		die("missing 'tilewidth' property\n");
+	if (!tileheight || !json_is_integer(tileheight))
+		die("missing 'tileheight' property\n");
+
+	printf("width|%lld\n", json_integer_value(width));
+	printf("height|%lld\n", json_integer_value(height));
+	printf("tilewidth|%lld\n", json_integer_value(tilewidth));
+	printf("tileheight|%lld\n", json_integer_value(tileheight));
+}
+
+static void
+write_object_property(int id, const json_t *property)
+{
+	assert(json_is_object(property));
+
+	json_t *name = json_object_get(property, "name");
+	json_t *type = json_object_get(property, "type");
+	json_t *value = json_object_get(property, "value");
+
+	if (!name || !json_is_string(name))
+		die("invalid 'name' property in object");
+	if (!type || !json_is_string(type))
+		die("invalid 'type' property in object");
+	if (!value || !json_is_string(value))
+		die("invalid 'value' property in object");
+
+	printf("object-property|%d|%s|%s\n",
+	    id,
+	    json_string_value(name),
+	    json_string_value(value)
+	);
+}
+
+static void
+write_object(const json_t *object)
+{
+	assert(json_is_object(object));
+
+	json_t *id = json_object_get(object, "id");
+	json_t *x = json_object_get(object, "x");
+	json_t *y = json_object_get(object, "y");
+	json_t *width = json_object_get(object, "width");
+	json_t *height = json_object_get(object, "height");
+	json_t *type = json_object_get(object, "type");
+	json_t *props = json_object_get(object, "properties");
+
+	if (!id || !json_is_integer(id))
+		die("invalid 'id' property in object\n");
+	if (!x || !json_is_real(x))
+		die("invalid 'x' property in object\n");
+	if (!y || !json_is_real(y))
+		die("invalid 'y' property in object\n");
+	if (!width || !json_is_real(width))
+		die("invalid 'width' property in object\n");
+	if (!height || !json_is_real(height))
+		die("invalid 'height' property in object\n");
+	if (!type || !json_is_string(type))
+		die("invalid 'type' property in object\n");
+
+	/* In tiled, those properties are float but we only use ints in MA */
+	printf("object|%lld|%s|%d|%d|%d|%d\n",
+	    json_integer_value(id),
+	    json_string_value(type),
+	    (int)json_real_value(x),
+	    (int)json_real_value(y),
+	    (int)json_real_value(width),
+	    (int)json_real_value(height)
+	);
+
+	if (json_is_array(props)) {
+		json_t *prop;
+		size_t index;
+
+		json_array_foreach(props, index, prop) {
+			if (!json_is_object(prop))
+				die("invalid property in object\n");
+
+			write_object_property(json_integer_value(id), prop);
+		}
+	}
+}
+
+static void
+write_layer(const json_t *layer)
+{
+	json_t *objects = json_object_get(layer, "objects");
+	json_t *data = json_object_get(layer, "data");
+	json_t *name = json_object_get(layer, "name");
+	json_t *tile, *object;
+	size_t index;
+
+	if (!name || !json_is_string(name))
+		die("invalid 'name' property in layer");
+	if (!is_layer(json_string_value(name)))
+		die("invalid 'name' layer: %s\n", json_string_value(name));
+
+	printf("layer|%s\n", json_string_value(name));
+
+	/* Only foreground/background have 'data' property */
+	if (json_is_array(data)) {
+		json_array_foreach(data, index, tile) {
+			if (!json_is_integer(tile))
+				die("invalid 'data' property in layer\n");
+
+			printf("%lld\n", json_integer_value(tile));
+		}
+	}
+
+	/* Only objects has 'objects' property */
+	if (json_is_array(objects)) {
+		json_array_foreach(objects, index, object) {
+			if (!json_is_object(object))
+				die("invalid 'objects' property in layer\n");
+
+			write_object(object);
+		}
+	}
+}
+
+static void
+write_layers(const json_t *layers)
+{
+	size_t index;
+	json_t *layer;
+
+	if (!layers)
+		return;
+
+	json_array_foreach(layers, index, layer) {
+		if (!json_is_object(layer))
+			die("layer is not an object\n");
+
+		write_layer(layer);
+	}
+}
+
+static void
+write_tileset(const json_t *tileset)
+{
+	json_t *image = json_object_get(tileset, "image");
+
+	if (!image || !json_is_string(image))
+		die("invalid 'image' property in tileset");
+
+	printf("tileset|%s\n", json_string_value(image));
+}
+
+static void
+write_tilesets(const json_t *tilesets)
+{
+	json_t *tileset;
+	size_t index;
+
+	if (!json_is_array(tilesets))
+		die("invalid 'tilesets' property");
+
+	json_array_foreach(tilesets, index, tileset) {
+		if (!json_is_object(tileset))
+			die("invalid tileset");
+
+		write_tileset(tileset);
+	}
+}
+
+int
+main(void)
+{
+	json_t *document;
+	json_error_t error;
+
+	document = json_loadf(stdin, 0, &error);
+
+	if (!document)
+		die("%d:%d: %s\n", error.line, error.column, error.text);
+
+	write_properties(json_object_get(document, "properties"));
+	write_metadata(document);
+	write_layers(json_object_get(document, "layers"));
+	write_tilesets(json_object_get(document, "tilesets"));
+
+	json_decref(document);
+}
--- a/tools/molko-bcc.c	Sun Jul 12 09:44:27 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/*
- * molko-bcc.c -- simple binary compiler
- *
- * Copyright (c) 2020 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdnoreturn.h>
-#include <string.h>
-#include <unistd.h>
-
-static const char *charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
-static bool fstatic;
-
-noreturn static void
-usage(void)
-{
-	fprintf(stderr, "usage: molko-bcc [-s] input varname\n");
-	exit(1);
-}
-
-noreturn static void
-die(const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	fputs("abort: ", stderr);
-	vfprintf(stderr, fmt, ap);
-	va_end(ap);
-	exit(1);
-}
-
-static char *
-mangle(char *variable)
-{
-	char *p;
-	size_t pos;
-
-	/* Remove extension. */
-	if ((p = strrchr(variable, '.')))
-		*p = '\0';
-
-	/* Remove disallowed characters. */
-	while ((pos = strspn(variable, charset)) != strlen(variable))
-		variable[pos] = '_';
-
-	return variable;
-}
-
-static void
-process(const char *input, const char *variable)
-{
-	FILE *fp;
-	int ch, idx = 0;
-
-	if (strcmp(input, "-") == 0)
-		fp = stdin;
-	else if (!(fp = fopen(input, "rb")))
-		die("%s: %s\n", input, strerror(errno));
-
-	if (fstatic)
-		printf("static ");
-
-	printf("const unsigned char %s[] = {\n", variable);
-
-	while ((ch = fgetc(fp)) != EOF) {
-		if (idx == 0)
-			putchar('\t');
-
-		printf("0x%02x", (unsigned char)ch);
-
-		if (!feof(fp))
-			printf(", ");
-
-		if (++idx == 4) {
-			idx = 0;
-			putchar('\n');
-		}
-	}
-
-	if (idx != 0)
-		printf("\n");
-
-	puts("};");
-	fclose(fp);
-}
-
-int
-main(int argc, char **argv)
-{
-	int ch;
-
-	while ((ch = getopt(argc, argv, "s")) != -1) {
-		switch (ch) {
-		case 's':
-			fstatic = true;
-			break;
-		default:
-			break;
-		}
-	}
-
-	argc -= optind;
-	argv += optind;
-
-	if (argc < 2)
-		usage();
-
-	process(argv[0], mangle(argv[1]));
-}
--- a/tools/molko-map.c	Sun Jul 12 09:44:27 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,304 +0,0 @@
-/*
- * molko-map.c -- convert tiled tiled JSON files into custom files
- *
- * Copyright (c) 2020 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdnoreturn.h>
-#include <string.h>
-
-#include <jansson.h>
-
-static void
-die(const char *fmt, ...)
-{
-	assert(fmt);
-
-	va_list ap;
-
-	va_start(ap, fmt);
-	vfprintf(stderr, fmt, ap);
-	va_end(ap);
-	exit(1);
-}
-
-static bool
-is_layer(const char *name)
-{
-	return strcmp(name, "background") == 0 ||
-	       strcmp(name, "foreground") == 0 ||
-	       strcmp(name, "objects") == 0;
-}
-
-static const json_t *
-find_property(const json_t *props, const char *which)
-{
-	json_t *value;
-	size_t index;
-
-	json_array_foreach(props, index, value) {
-		if (!json_is_object(value))
-			continue;
-
-		const json_t *key = json_object_get(value, "name");
-
-		if (json_is_string(key) && strcmp(json_string_value(key), which) == 0)
-			return value;
-	}
-
-	return NULL;
-}
-
-static void
-write_title(const json_t *props)
-{
-	const json_t *prop_title = find_property(props, "title");
-
-	if (!prop_title)
-		return;
-
-	const json_t *title = json_object_get(prop_title, "value");
-
-	if (title && json_is_string(title))
-		printf("title|%s\n", json_string_value(title));
-}
-
-static void
-write_origin(const json_t *props)
-{
-	const json_t *prop_origin_x = find_property(props, "origin-x");
-	const json_t *prop_origin_y = find_property(props, "origin-y");
-
-	if (!prop_origin_x || !prop_origin_y)
-		return;
-
-	const json_t *origin_x = json_object_get(prop_origin_x, "value");
-	const json_t *origin_y = json_object_get(prop_origin_y, "value");
-
-	if (!origin_x || !json_is_integer(origin_x) ||
-	    !origin_y || !json_is_integer(origin_y))
-		return;
-
-	printf("origin|%lld|%lld\n", json_integer_value(origin_x),
-	    json_integer_value(origin_y));
-}
-
-static void
-write_properties(const json_t *props)
-{
-	write_title(props);
-	write_origin(props);
-}
-
-static void
-write_metadata(const json_t *document)
-{
-	json_t *width = json_object_get(document, "width");
-	json_t *height = json_object_get(document, "height");
-	json_t *tilewidth = json_object_get(document, "tilewidth");
-	json_t *tileheight = json_object_get(document, "tileheight");
-
-	if (!width || !json_is_integer(width))
-		die("missing 'width' property\n");
-	if (!height || !json_is_integer(height))
-		die("missing 'height' property\n");
-	if (!tilewidth || !json_is_integer(tilewidth))
-		die("missing 'tilewidth' property\n");
-	if (!tileheight || !json_is_integer(tileheight))
-		die("missing 'tileheight' property\n");
-
-	printf("width|%lld\n", json_integer_value(width));
-	printf("height|%lld\n", json_integer_value(height));
-	printf("tilewidth|%lld\n", json_integer_value(tilewidth));
-	printf("tileheight|%lld\n", json_integer_value(tileheight));
-}
-
-static void
-write_object_property(int id, const json_t *property)
-{
-	assert(json_is_object(property));
-
-	json_t *name = json_object_get(property, "name");
-	json_t *type = json_object_get(property, "type");
-	json_t *value = json_object_get(property, "value");
-
-	if (!name || !json_is_string(name))
-		die("invalid 'name' property in object");
-	if (!type || !json_is_string(type))
-		die("invalid 'type' property in object");
-	if (!value || !json_is_string(value))
-		die("invalid 'value' property in object");
-
-	printf("object-property|%d|%s|%s\n",
-	    id,
-	    json_string_value(name),
-	    json_string_value(value)
-	);
-}
-
-static void
-write_object(const json_t *object)
-{
-	assert(json_is_object(object));
-
-	json_t *id = json_object_get(object, "id");
-	json_t *x = json_object_get(object, "x");
-	json_t *y = json_object_get(object, "y");
-	json_t *width = json_object_get(object, "width");
-	json_t *height = json_object_get(object, "height");
-	json_t *type = json_object_get(object, "type");
-	json_t *props = json_object_get(object, "properties");
-
-	if (!id || !json_is_integer(id))
-		die("invalid 'id' property in object\n");
-	if (!x || !json_is_real(x))
-		die("invalid 'x' property in object\n");
-	if (!y || !json_is_real(y))
-		die("invalid 'y' property in object\n");
-	if (!width || !json_is_real(width))
-		die("invalid 'width' property in object\n");
-	if (!height || !json_is_real(height))
-		die("invalid 'height' property in object\n");
-	if (!type || !json_is_string(type))
-		die("invalid 'type' property in object\n");
-
-	/* In tiled, those properties are float but we only use ints in MA */
-	printf("object|%lld|%s|%d|%d|%d|%d\n",
-	    json_integer_value(id),
-	    json_string_value(type),
-	    (int)json_real_value(x),
-	    (int)json_real_value(y),
-	    (int)json_real_value(width),
-	    (int)json_real_value(height)
-	);
-
-	if (json_is_array(props)) {
-		json_t *prop;
-		size_t index;
-
-		json_array_foreach(props, index, prop) {
-			if (!json_is_object(prop))
-				die("invalid property in object\n");
-
-			write_object_property(json_integer_value(id), prop);
-		}
-	}
-}
-
-static void
-write_layer(const json_t *layer)
-{
-	json_t *objects = json_object_get(layer, "objects");
-	json_t *data = json_object_get(layer, "data");
-	json_t *name = json_object_get(layer, "name");
-	json_t *tile, *object;
-	size_t index;
-
-	if (!name || !json_is_string(name))
-		die("invalid 'name' property in layer");
-	if (!is_layer(json_string_value(name)))
-		die("invalid 'name' layer: %s\n", json_string_value(name));
-
-	printf("layer|%s\n", json_string_value(name));
-
-	/* Only foreground/background have 'data' property */
-	if (json_is_array(data)) {
-		json_array_foreach(data, index, tile) {
-			if (!json_is_integer(tile))
-				die("invalid 'data' property in layer\n");
-
-			printf("%lld\n", json_integer_value(tile));
-		}
-	}
-
-	/* Only objects has 'objects' property */
-	if (json_is_array(objects)) {
-		json_array_foreach(objects, index, object) {
-			if (!json_is_object(object))
-				die("invalid 'objects' property in layer\n");
-
-			write_object(object);
-		}
-	}
-}
-
-static void
-write_layers(const json_t *layers)
-{
-	size_t index;
-	json_t *layer;
-
-	if (!layers)
-		return;
-
-	json_array_foreach(layers, index, layer) {
-		if (!json_is_object(layer))
-			die("layer is not an object\n");
-
-		write_layer(layer);
-	}
-}
-
-static void
-write_tileset(const json_t *tileset)
-{
-	json_t *image = json_object_get(tileset, "image");
-
-	if (!image || !json_is_string(image))
-		die("invalid 'image' property in tileset");
-
-	printf("tileset|%s\n", json_string_value(image));
-}
-
-static void
-write_tilesets(const json_t *tilesets)
-{
-	json_t *tileset;
-	size_t index;
-
-	if (!json_is_array(tilesets))
-		die("invalid 'tilesets' property");
-
-	json_array_foreach(tilesets, index, tileset) {
-		if (!json_is_object(tileset))
-			die("invalid tileset");
-
-		write_tileset(tileset);
-	}
-}
-
-int
-main(void)
-{
-	json_t *document;
-	json_error_t error;
-
-	document = json_loadf(stdin, 0, &error);
-
-	if (!document)
-		die("%d:%d: %s\n", error.line, error.column, error.text);
-
-	write_properties(json_object_get(document, "properties"));
-	write_metadata(document);
-	write_layers(json_object_get(document, "layers"));
-	write_tilesets(json_object_get(document, "tilesets"));
-
-	json_decref(document);
-}