changeset 431:8f59201dc76b

core: cleanup hierarchy
author David Demelier <markand@malikania.fr>
date Sat, 15 Oct 2022 20:23:14 +0200
parents 1645433e008d
children 38cf60f5a1c4
files GNUmakefile examples/example-action/example-action.c examples/example-animation/example-animation.c examples/example-audio/example-audio.c examples/example-cursor/example-cursor.c examples/example-debug/example-debug.c examples/example-drawable/example-drawable.c examples/example-font/example-font.c examples/example-gridmenu/example-gridmenu.c examples/example-label/example-label.c examples/example-message/example-message.c examples/example-notify/example-notify.c examples/example-sprite/example-sprite.c examples/example-ui/example-ui.c examples/example/registry.c examples/example/registry.h examples/example/spell-fire.c examples/example/trace_hud.c libmlk-core/mlk/core/action-stack.c libmlk-core/mlk/core/action-stack.h libmlk-core/mlk/core/action.c libmlk-core/mlk/core/action.h libmlk-core/mlk/core/alloc.c libmlk-core/mlk/core/alloc.h libmlk-core/mlk/core/animation.c libmlk-core/mlk/core/animation.h libmlk-core/mlk/core/buf.c libmlk-core/mlk/core/buf.h libmlk-core/mlk/core/clock.c libmlk-core/mlk/core/clock.h libmlk-core/mlk/core/color.h libmlk-core/mlk/core/core.c libmlk-core/mlk/core/core.h libmlk-core/mlk/core/drawable-stack.c libmlk-core/mlk/core/drawable-stack.h libmlk-core/mlk/core/drawable.c libmlk-core/mlk/core/drawable.h libmlk-core/mlk/core/err.c libmlk-core/mlk/core/err.h libmlk-core/mlk/core/error.c libmlk-core/mlk/core/error.h libmlk-core/mlk/core/event.c libmlk-core/mlk/core/event.h libmlk-core/mlk/core/font.c libmlk-core/mlk/core/font.h libmlk-core/mlk/core/game.c libmlk-core/mlk/core/game.h libmlk-core/mlk/core/image.c libmlk-core/mlk/core/image.h libmlk-core/mlk/core/inhibit.h libmlk-core/mlk/core/key.h libmlk-core/mlk/core/maths.c libmlk-core/mlk/core/maths.h libmlk-core/mlk/core/mouse.h libmlk-core/mlk/core/music.c libmlk-core/mlk/core/music.h libmlk-core/mlk/core/painter.c libmlk-core/mlk/core/painter.h libmlk-core/mlk/core/panic.c libmlk-core/mlk/core/panic.h libmlk-core/mlk/core/script.c libmlk-core/mlk/core/script.h libmlk-core/mlk/core/sound.c libmlk-core/mlk/core/sound.h libmlk-core/mlk/core/sprite.c libmlk-core/mlk/core/sprite.h libmlk-core/mlk/core/state.c libmlk-core/mlk/core/state.h libmlk-core/mlk/core/sys.c libmlk-core/mlk/core/sys.h libmlk-core/mlk/core/sys_p.h libmlk-core/mlk/core/texture.c libmlk-core/mlk/core/texture.h libmlk-core/mlk/core/texture_p.h libmlk-core/mlk/core/trace.c libmlk-core/mlk/core/trace.h libmlk-core/mlk/core/util.c libmlk-core/mlk/core/util.h libmlk-core/mlk/core/window.c libmlk-core/mlk/core/window.h libmlk-core/mlk/core/window_p.h src/libmlk-core/core/action-stack.c src/libmlk-core/core/action-stack.h src/libmlk-core/core/action.c src/libmlk-core/core/action.h src/libmlk-core/core/alloc.c src/libmlk-core/core/alloc.h src/libmlk-core/core/animation.c src/libmlk-core/core/animation.h src/libmlk-core/core/buf.c src/libmlk-core/core/buf.h src/libmlk-core/core/clock.c src/libmlk-core/core/clock.h src/libmlk-core/core/color.h src/libmlk-core/core/core.c src/libmlk-core/core/core.h src/libmlk-core/core/drawable-stack.c src/libmlk-core/core/drawable-stack.h src/libmlk-core/core/drawable.c src/libmlk-core/core/drawable.h src/libmlk-core/core/err.c src/libmlk-core/core/err.h src/libmlk-core/core/error.c src/libmlk-core/core/error.h src/libmlk-core/core/event.c src/libmlk-core/core/event.h src/libmlk-core/core/font.c src/libmlk-core/core/font.h src/libmlk-core/core/game.c src/libmlk-core/core/game.h src/libmlk-core/core/image.c src/libmlk-core/core/image.h src/libmlk-core/core/inhibit.h src/libmlk-core/core/key.h src/libmlk-core/core/maths.c src/libmlk-core/core/maths.h src/libmlk-core/core/mouse.h src/libmlk-core/core/music.c src/libmlk-core/core/music.h src/libmlk-core/core/painter.c src/libmlk-core/core/painter.h src/libmlk-core/core/panic.c src/libmlk-core/core/panic.h src/libmlk-core/core/script.c src/libmlk-core/core/script.h src/libmlk-core/core/sound.c src/libmlk-core/core/sound.h src/libmlk-core/core/sprite.c src/libmlk-core/core/sprite.h src/libmlk-core/core/state.c src/libmlk-core/core/state.h src/libmlk-core/core/sys.c src/libmlk-core/core/sys.h src/libmlk-core/core/sys_p.h src/libmlk-core/core/texture.c src/libmlk-core/core/texture.h src/libmlk-core/core/texture_p.h src/libmlk-core/core/trace.c src/libmlk-core/core/trace.h src/libmlk-core/core/util.c src/libmlk-core/core/util.h src/libmlk-core/core/window.c src/libmlk-core/core/window.h src/libmlk-core/core/window_p.h src/libmlk-rpg/rpg/battle-bar-default.c src/libmlk-rpg/rpg/battle-bar-default.h src/libmlk-rpg/rpg/battle-bar.h src/libmlk-rpg/rpg/battle-entity-state-attacking.c src/libmlk-rpg/rpg/battle-entity-state-attacking.h src/libmlk-rpg/rpg/battle-entity-state-blinking.c src/libmlk-rpg/rpg/battle-entity-state-moving.c src/libmlk-rpg/rpg/battle-entity-state.h src/libmlk-rpg/rpg/battle-entity.c src/libmlk-rpg/rpg/battle-entity.h src/libmlk-rpg/rpg/battle-indicator.c src/libmlk-rpg/rpg/battle-indicator.h src/libmlk-rpg/rpg/battle-message.c src/libmlk-rpg/rpg/battle-message.h src/libmlk-rpg/rpg/battle-state-ai.c src/libmlk-rpg/rpg/battle-state-attacking.c src/libmlk-rpg/rpg/battle-state-check.c src/libmlk-rpg/rpg/battle-state-closing.c src/libmlk-rpg/rpg/battle-state-closing.h src/libmlk-rpg/rpg/battle-state-item.c src/libmlk-rpg/rpg/battle-state-lost.c src/libmlk-rpg/rpg/battle-state-menu.c src/libmlk-rpg/rpg/battle-state-opening.c src/libmlk-rpg/rpg/battle-state-rendering.c src/libmlk-rpg/rpg/battle-state-selection.c src/libmlk-rpg/rpg/battle-state-victory.c src/libmlk-rpg/rpg/battle-state.h src/libmlk-rpg/rpg/battle.c src/libmlk-rpg/rpg/battle.h src/libmlk-rpg/rpg/character.c src/libmlk-rpg/rpg/character.h src/libmlk-rpg/rpg/equipment.h src/libmlk-rpg/rpg/inventory.h src/libmlk-rpg/rpg/item.h src/libmlk-rpg/rpg/map-file.c src/libmlk-rpg/rpg/map-file.h src/libmlk-rpg/rpg/map.c src/libmlk-rpg/rpg/map.h src/libmlk-rpg/rpg/message.c src/libmlk-rpg/rpg/message.h src/libmlk-rpg/rpg/property.h src/libmlk-rpg/rpg/quest.h src/libmlk-rpg/rpg/rpg.h src/libmlk-rpg/rpg/save.c src/libmlk-rpg/rpg/save.h src/libmlk-rpg/rpg/selection.c src/libmlk-rpg/rpg/selection.h src/libmlk-rpg/rpg/spell.h src/libmlk-rpg/rpg/tileset-file.c src/libmlk-rpg/rpg/tileset-file.h src/libmlk-rpg/rpg/tileset.c src/libmlk-rpg/rpg/tileset.h src/libmlk-rpg/rpg/walksprite.c src/libmlk-rpg/rpg/walksprite.h src/libmlk-ui/ui/align.h src/libmlk-ui/ui/button.c src/libmlk-ui/ui/button.h src/libmlk-ui/ui/checkbox.c src/libmlk-ui/ui/checkbox.h src/libmlk-ui/ui/debug.c src/libmlk-ui/ui/debug.h src/libmlk-ui/ui/frame.c src/libmlk-ui/ui/frame.h src/libmlk-ui/ui/gridmenu.c src/libmlk-ui/ui/gridmenu.h src/libmlk-ui/ui/label.c src/libmlk-ui/ui/label.h src/libmlk-ui/ui/notify.c src/libmlk-ui/ui/notify.h src/libmlk-ui/ui/theme.c src/libmlk-ui/ui/theme.h src/libmlk-ui/ui/ui.h tests/test-action-script.c tests/test-action.c tests/test-alloc.c tests/test-color.c tests/test-drawable.c tests/test-error.c tests/test-map.c tests/test-save-quest.c tests/test-state.c tests/test-tileset.c tests/test-util.c
diffstat 227 files changed, 5720 insertions(+), 5720 deletions(-) [+]
line wrap: on
line diff
--- a/GNUmakefile	Sat Oct 15 17:18:45 2022 +0200
+++ b/GNUmakefile	Sat Oct 15 20:23:14 2022 +0200
@@ -42,7 +42,7 @@
 INCS :=                 -Iextern/libdt \
                         -Iextern/libsqlite \
                         -Isrc/libmlk-util \
-                        -Isrc/libmlk-core \
+                        -Ilibmlk-core \
                         -Isrc/libmlk-ui \
                         -Isrc/libmlk-rpg \
                         -I. \
@@ -172,34 +172,34 @@
 # {{{ libmlk-core
 
 LIBMLK_CORE :=          libmlk-core.a
-LIBMLK_CORE_SRCS :=     src/libmlk-core/core/action-stack.c \
-                        src/libmlk-core/core/action.c \
-                        src/libmlk-core/core/alloc.c \
-                        src/libmlk-core/core/animation.c \
-                        src/libmlk-core/core/buf.c \
-                        src/libmlk-core/core/clock.c \
-                        src/libmlk-core/core/core.c \
-                        src/libmlk-core/core/drawable-stack.c \
-                        src/libmlk-core/core/drawable.c \
-                        src/libmlk-core/core/err.c \
-                        src/libmlk-core/core/error.c \
-                        src/libmlk-core/core/event.c \
-                        src/libmlk-core/core/font.c \
-                        src/libmlk-core/core/game.c \
-                        src/libmlk-core/core/image.c \
-                        src/libmlk-core/core/maths.c \
-                        src/libmlk-core/core/music.c \
-                        src/libmlk-core/core/painter.c \
-                        src/libmlk-core/core/panic.c \
-                        src/libmlk-core/core/script.c \
-                        src/libmlk-core/core/sound.c \
-                        src/libmlk-core/core/sprite.c \
-                        src/libmlk-core/core/state.c \
-                        src/libmlk-core/core/sys.c \
-                        src/libmlk-core/core/texture.c \
-                        src/libmlk-core/core/trace.c \
-                        src/libmlk-core/core/util.c \
-                        src/libmlk-core/core/window.c
+LIBMLK_CORE_SRCS :=     libmlk-core/mlk/core/action-stack.c \
+                        libmlk-core/mlk/core/action.c \
+                        libmlk-core/mlk/core/alloc.c \
+                        libmlk-core/mlk/core/animation.c \
+                        libmlk-core/mlk/core/buf.c \
+                        libmlk-core/mlk/core/clock.c \
+                        libmlk-core/mlk/core/core.c \
+                        libmlk-core/mlk/core/drawable-stack.c \
+                        libmlk-core/mlk/core/drawable.c \
+                        libmlk-core/mlk/core/err.c \
+                        libmlk-core/mlk/core/error.c \
+                        libmlk-core/mlk/core/event.c \
+                        libmlk-core/mlk/core/font.c \
+                        libmlk-core/mlk/core/game.c \
+                        libmlk-core/mlk/core/image.c \
+                        libmlk-core/mlk/core/maths.c \
+                        libmlk-core/mlk/core/music.c \
+                        libmlk-core/mlk/core/painter.c \
+                        libmlk-core/mlk/core/panic.c \
+                        libmlk-core/mlk/core/script.c \
+                        libmlk-core/mlk/core/sound.c \
+                        libmlk-core/mlk/core/sprite.c \
+                        libmlk-core/mlk/core/state.c \
+                        libmlk-core/mlk/core/sys.c \
+                        libmlk-core/mlk/core/texture.c \
+                        libmlk-core/mlk/core/trace.c \
+                        libmlk-core/mlk/core/util.c \
+                        libmlk-core/mlk/core/window.c
 LIBMLK_CORE_OBJS :=     $(LIBMLK_CORE_SRCS:.c=.o)
 LIBMLK_CORE_DEPS :=     $(LIBMLK_CORE_SRCS:.c=.d)
 
--- a/examples/example-action/example-action.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example-action/example-action.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,22 +18,22 @@
 
 #include <assert.h>
 
-#include <core/action.h>
-#include <core/action-stack.h>
-#include <core/core.h>
-#include <core/event.h>
-#include <core/game.h>
-#include <core/image.h>
-#include <core/maths.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/script.h>
-#include <core/sprite.h>
-#include <core/state.h>
-#include <core/sys.h>
-#include <core/texture.h>
-#include <core/util.h>
-#include <core/window.h>
+#include <mlk/core/action.h>
+#include <mlk/core/action-stack.h>
+#include <mlk/core/core.h>
+#include <mlk/core/event.h>
+#include <mlk/core/game.h>
+#include <mlk/core/image.h>
+#include <mlk/core/maths.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/script.h>
+#include <mlk/core/sprite.h>
+#include <mlk/core/state.h>
+#include <mlk/core/sys.h>
+#include <mlk/core/texture.h>
+#include <mlk/core/util.h>
+#include <mlk/core/window.h>
 
 #include <ui/theme.h>
 #include <ui/ui.h>
--- a/examples/example-animation/example-animation.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example-animation/example-animation.c	Sat Oct 15 20:23:14 2022 +0200
@@ -16,19 +16,19 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <core/animation.h>
-#include <core/core.h>
-#include <core/event.h>
-#include <core/game.h>
-#include <core/image.h>
-#include <core/sys.h>
-#include <core/window.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/sprite.h>
-#include <core/state.h>
-#include <core/texture.h>
-#include <core/util.h>
+#include <mlk/core/animation.h>
+#include <mlk/core/core.h>
+#include <mlk/core/event.h>
+#include <mlk/core/game.h>
+#include <mlk/core/image.h>
+#include <mlk/core/sys.h>
+#include <mlk/core/window.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/sprite.h>
+#include <mlk/core/state.h>
+#include <mlk/core/texture.h>
+#include <mlk/core/util.h>
 
 #include <ui/label.h>
 #include <ui/ui.h>
--- a/examples/example-audio/example-audio.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example-audio/example-audio.c	Sat Oct 15 20:23:14 2022 +0200
@@ -16,17 +16,17 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <core/core.h>
-#include <core/event.h>
-#include <core/game.h>
-#include <core/music.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/sound.h>
-#include <core/state.h>
-#include <core/sys.h>
-#include <core/util.h>
-#include <core/window.h>
+#include <mlk/core/core.h>
+#include <mlk/core/event.h>
+#include <mlk/core/game.h>
+#include <mlk/core/music.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/sound.h>
+#include <mlk/core/state.h>
+#include <mlk/core/sys.h>
+#include <mlk/core/util.h>
+#include <mlk/core/window.h>
 
 #include <ui/label.h>
 #include <ui/theme.h>
--- a/examples/example-cursor/example-cursor.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example-cursor/example-cursor.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,16 +18,16 @@
 
 #include <stdio.h>
 
-#include <core/core.h>
-#include <core/event.h>
-#include <core/game.h>
-#include <core/key.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/state.h>
-#include <core/sys.h>
-#include <core/util.h>
-#include <core/window.h>
+#include <mlk/core/core.h>
+#include <mlk/core/event.h>
+#include <mlk/core/game.h>
+#include <mlk/core/key.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/state.h>
+#include <mlk/core/sys.h>
+#include <mlk/core/util.h>
+#include <mlk/core/window.h>
 
 #include <ui/label.h>
 #include <ui/ui.h>
--- a/examples/example-debug/example-debug.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example-debug/example-debug.c	Sat Oct 15 20:23:14 2022 +0200
@@ -16,14 +16,14 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <core/core.h>
-#include <core/event.h>
-#include <core/game.h>
-#include <core/window.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/state.h>
-#include <core/util.h>
+#include <mlk/core/core.h>
+#include <mlk/core/event.h>
+#include <mlk/core/game.h>
+#include <mlk/core/window.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/state.h>
+#include <mlk/core/util.h>
 
 #include <ui/debug.h>
 #include <ui/theme.h>
--- a/examples/example-drawable/example-drawable.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example-drawable/example-drawable.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,23 +19,23 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <core/alloc.h>
-#include <core/animation.h>
-#include <core/core.h>
-#include <core/event.h>
-#include <core/game.h>
-#include <core/drawable.h>
-#include <core/drawable-stack.h>
-#include <core/key.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/sys.h>
-#include <core/image.h>
-#include <core/sprite.h>
-#include <core/state.h>
-#include <core/texture.h>
-#include <core/util.h>
-#include <core/window.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/animation.h>
+#include <mlk/core/core.h>
+#include <mlk/core/event.h>
+#include <mlk/core/game.h>
+#include <mlk/core/drawable.h>
+#include <mlk/core/drawable-stack.h>
+#include <mlk/core/key.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/sys.h>
+#include <mlk/core/image.h>
+#include <mlk/core/sprite.h>
+#include <mlk/core/state.h>
+#include <mlk/core/texture.h>
+#include <mlk/core/util.h>
+#include <mlk/core/window.h>
 
 #include <ui/label.h>
 #include <ui/theme.h>
--- a/examples/example-font/example-font.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example-font/example-font.c	Sat Oct 15 20:23:14 2022 +0200
@@ -16,17 +16,17 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <core/core.h>
-#include <core/event.h>
-#include <core/font.h>
-#include <core/game.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/state.h>
-#include <core/sys.h>
-#include <core/texture.h>
-#include <core/util.h>
-#include <core/window.h>
+#include <mlk/core/core.h>
+#include <mlk/core/event.h>
+#include <mlk/core/font.h>
+#include <mlk/core/game.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/state.h>
+#include <mlk/core/sys.h>
+#include <mlk/core/texture.h>
+#include <mlk/core/util.h>
+#include <mlk/core/window.h>
 
 #include <ui/theme.h>
 #include <ui/ui.h>
--- a/examples/example-gridmenu/example-gridmenu.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example-gridmenu/example-gridmenu.c	Sat Oct 15 20:23:14 2022 +0200
@@ -16,16 +16,16 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <core/core.h>
-#include <core/event.h>
-#include <core/game.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/state.h>
-#include <core/sys.h>
-#include <core/trace.h>
-#include <core/util.h>
-#include <core/window.h>
+#include <mlk/core/core.h>
+#include <mlk/core/event.h>
+#include <mlk/core/game.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/state.h>
+#include <mlk/core/sys.h>
+#include <mlk/core/trace.h>
+#include <mlk/core/util.h>
+#include <mlk/core/window.h>
 
 #include <ui/align.h>
 #include <ui/gridmenu.h>
--- a/examples/example-label/example-label.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example-label/example-label.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,15 +18,15 @@
 
 #include <stddef.h>
 
-#include <core/core.h>
-#include <core/event.h>
-#include <core/game.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/state.h>
-#include <core/sys.h>
-#include <core/util.h>
-#include <core/window.h>
+#include <mlk/core/core.h>
+#include <mlk/core/event.h>
+#include <mlk/core/game.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/state.h>
+#include <mlk/core/sys.h>
+#include <mlk/core/util.h>
+#include <mlk/core/window.h>
 
 #include <ui/align.h>
 #include <ui/label.h>
--- a/examples/example-message/example-message.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example-message/example-message.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,15 +18,15 @@
 
 #include <stddef.h>
 
-#include <core/core.h>
-#include <core/event.h>
-#include <core/game.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/state.h>
-#include <core/sys.h>
-#include <core/util.h>
-#include <core/window.h>
+#include <mlk/core/core.h>
+#include <mlk/core/event.h>
+#include <mlk/core/game.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/state.h>
+#include <mlk/core/sys.h>
+#include <mlk/core/util.h>
+#include <mlk/core/window.h>
 
 #include <ui/frame.h>
 #include <ui/theme.h>
--- a/examples/example-notify/example-notify.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example-notify/example-notify.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,16 +18,16 @@
 
 #include <assert.h>
 
-#include <core/core.h>
-#include <core/event.h>
-#include <core/game.h>
-#include <core/image.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/state.h>
-#include <core/texture.h>
-#include <core/util.h>
-#include <core/window.h>
+#include <mlk/core/core.h>
+#include <mlk/core/event.h>
+#include <mlk/core/game.h>
+#include <mlk/core/image.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/state.h>
+#include <mlk/core/texture.h>
+#include <mlk/core/util.h>
+#include <mlk/core/window.h>
 
 #include <ui/notify.h>
 #include <ui/label.h>
--- a/examples/example-sprite/example-sprite.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example-sprite/example-sprite.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,20 +18,20 @@
 
 #include <stdio.h>
 
-#include <core/core.h>
-#include <core/event.h>
-#include <core/game.h>
-#include <core/image.h>
-#include <core/key.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/image.h>
-#include <core/sprite.h>
-#include <core/state.h>
-#include <core/sys.h>
-#include <core/texture.h>
-#include <core/util.h>
-#include <core/window.h>
+#include <mlk/core/core.h>
+#include <mlk/core/event.h>
+#include <mlk/core/game.h>
+#include <mlk/core/image.h>
+#include <mlk/core/key.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/image.h>
+#include <mlk/core/sprite.h>
+#include <mlk/core/state.h>
+#include <mlk/core/sys.h>
+#include <mlk/core/texture.h>
+#include <mlk/core/util.h>
+#include <mlk/core/window.h>
 
 #include <ui/align.h>
 #include <ui/label.h>
--- a/examples/example-ui/example-ui.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example-ui/example-ui.c	Sat Oct 15 20:23:14 2022 +0200
@@ -16,16 +16,16 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <core/core.h>
-#include <core/event.h>
-#include <core/game.h>
-#include <core/maths.h>
-#include <core/panic.h>
-#include <core/painter.h>
-#include <core/state.h>
-#include <core/sys.h>
-#include <core/util.h>
-#include <core/window.h>
+#include <mlk/core/core.h>
+#include <mlk/core/event.h>
+#include <mlk/core/game.h>
+#include <mlk/core/maths.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/state.h>
+#include <mlk/core/sys.h>
+#include <mlk/core/util.h>
+#include <mlk/core/window.h>
 
 #include <ui/align.h>
 #include <ui/button.h>
--- a/examples/example/registry.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example/registry.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,10 +18,10 @@
 
 #include <stddef.h>
 
-#include <core/image.h>
-#include <core/panic.h>
-#include <core/util.h>
-#include <core/sys.h>
+#include <mlk/core/image.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/util.h>
+#include <mlk/core/sys.h>
 
 #include <assets/images/battle-background.h>
 #include <assets/images/black-cat.h>
--- a/examples/example/registry.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example/registry.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,9 +19,9 @@
 #ifndef EXAMPLES_BATTLE_REGISTRY_H
 #define EXAMPLES_BATTLE_REGISTRY_H
 
-#include <core/sound.h>
-#include <core/sprite.h>
-#include <core/texture.h>
+#include <mlk/core/sound.h>
+#include <mlk/core/sprite.h>
+#include <mlk/core/texture.h>
 
 enum registry_texture {
 	/* UI. */
--- a/examples/example/spell-fire.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example/spell-fire.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,10 +18,10 @@
 
 #include <stdlib.h>
 
-#include <core/action.h>
-#include <core/animation.h>
-#include <core/drawable.h>
-#include <core/alloc.h>
+#include <mlk/core/action.h>
+#include <mlk/core/animation.h>
+#include <mlk/core/drawable.h>
+#include <mlk/core/alloc.h>
 
 #include <ui/align.h>
 
--- a/examples/example/trace_hud.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/examples/example/trace_hud.c	Sat Oct 15 20:23:14 2022 +0200
@@ -20,10 +20,10 @@
 #include <stdio.h>
 #include <string.h>
 
-#include <core/action.h>
-#include <core/font.h>
-#include <core/trace.h>
-#include <core/window.h>
+#include <mlk/core/action.h>
+#include <mlk/core/font.h>
+#include <mlk/core/trace.h>
+#include <mlk/core/window.h>
 
 #include <ui/label.h>
 #include <ui/theme.h>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/action-stack.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,135 @@
+/*
+ * action-stack.h -- convenient stack of actions
+ *
+ * Copyright (c) 2020-2022 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 <string.h>
+
+#include "action-stack.h"
+#include "action.h"
+#include "err.h"
+
+#define ACTION_FOREACH(st, iter) \
+	for (size_t i = 0; i < (st)->actionsz && ((iter) = (st)->actions[i], 1); ++i)
+
+void
+action_stack_init(struct action_stack *st, struct action **actions, size_t actionsz)
+{
+	assert(st);
+
+	st->actions = actions;
+	st->actionsz = actionsz;
+
+	for (size_t i = 0; i < st->actionsz; ++i)
+		st->actions[i] = NULL;
+}
+
+int
+action_stack_add(struct action_stack *st, struct action *act)
+{
+	assert(st);
+	assert(act);
+
+	for (size_t i = 0; i < st->actionsz; ++i) {
+		if (!st->actions[i]) {
+			st->actions[i] = act;
+			return 0;
+		}
+	}
+
+	return ERR_NO_MEM;
+}
+
+void
+action_stack_handle(struct action_stack *st, const union event *ev)
+{
+	assert(st);
+	assert(ev);
+
+	struct action *act;
+
+	ACTION_FOREACH(st, act)
+		if (act)
+			action_handle(act, ev);
+}
+
+int
+action_stack_update(struct action_stack *st, unsigned int ticks)
+{
+	assert(st);
+
+	struct action *act;
+
+	for (size_t i = 0; i < st->actionsz; ++i) {
+		act = st->actions[i];
+
+		if (act && action_update(act, ticks)) {
+			action_end(act);
+			action_finish(act);
+			st->actions[i] = NULL;
+		}
+	}
+
+	/*
+	 * We process all actions again in case the user modified the stack
+	 * within their update function.
+	 */
+	return action_stack_completed(st);
+}
+
+void
+action_stack_draw(const struct action_stack *st)
+{
+	assert(st);
+
+	struct action *act;
+
+	ACTION_FOREACH(st, act)
+		if (act)
+			action_draw(act);
+}
+
+int
+action_stack_completed(const struct action_stack *st)
+{
+	assert(st);
+
+	struct action *act;
+
+	ACTION_FOREACH(st, act)
+		if (act)
+			return 0;
+
+	return 1;
+}
+
+void
+action_stack_finish(struct action_stack *st)
+{
+	assert(st);
+
+	struct action *act;
+
+	ACTION_FOREACH(st, act) {
+		if (act) {
+			action_end(act);
+			action_finish(act);
+		}
+	}
+
+	memset(st, 0, sizeof (*st));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/action-stack.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,58 @@
+/*
+ * action-stack.h -- convenient stack of actions
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_ACTION_STACK_H
+#define MLK_CORE_ACTION_STACK_H
+
+#include <stddef.h>
+
+#include "core.h"
+
+union event;
+
+struct action_stack {
+	struct action **actions;
+	size_t actionsz;
+};
+
+CORE_BEGIN_DECLS
+
+void
+action_stack_init(struct action_stack *, struct action **, size_t);
+
+int
+action_stack_add(struct action_stack *, struct action *);
+
+void
+action_stack_handle(struct action_stack *, const union event *);
+
+int
+action_stack_update(struct action_stack *, unsigned int);
+
+void
+action_stack_draw(const struct action_stack *);
+
+int
+action_stack_completed(const struct action_stack *);
+
+void
+action_stack_finish(struct action_stack *);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_ACTION_STACK_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/action.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,70 @@
+/*
+ * action.c -- action states
+ *
+ * Copyright (c) 2020-2022 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 "action.h"
+
+void
+action_handle(struct action *act, const union event *ev)
+{
+	assert(act);
+	assert(ev);
+
+	if (act->handle)
+		act->handle(act, ev);
+}
+
+int
+action_update(struct action *act, unsigned int ticks)
+{
+	assert(act);
+
+	if (act->update)
+		return act->update(act, ticks);
+
+	/* No function means immortal action. */
+	return 0;
+}
+
+void
+action_draw(struct action *act)
+{
+	assert(act);
+
+	if (act->draw)
+		act->draw(act);
+}
+
+void
+action_end(struct action *act)
+{
+	assert(act);
+
+	if (act->end)
+		act->end(act);
+}
+
+void
+action_finish(struct action *act)
+{
+	assert(act);
+
+	if (act->finish)
+		act->finish(act);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/action.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,54 @@
+/*
+ * action.h -- action states
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_ACTION_H
+#define MLK_CORE_ACTION_H
+
+#include "core.h"
+
+union event;
+
+struct action {
+	void *data;
+	void (*handle)(struct action *, const union event *);
+	int (*update)(struct action *, unsigned int);
+	void (*draw)(struct action *);
+	void (*end)(struct action *);
+	void (*finish)(struct action *);
+};
+
+CORE_BEGIN_DECLS
+
+void
+action_handle(struct action *, const union event *);
+
+int
+action_update(struct action *, unsigned int);
+
+void
+action_draw(struct action *);
+
+void
+action_end(struct action *);
+
+void
+action_finish(struct action *);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_ACTION_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/alloc.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,237 @@
+/*
+ * alloc.h -- custom allocators
+ *
+ * Copyright (c) 2020-2022 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 <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <SDL.h>
+
+#include "alloc.h"
+#include "buf.h"
+#include "error.h"
+#include "panic.h"
+
+static void *
+panic_alloc(size_t size)
+{
+	void *mem;
+
+	if (!(mem = malloc(size)))
+		panicf("%s", strerror(errno));
+
+	return mem;
+}
+
+static void *
+panic_realloc(void *ptr, size_t size)
+{
+	void *mem;
+
+	if (!(mem = realloc(ptr, size)) && size != 0)
+		panicf("%s", strerror(errno));
+
+	return mem;
+}
+
+static const struct alloc_funcs default_alloc_funcs = {
+	.alloc = panic_alloc,
+	.realloc = panic_realloc,
+	.free = free
+};
+
+static const struct alloc_funcs *funcs = &default_alloc_funcs;
+
+void
+alloc_set(const struct alloc_funcs *newfuncs)
+{
+	assert(funcs);
+	assert(funcs->alloc);
+	assert(funcs->realloc);
+	assert(funcs->free);
+
+	funcs = newfuncs;
+
+	/* Change SDL allocators as well. */
+	SDL_SetMemoryFunctions(alloc_new, alloc_array0, alloc_renew, free);
+}
+
+void *
+alloc_new(size_t size)
+{
+	assert(size != 0);
+
+	return funcs->alloc(size);
+}
+
+void *
+alloc_new0(size_t size)
+{
+	assert(size != 0);
+
+	return memset(funcs->alloc(size), 0, size);
+}
+
+void *
+alloc_array(size_t len, size_t elemsize)
+{
+	assert(len != 0);
+	assert(elemsize != 0);
+
+	return funcs->alloc(len * elemsize);
+}
+
+void *
+alloc_array0(size_t len, size_t elemsize)
+{
+	assert(len != 0);
+	assert(elemsize != 0);
+
+	return alloc_new0(len * elemsize);
+}
+
+void *
+alloc_renew(void *ptr, size_t size)
+{
+	return funcs->realloc(ptr, size);
+}
+
+void *
+alloc_rearray(void *ptr, size_t len, size_t elemsize)
+{
+	assert(elemsize != 0);
+
+	return funcs->realloc(ptr, len * elemsize);
+}
+
+void *
+alloc_rearray0(void *ptr, size_t oldlen, size_t newlen, size_t elemsize)
+{
+	ptr = funcs->realloc(ptr, newlen * elemsize);
+
+	if (newlen > oldlen)
+		memset((unsigned char *)ptr + (oldlen * elemsize), 0, (newlen - oldlen) * elemsize);
+
+	return ptr;
+}
+
+void *
+alloc_dup(const void *ptr, size_t size)
+{
+	assert(ptr);
+	assert(size != 0);
+
+	return memcpy(funcs->alloc(size), ptr, size);
+}
+
+char *
+alloc_sdup(const char *src)
+{
+	assert(src);
+
+	size_t len = strlen(src) + 1;
+
+	return memcpy(funcs->alloc(len), src, len);
+}
+
+char *
+alloc_sdupf(const char *fmt, ...)
+{
+	struct buf buf = {0};
+	va_list ap;
+
+	va_start(ap, fmt);
+	buf_vprintf(&buf, fmt, ap);
+	va_end(ap);
+
+	return buf.data;
+}
+
+void
+alloc_free(void *ptr)
+{
+	funcs->free(ptr);
+}
+
+void
+alloc_pool_init(struct alloc_pool *pool, size_t elemsize, void (*finalizer)(void *))
+{
+	assert(pool);
+	assert(elemsize != 0);
+
+	pool->data = alloc_array(ALLOC_POOL_INIT_DEFAULT, elemsize);
+	pool->elemsize = elemsize;
+	pool->size = 0;
+	pool->capacity = ALLOC_POOL_INIT_DEFAULT;
+	pool->finalizer = finalizer;
+}
+
+void *
+alloc_pool_new(struct alloc_pool *pool)
+{
+	assert(pool);
+
+	if (pool->size >= pool->capacity) {
+		pool->capacity *= 2;
+		pool->data = alloc_rearray(pool->data, pool->capacity, pool->elemsize);
+	}
+
+	return ((unsigned char *)pool->data) + pool->size++ * pool->elemsize;
+}
+
+void *
+alloc_pool_get(const struct alloc_pool *pool, size_t index)
+{
+	assert(pool);
+	assert(index < pool->size);
+
+	return ((unsigned char *)pool->data) + index * pool->elemsize;
+}
+
+void *
+alloc_pool_shrink(struct alloc_pool *pool)
+{
+	assert(pool);
+
+	void *ptr;
+
+	ptr = alloc_rearray(pool->data, pool->size, pool->elemsize);
+	memset(pool, 0, sizeof (*pool));
+
+	return ptr;
+}
+
+void
+alloc_pool_finish(struct alloc_pool *pool)
+{
+	unsigned char *tab;
+
+	if (!pool)
+		return;
+
+	if (pool->finalizer) {
+		tab = pool->data;
+
+		for (size_t i = 0; i < pool->size; ++i)
+			pool->finalizer(tab + i * pool->elemsize);
+	}
+
+	free(pool->data);
+	memset(pool, 0, sizeof (*pool));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/alloc.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,103 @@
+/*
+ * alloc.h -- custom allocators
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_ALLOC_H
+#define MLK_CORE_ALLOC_H
+
+#include <stddef.h>
+
+#include "core.h"
+#include "util.h"
+
+/* Must be power of 2. */
+#define ALLOC_POOL_INIT_DEFAULT (32)
+
+/* Custom allocator. */
+struct alloc_funcs {
+	void *(*alloc)(size_t);
+	void *(*realloc)(void *, size_t);
+	void (*free)(void *);
+};
+
+/* Minimalist growable array for loading data. */
+struct alloc_pool {
+	void *data;
+	size_t elemsize;
+	size_t size;
+	size_t capacity;
+	void (*finalizer)(void *);
+};
+
+CORE_BEGIN_DECLS
+
+/* allocator functions. */
+void
+alloc_set(const struct alloc_funcs *);
+
+void *
+alloc_new(size_t);
+
+void *
+alloc_new0(size_t);
+
+void *
+alloc_array(size_t, size_t);
+
+void *
+alloc_array0(size_t, size_t);
+
+void *
+alloc_renew(void *, size_t);
+
+void *
+alloc_rearray(void *, size_t, size_t);
+
+void *
+alloc_rearray0(void *, size_t, size_t, size_t);
+
+void *
+alloc_dup(const void *, size_t);
+
+char *
+alloc_sdup(const char *);
+
+char *
+alloc_sdupf(const char *, ...);
+
+void
+alloc_free(void *);
+
+/* alloc_pool functions. */
+void
+alloc_pool_init(struct alloc_pool *, size_t , void (*)(void *));
+
+void *
+alloc_pool_new(struct alloc_pool *);
+
+void *
+alloc_pool_get(const struct alloc_pool *, size_t);
+
+void *
+alloc_pool_shrink(struct alloc_pool *);
+
+void
+alloc_pool_finish(struct alloc_pool *);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_ALLOC_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/animation.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,120 @@
+/*
+ * animation.c -- basic animations
+ *
+ * Copyright (c) 2020-2022 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 <string.h>
+
+#include "drawable.h"
+#include "animation.h"
+#include "sprite.h"
+
+static int
+update(struct drawable *dw, unsigned int ticks)
+{
+	return animation_update(dw->data, ticks);
+}
+
+static void
+draw(struct drawable *dw)
+{
+	animation_draw(dw->data, dw->x, dw->y);
+}
+
+void
+animation_init(struct animation *an, const struct sprite *sprite, unsigned int delay)
+{
+	assert(an);
+	assert(sprite);
+
+	an->sprite = sprite;
+	an->row = 0;
+	an->column = 0;
+	an->delay = delay;
+	an->elapsed = 0;
+}
+
+void
+animation_start(struct animation *an)
+{
+	assert(an);
+
+	an->row = 0;
+	an->column = 0;
+	an->elapsed = 0;
+}
+
+int
+animation_completed(const struct animation *an)
+{
+	assert(an);
+
+	return an->elapsed >= an->delay &&
+	       an->row >= an->sprite->nrows &&
+	       an->column >= an->sprite->ncols;
+}
+
+int
+animation_update(struct animation *an, unsigned int ticks)
+{
+	assert(an);
+
+	an->elapsed += ticks;
+
+	if (an->elapsed < an->delay)
+		return 0;
+
+	/* Increment column first */
+	if (++an->column >= an->sprite->ncols) {
+		/*
+		 * Increment row, if we reach the last row it means we are
+		 * at the last frame.
+		 */
+		if (++an->row >= an->sprite->nrows)
+			an->row = an->sprite->nrows;
+		else
+			an->column = an->elapsed = 0;
+	} else
+		an->elapsed = 0;
+
+	return animation_completed(an);
+}
+
+int
+animation_draw(const struct animation *an, int x, int y)
+{
+	assert(an);
+
+	return sprite_draw(an->sprite, an->row, an->column, x, y);
+}
+
+void
+animation_drawable(struct animation *an, struct drawable *dw, int x, int y)
+{
+	assert(an);
+	assert(dw);
+
+	memset(dw, 0, sizeof (*dw));
+	
+	dw->data = an;
+	dw->x = x - (an->sprite->cellw / 2);
+	dw->y = y - (an->sprite->cellh / 2);
+	dw->update = update;
+	dw->draw = draw;
+
+	animation_start(an);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/animation.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,57 @@
+/*
+ * animation.h -- basic animations
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_ANIMATION_H
+#define MLK_CORE_ANIMATION_H
+
+#include "core.h"
+
+struct drawable;
+struct sprite;
+
+struct animation {
+	const struct sprite *sprite;
+	unsigned int row;
+	unsigned int column;
+	unsigned int delay;
+	unsigned int elapsed;
+};
+
+CORE_BEGIN_DECLS
+
+void
+animation_init(struct animation *, const struct sprite *, unsigned int);
+
+void
+animation_start(struct animation *);
+
+int
+animation_completed(const struct animation *);
+
+int
+animation_update(struct animation *, unsigned int);
+
+int
+animation_draw(const struct animation *, int, int);
+
+void
+animation_drawable(struct animation *, struct drawable *, int, int);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_ANIMATION_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/buf.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,346 @@
+/*
+ * buf.c -- simple string buffer for C
+ *
+ * Copyright (c) 2019-2022 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 <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "buf.h"
+
+/*
+ * Try to increase the buffer length by a power of two until we have enough
+ * space to fit `desired'.
+ *
+ * Detects overflow and return -1 if happened or reallocation could not
+ * occur.
+ */
+static int
+growdbl(struct buf *b, size_t desired)
+{
+	size_t newcap = b->capacity;
+	void *newptr;
+
+	while (desired > newcap - b->length) {
+		const size_t r = newcap * 2;
+
+		/* Overflow occured. */
+		if (r / newcap != 2) {
+#if defined(ENOMEM)
+			errno = ENOMEM;
+#endif
+			return -1;
+		}
+
+		newcap = r;
+	}
+
+	/* At this step we must have enough room. */
+	assert(newcap - b->length >= desired);
+
+	/* Pretty much impossible to reach but always assume it's possible. */
+	if (newcap == SIZE_MAX) {
+#if defined(ENOMEM)
+		errno = ENOMEM;
+#endif
+		return -1;
+	}
+
+	if (!(newptr = BUF_REALLOC(b->data, newcap + 1)))
+		return -1;
+
+	b->data = newptr;
+	b->capacity = newcap;
+
+	return 0;
+}
+
+/*
+ * Try to allocate just enough space for the `desired' amount of space. This is
+ * only used when the buffer is already too large but hasn't reached SIZE_MAX
+ * yet.
+ *
+ * Returns -1 if allocation failed.
+ */
+static int
+growmin(struct buf *b, size_t desired)
+{
+	size_t newcap;
+	void *newptr;
+
+	if (desired >= SIZE_MAX - b->length) {
+#if defined(ENOMEM)
+		errno = ENOMEM;
+#endif
+		return -1;
+	}
+
+	/* Don't forget to keep what's remaining between capacity and length. */
+	newcap = b->capacity + (desired - (b->capacity - b->length));
+
+	/* Try to reallocate. */
+	if (!(newptr = BUF_REALLOC(b->data, newcap + 1)))
+		return -1;
+
+	b->data = newptr;
+	b->capacity = newcap;
+
+	return 0;
+}
+
+/*
+ * Entry point for reallocating data. Will try to allocate twice until we have
+ * enough room and then only the minimal amount.
+ */
+static int
+grow(struct buf *b, size_t desired)
+{
+	const size_t avail = b->capacity - b->length;
+
+	if (avail >= desired)
+		return 0;
+
+	if (!b->capacity) {
+		if (!(b->data = BUF_MALLOC(desired + 1)))
+			return -1;
+
+		b->capacity = desired;
+	} else if (growdbl(b, desired) < 0 && growmin(b, desired) < 0)
+		return -1;
+
+	return 0;
+}
+
+void
+buf_init(struct buf *b)
+{
+	assert(b);
+
+	memset(b, 0, sizeof (*b));
+}
+
+int
+buf_reserve(struct buf *b, size_t amount)
+{
+	assert(b);
+
+	if (grow(b, amount) < 0)
+		return -1;
+
+	return 0;
+}
+
+int
+buf_resize(struct buf *b, size_t size, char ch)
+{
+	assert(b);
+
+	/* New size is smaller than curren't length, just update it. */
+	if (size < b->length) {
+		b->data[b->length = size] = 0;
+		return 0;
+	}
+
+	/* New size is bigger, data may be reallocated. */
+	if (grow(b, size - b->length) < 0)
+		return -1;
+
+	memset(&b->data[b->length], ch, size - b->length);
+	b->length = size;
+	b->data[b->length] = 0;
+
+	return 0;
+}
+
+int
+buf_shrink(struct buf *b)
+{
+	assert(b);
+
+	void *newptr;
+
+	if (b->length == 0) {
+		free(b->data);
+		b->data = NULL;
+		b->length = b->capacity = 0;
+		return 0;
+	}
+
+	if (!(newptr = BUF_REALLOC(b->data, b->length + 1)))
+		return -1;
+
+	b->data = newptr;
+	b->capacity = b->length;
+
+	return 0;
+}
+
+void
+buf_erase(struct buf *b, size_t pos, size_t count)
+{
+	assert(b);
+	assert(pos <= b->length);
+
+	if (count > b->length - pos) {
+		/* Optimize whole erase at pos. */
+		b->data[pos] = 0;
+		b->length = pos;
+	} else {
+		memmove(&b->data[pos], &b->data[pos + count], b->length - count);
+		b->length -= count;
+	}
+}
+
+int
+buf_putc(struct buf *b, char c)
+{
+	assert(b);
+
+	if (grow(b, 1) < 0)
+		return -1;
+
+	b->data[b->length++] = c;
+	b->data[b->length] = 0;
+
+	return 0;
+}
+
+int
+buf_puts(struct buf *b, const char *s)
+{
+	assert(b);
+	assert(s);
+
+	const size_t len = strlen(s);
+
+	if (grow(b, len) < 0)
+		return -1;
+
+	memcpy(&b->data[b->length], s, len + 1);
+	b->length += len;
+
+	return 0;
+}
+
+int
+buf_printf(struct buf *b, const char *fmt, ...)
+{
+	assert(b);
+	assert(fmt);
+
+	va_list ap;
+	int ret;
+
+	va_start(ap, fmt);
+	ret = buf_vprintf(b, fmt, ap);
+	va_end(ap);
+
+	return ret;
+}
+
+int
+buf_vprintf(struct buf *b, const char *fmt, va_list args)
+{
+	assert(b);
+	assert(fmt);
+
+	va_list ap;
+	int amount;
+
+	/* Determine length. */
+	va_copy(ap, args);
+	amount = vsnprintf(NULL, 0, fmt, ap);
+	va_end(ap);
+
+	if (amount < 0)
+		return -1;
+
+	/* Do actual copy. */
+	if (grow(b, amount) < 0)
+		return -1;
+
+	va_copy(ap, args);
+	amount = vsprintf(&b->data[b->length], fmt, ap);
+	va_end(ap);
+
+	if (amount < 0)
+		return -1;
+
+	b->length += amount;
+
+	return 0;
+}
+
+int
+buf_sub(struct buf *b, const struct buf *src, size_t pos, size_t count)
+{
+	assert(b);
+	assert(src);
+	assert(pos <= src->length);
+
+	if (count >= src->length)
+		count = src->length - pos;
+	if (!(b->data = BUF_MALLOC(count + 1)))
+		return -1;
+
+	strncpy(b->data, &src->data[pos], count);
+	b->length = count;
+	b->capacity = count;
+	b->data[b->length] = 0;
+
+	return 0;
+}
+
+int
+buf_dup(struct buf *b, const struct buf *src)
+{
+	assert(b);
+	assert(src);
+
+	if (!src->data)
+		return 0;
+	if (!(b->data = BUF_MALLOC(src->length + 1)))
+		return -1;
+
+	memcpy(b->data, src->data, src->length + 1);
+	b->capacity = src->length;
+	b->length = src->length;
+
+	return 0;
+}
+
+void
+buf_clear(struct buf *b)
+{
+	assert(b);
+
+	if (b->data)
+		b->data[b->length = 0] = 0;
+}
+
+void
+buf_finish(struct buf *b)
+{
+	assert(b);
+
+	BUF_FREE(b->data);
+	b->data = NULL;
+	b->capacity = b->length = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/buf.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,92 @@
+/*
+ * buf.h -- simple string buffer for C
+ *
+ * Copyright (c) 2019-2022 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.
+ */
+
+#ifndef BUF_H
+#define BUF_H
+
+#include <stdarg.h>
+#include <stddef.h>
+
+#include "alloc.h"
+
+#if !defined(BUF_MALLOC)
+#	define BUF_MALLOC alloc_new
+#endif
+
+#if !defined(BUF_REALLOC)
+#	define BUF_REALLOC alloc_renew
+#endif
+
+#if !defined(BUF_FREE)
+#	define BUF_FREE alloc_free
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct buf {
+	char *data;
+	size_t length;
+	size_t capacity;
+};
+
+void
+buf_init(struct buf *);
+
+int
+buf_reserve(struct buf *, size_t);
+
+int
+buf_resize(struct buf *, size_t, char);
+
+int
+buf_shrink(struct buf *);
+
+void
+buf_erase(struct buf *, size_t, size_t);
+
+int
+buf_putc(struct buf *, char);
+
+int
+buf_puts(struct buf *, const char *);
+
+int
+buf_printf(struct buf *, const char *, ...);
+
+int
+buf_vprintf(struct buf *, const char *, va_list);
+
+int
+buf_sub(struct buf *, const struct buf *, size_t, size_t);
+
+int
+buf_dup(struct buf *, const struct buf *);
+
+void
+buf_clear(struct buf *);
+
+void
+buf_finish(struct buf *);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* !BUF_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/clock.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,33 @@
+/*
+ * clock.c -- track elapsed time
+ *
+ * Copyright (c) 2020-2022 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 <SDL.h>
+
+#include "clock.h"
+
+void
+mlk_clock_start(struct mlk_clock *clock)
+{
+	clock->ticks = SDL_GetTicks();
+}
+
+unsigned int
+mlk_clock_elapsed(const struct mlk_clock *clock)
+{
+	return SDL_GetTicks() - clock->ticks;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/clock.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,38 @@
+/*
+ * clock.h -- track elapsed time
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_CLOCK_H
+#define MLK_CORE_CLOCK_H
+
+#include "core.h"
+
+struct mlk_clock {
+	unsigned int ticks;
+};
+
+CORE_BEGIN_DECLS
+
+void
+mlk_clock_start(struct mlk_clock *);
+
+unsigned int
+mlk_clock_elapsed(const struct mlk_clock *);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_CLOCK_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/color.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,32 @@
+/*
+ * color.h -- basic color routines
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_COLOR_H
+#define MLK_CORE_COLOR_H
+
+#define COLOR_R(c)              (c >> 24 & 0xff)
+#define COLOR_G(c)              (c >> 16 & 0xff)
+#define COLOR_B(c)              (c >> 8  & 0xff)
+#define COLOR_A(c)              (c       & 0xff)
+#define COLOR_HEX(r, g, b, a)   \
+        ((r << 24 & 0xff000000) | \
+         (g << 16 & 0x00ff0000) | \
+         (b << 8  & 0x0000ff00) | \
+         (a       & 0x000000ff))
+
+#endif /* !MLK_CORE_COLOR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/core.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,45 @@
+/*
+ * core.c -- libcore main entry
+ *
+ * Copyright (c) 2020-2022 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 <stddef.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "core.h"
+#include "sys.h"
+
+int
+core_init(const char *organization, const char *name)
+{
+	assert(organization);
+	assert(name);
+
+	srand(time(NULL));
+
+	if (sys_init(organization, name) < 0)
+		return -1;
+
+	return 0;
+}
+
+void
+core_finish(void)
+{
+	sys_finish();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/core.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,40 @@
+/*
+ * core.c -- libcore main entry
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_CORE_H
+#define MLK_CORE_CORE_H
+
+#if defined(__cplusplus)
+#       define CORE_BEGIN_DECLS extern "C" {
+#       define CORE_END_DECLS }
+#else
+#       define CORE_BEGIN_DECLS
+#       define CORE_END_DECLS
+#endif
+
+CORE_BEGIN_DECLS
+
+int
+core_init(const char *, const char *);
+
+void
+core_finish(void);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_CORE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/drawable-stack.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,122 @@
+/*
+ * drawable-stack.c -- convenient stack of drawables
+ *
+ * Copyright (c) 2020-2022 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 <string.h>
+
+#include "drawable.h"
+#include "drawable-stack.h"
+#include "err.h"
+
+#define DRAWABLE_FOREACH(st, iter) \
+	for (size_t i = 0; i < (st)->objectsz && ((iter) = (st)->objects[i], 1); ++i)
+
+void
+drawable_stack_init(struct drawable_stack *st, struct drawable **objects, size_t objectsz)
+{
+	assert(st);
+
+	st->objects = objects;
+	st->objectsz = objectsz;
+
+	for (size_t i = 0; i < st->objectsz; ++i)
+		st->objects[i] = NULL;
+}
+
+int
+drawable_stack_add(struct drawable_stack *st, struct drawable *dw)
+{
+	assert(st);
+	assert(dw);
+
+	for (size_t i = 0; i < st->objectsz; ++i) {
+		if (!st->objects[i]) {
+			st->objects[i] = dw;
+			return 0;
+		}
+	}
+
+	return ERR_NO_MEM;
+}
+
+int
+drawable_stack_update(struct drawable_stack *st, unsigned int ticks)
+{
+	assert(st);
+
+	struct drawable *dw;
+
+	for (size_t i = 0; i < st->objectsz; ++i) {
+		dw = st->objects[i];
+
+		if (dw && drawable_update(dw, ticks)) {
+			drawable_end(dw);
+			drawable_finish(dw);
+			st->objects[i] = NULL;
+		}
+	}
+
+	/*
+	 * We process the array again in case a drawable added a new drawable
+	 * within the update function.
+	 */
+	return drawable_stack_completed(st);
+}
+
+void
+drawable_stack_draw(struct drawable_stack *st)
+{
+	assert(st);
+
+	struct drawable *dw;
+
+	DRAWABLE_FOREACH(st, dw)
+		if (dw)
+			drawable_draw(dw);
+}
+
+int
+drawable_stack_completed(const struct drawable_stack *st)
+{
+	assert(st);
+
+	struct drawable *dw;
+
+	DRAWABLE_FOREACH(st, dw)
+		if (dw)
+			return 0;
+
+	return 1;
+}
+
+void
+drawable_stack_finish(struct drawable_stack *st)
+{
+	assert(st);
+
+	struct drawable *dw;
+
+	DRAWABLE_FOREACH(st, dw) {
+		if (dw) {
+			drawable_end(dw);
+			drawable_finish(dw);
+		}
+	}
+
+	memset(st, 0, sizeof (*st));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/drawable-stack.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,53 @@
+/*
+ * drawable-stack.h -- convenient stack of drawables
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_DRAWABLE_STACK_H
+#define MLK_CORE_DRAWABLE_STACK_H
+
+#include <stddef.h>
+
+#include "core.h"
+
+struct drawable_stack {
+	struct drawable **objects;
+	size_t objectsz;
+};
+
+CORE_BEGIN_DECLS
+
+void
+drawable_stack_init(struct drawable_stack *, struct drawable **, size_t);
+
+int
+drawable_stack_add(struct drawable_stack *, struct drawable *);
+
+int
+drawable_stack_update(struct drawable_stack *, unsigned int);
+
+void
+drawable_stack_draw(struct drawable_stack *);
+
+int
+drawable_stack_completed(const struct drawable_stack *);
+
+void
+drawable_stack_finish(struct drawable_stack *);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_DRAWABLE_STACK_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/drawable.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,55 @@
+/*
+ * drawable.c -- automatic drawable objects
+ *
+ * Copyright (c) 2020-2022 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 "drawable.h"
+
+int
+drawable_update(struct drawable *dw, unsigned int ticks)
+{
+	assert(dw);
+
+	return dw->update(dw, ticks);
+}
+
+void
+drawable_draw(struct drawable *dw)
+{
+	assert(dw);
+
+	dw->draw(dw);
+}
+
+void
+drawable_end(struct drawable *dw)
+{
+	assert(dw);
+
+	if (dw->end)
+		dw->end(dw);
+}
+
+void
+drawable_finish(struct drawable *dw)
+{
+	assert(dw);
+
+	if (dw->finish)
+		dw->finish(dw);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/drawable.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,50 @@
+/*
+ * drawable.h -- automatic drawable objects
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_DRAWABLE_H
+#define MLK_CORE_DRAWABLE_H
+
+#include "core.h"
+
+struct drawable {
+	void *data;
+	int x;
+	int y;
+	int (*update)(struct drawable *, unsigned int);
+	void (*draw)(struct drawable *);
+	void (*end)(struct drawable *);
+	void (*finish)(struct drawable *);
+};
+
+CORE_BEGIN_DECLS
+
+int
+drawable_update(struct drawable *, unsigned int);
+
+void
+drawable_draw(struct drawable *);
+
+void
+drawable_end(struct drawable *);
+
+void
+drawable_finish(struct drawable *);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_DRAWABLE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/err.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,36 @@
+/*
+ * err.h -- error routines
+ *
+ * Copyright (c) 2020-2022 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 <SDL.h>
+
+#include "err.h"
+
+const char *
+err_string(int e)
+{
+	switch (e) {
+	case ERR_SDL:
+		return SDL_GetError();
+	case ERR_NO_MEM:
+		return "out of memory";
+	case ERR_NO_SUPPORT:
+		return "operation not supported";
+	default:
+		return "no error";
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/err.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,30 @@
+/*
+ * err.h -- error handing
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_ERR_H
+#define MLK_ERR_H
+
+#define ERR_NONE         0
+#define ERR_SDL         -1
+#define ERR_NO_MEM      -2
+#define ERR_NO_SUPPORT  -3
+
+const char *
+err_string(int e);
+
+#endif /* !MLK_ERROR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/error.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,56 @@
+/*
+ * error.c -- error routines
+ *
+ * Copyright (c) 2020-2022 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 <stdio.h>
+
+#include "error.h"
+
+#include <SDL.h>
+
+static char buffer[2048];
+
+const char *
+error(void)
+{
+	return buffer;
+}
+
+int
+errorf(const char *fmt, ...)
+{
+	assert(fmt);
+
+	va_list ap;
+
+	va_start(ap, fmt);
+	errorva(fmt, ap);
+	va_end(ap);
+
+	return -1;
+}
+
+int
+errorva(const char *fmt, va_list ap)
+{
+	assert(fmt);
+
+	vsnprintf(buffer, sizeof (buffer), fmt, ap);
+
+	return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/error.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,39 @@
+/*
+ * error.h -- error routines
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_ERROR_H
+#define MLK_CORE_ERROR_H
+
+#include <stdarg.h>
+
+#include "core.h"
+
+CORE_BEGIN_DECLS
+
+const char *
+error(void);
+
+int
+errorf(const char *, ...);
+
+int
+errorva(const char *, va_list);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_ERROR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/event.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,256 @@
+/*
+ * event.c -- event management
+ *
+ * Copyright (c) 2020-2022 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 <SDL.h>
+
+#include "event.h"
+
+/* Maintain with enum key constants in key.h */
+static const struct {
+	SDL_Keycode key;
+	enum key value;
+} keymap[] = {
+	{ SDLK_RETURN,          KEY_ENTER               },
+	{ SDLK_ESCAPE,          KEY_ESCAPE              },
+	{ SDLK_BACKSPACE,       KEY_BACKSPACE           },
+	{ SDLK_TAB,             KEY_TAB                 },
+	{ SDLK_SPACE,           KEY_SPACE               },
+	{ SDLK_EXCLAIM,         KEY_EXCLAIM             },
+	{ SDLK_QUOTEDBL,        KEY_DOUBLE_QUOTE        },
+	{ SDLK_HASH,            KEY_HASH                },
+	{ SDLK_PERCENT,         KEY_PERCENT             },
+	{ SDLK_DOLLAR,          KEY_DOLLAR              },
+	{ SDLK_AMPERSAND,       KEY_AMPERSAND           },
+	{ SDLK_QUOTE,           KEY_QUOTE               },
+	{ SDLK_LEFTPAREN,       KEY_LEFT_PAREN          },
+	{ SDLK_RIGHTPAREN,      KEY_RIGHT_PAREN         },
+	{ SDLK_ASTERISK,        KEY_ASTERISK            },
+	{ SDLK_PLUS,            KEY_PLUS                },
+	{ SDLK_COMMA,           KEY_COMMA               },
+	{ SDLK_MINUS,           KEY_MINUS               },
+	{ SDLK_PERIOD,          KEY_PERIOD              },
+	{ SDLK_SLASH,           KEY_SLASH               },
+	{ SDLK_0,               KEY_0                   },
+	{ SDLK_1,               KEY_1                   },
+	{ SDLK_2,               KEY_2                   },
+	{ SDLK_3,               KEY_3                   },
+	{ SDLK_4,               KEY_4                   },
+	{ SDLK_5,               KEY_5                   },
+	{ SDLK_6,               KEY_6                   },
+	{ SDLK_7,               KEY_7                   },
+	{ SDLK_8,               KEY_8                   },
+	{ SDLK_9,               KEY_9                   },
+	{ SDLK_COLON,           KEY_COLON               },
+	{ SDLK_SEMICOLON,       KEY_SEMICOLON           },
+	{ SDLK_LESS,            KEY_LESS                },
+	{ SDLK_EQUALS,          KEY_EQUALS              },
+	{ SDLK_GREATER,         KEY_GREATER             },
+	{ SDLK_QUESTION,        KEY_QUESTION            },
+	{ SDLK_AT,              KEY_AT                  },
+	{ SDLK_LEFTBRACKET,     KEY_LEFT_BRACKET        },
+	{ SDLK_BACKSLASH,       KEY_BACKSLASH           },
+	{ SDLK_RIGHTBRACKET,    KEY_RIGHT_BRACKET       },
+	{ SDLK_CARET,           KEY_CARET               },
+	{ SDLK_UNDERSCORE,      KEY_UNDERSCORE          },
+	{ SDLK_BACKQUOTE,       KEY_BACKQUOTE           },
+	{ SDLK_a,               KEY_a                   },
+	{ SDLK_b,               KEY_b                   },
+	{ SDLK_c,               KEY_c                   },
+	{ SDLK_d,               KEY_d                   },
+	{ SDLK_e,               KEY_e                   },
+	{ SDLK_f,               KEY_f                   },
+	{ SDLK_g,               KEY_g                   },
+	{ SDLK_h,               KEY_h                   },
+	{ SDLK_i,               KEY_i                   },
+	{ SDLK_j,               KEY_j                   },
+	{ SDLK_k,               KEY_k                   },
+	{ SDLK_l,               KEY_l                   },
+	{ SDLK_m,               KEY_m                   },
+	{ SDLK_n,               KEY_n                   },
+	{ SDLK_o,               KEY_o                   },
+	{ SDLK_p,               KEY_p                   },
+	{ SDLK_q,               KEY_q                   },
+	{ SDLK_r,               KEY_r                   },
+	{ SDLK_s,               KEY_s                   },
+	{ SDLK_t,               KEY_t                   },
+	{ SDLK_u,               KEY_u                   },
+	{ SDLK_v,               KEY_v                   },
+	{ SDLK_w,               KEY_w                   },
+	{ SDLK_x,               KEY_x                   },
+	{ SDLK_y,               KEY_y                   },
+	{ SDLK_z,               KEY_z                   },
+	{ SDLK_CAPSLOCK,        KEY_CAPSLOCK            },
+	{ SDLK_F1,              KEY_F1                  },
+	{ SDLK_F2,              KEY_F2                  },
+	{ SDLK_F3,              KEY_F3                  },
+	{ SDLK_F4,              KEY_F4                  },
+	{ SDLK_F5,              KEY_F5                  },
+	{ SDLK_F6,              KEY_F6                  },
+	{ SDLK_F7,              KEY_F7                  },
+	{ SDLK_F8,              KEY_F8                  },
+	{ SDLK_F9,              KEY_F9                  },
+	{ SDLK_F10,             KEY_F10                 },
+	{ SDLK_F11,             KEY_F11                 },
+	{ SDLK_F12,             KEY_F12                 },
+	{ SDLK_F13,             KEY_F13                 },
+	{ SDLK_F14,             KEY_F14                 },
+	{ SDLK_F15,             KEY_F15                 },
+	{ SDLK_F16,             KEY_F16                 },
+	{ SDLK_F17,             KEY_F17                 },
+	{ SDLK_F18,             KEY_F18                 },
+	{ SDLK_F19,             KEY_F19                 },
+	{ SDLK_F20,             KEY_F20                 },
+	{ SDLK_F21,             KEY_F21                 },
+	{ SDLK_F22,             KEY_F22                 },
+	{ SDLK_F23,             KEY_F23                 },
+	{ SDLK_F24,             KEY_F24                 },
+	{ SDLK_PRINTSCREEN,     KEY_PRINTSCREEN         },
+	{ SDLK_SCROLLLOCK,      KEY_SCROLL_LOCK         },
+	{ SDLK_PAUSE,           KEY_PAUSE               },
+	{ SDLK_INSERT,          KEY_INSERT              },
+	{ SDLK_HOME,            KEY_HOME                },
+	{ SDLK_PAGEUP,          KEY_PAGEUP              },
+	{ SDLK_DELETE,          KEY_DELETE              },
+	{ SDLK_END,             KEY_END                 },
+	{ SDLK_PAGEDOWN,        KEY_PAGEDOWN            },
+	{ SDLK_RIGHT,           KEY_RIGHT               },
+	{ SDLK_LEFT,            KEY_LEFT                },
+	{ SDLK_DOWN,            KEY_DOWN                },
+	{ SDLK_UP,              KEY_UP                  },
+	{ SDLK_KP_DIVIDE,       KEY_KP_DIVIDE           },
+	{ SDLK_KP_MULTIPLY,     KEY_KP_MULTIPLY         },
+	{ SDLK_KP_MINUS,        KEY_KP_MINUS            },
+	{ SDLK_KP_PLUS,         KEY_KP_PLUS             },
+	{ SDLK_KP_ENTER,        KEY_KP_ENTER            },
+	{ SDLK_KP_1,            KEY_KP_1                },
+	{ SDLK_KP_2,            KEY_KP_2                },
+	{ SDLK_KP_3,            KEY_KP_3                },
+	{ SDLK_KP_4,            KEY_KP_4                },
+	{ SDLK_KP_5,            KEY_KP_5                },
+	{ SDLK_KP_6,            KEY_KP_6                },
+	{ SDLK_KP_7,            KEY_KP_7                },
+	{ SDLK_KP_8,            KEY_KP_8                },
+	{ SDLK_KP_9,            KEY_KP_9                },
+	{ SDLK_KP_0,            KEY_KP_0                },
+	{ SDLK_KP_PERIOD,       KEY_KP_PERIOD           },
+	{ SDLK_KP_COMMA,        KEY_KP_COMMA            },
+	{ SDLK_MENU,            KEY_MENU                },
+	{ SDLK_MUTE,            KEY_MUTE                },
+	{ SDLK_VOLUMEUP,        KEY_VOLUME_UP           },
+	{ SDLK_VOLUMEDOWN,      KEY_VOLUME_DOWN         },
+	{ SDLK_LCTRL,           KEY_LCTRL               },
+	{ SDLK_LSHIFT,          KEY_LSHIFT              },
+	{ SDLK_LALT,            KEY_LALT                },
+	{ SDLK_LGUI,            KEY_LSUPER              },
+	{ SDLK_RCTRL,           KEY_RCTRL               },
+	{ SDLK_RSHIFT,          KEY_RSHIFT              },
+	{ SDLK_RALT,            KEY_RALT                },
+	{ SDLK_RGUI,            KEY_RSUPER              },
+	{ 0,                    -1                      }
+};
+
+/* Maintain with enum mouse_button constants in mouse.h */
+static const struct {
+	int key;
+	enum mouse_button value;
+} buttons[] = {
+	{ SDL_BUTTON_LEFT,      MOUSE_BUTTON_LEFT       },
+	{ SDL_BUTTON_MIDDLE,    MOUSE_BUTTON_MIDDLE     },
+	{ SDL_BUTTON_RIGHT,     MOUSE_BUTTON_RIGHT      },
+	{ -1,                   MOUSE_BUTTON_NONE       }
+};
+
+static void
+convert_key(const SDL_Event *event, union event *ev)
+{
+	ev->type = event->type == SDL_KEYDOWN ? EVENT_KEYDOWN : EVENT_KEYUP;
+	ev->key.key = KEY_UNKNOWN;
+
+	for (size_t i = 0; keymap[i].key != 0; ++i) {
+		if (keymap[i].key == event->key.keysym.sym) {
+			ev->key.key = keymap[i].value;
+			break;
+		}
+	}
+}
+
+static void
+convert_mouse(const SDL_Event *event, union event *ev)
+{
+	ev->type = EVENT_MOUSE;
+	ev->mouse.buttons = 0;
+	ev->mouse.x = event->motion.x;
+	ev->mouse.y = event->motion.y;
+
+	if (event->motion.state & SDL_BUTTON_LMASK)
+		ev->mouse.buttons |= MOUSE_BUTTON_LEFT;
+	if (event->motion.state & SDL_BUTTON_MMASK)
+		ev->mouse.buttons |= MOUSE_BUTTON_MIDDLE;
+	if (event->motion.state & SDL_BUTTON_RMASK)
+		ev->mouse.buttons |= MOUSE_BUTTON_RIGHT;
+}
+
+static void
+convert_click(const SDL_Event *event, union event *ev)
+{
+	ev->type = event->type == SDL_MOUSEBUTTONDOWN ? EVENT_CLICKDOWN : EVENT_CLICKUP;
+	ev->click.button = MOUSE_BUTTON_NONE;
+	ev->click.x = event->button.x;
+	ev->click.y = event->button.y;
+	ev->click.clicks = event->button.clicks;
+
+	for (size_t i = 0; buttons[i].value != MOUSE_BUTTON_NONE; ++i) {
+		if (buttons[i].key == event->button.button) {
+			ev->click.button = buttons[i].value;
+			break;
+		}
+	}
+}
+
+int
+event_poll(union event *ev)
+{
+	SDL_Event event;
+
+	/*
+	 * Loop until we find an event we want to report, we skip unneeded
+	 * ones.
+	 */
+	while (SDL_PollEvent(&event)) {
+		switch (event.type) {
+		case SDL_QUIT:
+			ev->type = EVENT_QUIT;
+			return 1;
+		case SDL_KEYDOWN:
+		case SDL_KEYUP:
+			convert_key(&event, ev);
+			return 1;
+		case SDL_MOUSEMOTION:
+			convert_mouse(&event, ev);
+			return 1;
+		case SDL_MOUSEBUTTONDOWN:
+		case SDL_MOUSEBUTTONUP:
+			convert_click(&event, ev);
+			return 1;
+		default:
+			continue;
+		}
+	}
+
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/event.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,70 @@
+/*
+ * event.h -- event management
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_EVENT_H
+#define MLK_CORE_EVENT_H
+
+#include "core.h"
+#include "key.h"
+#include "mouse.h"
+
+enum event_type {
+	EVENT_CLICKDOWN,
+	EVENT_CLICKUP,
+	EVENT_KEYDOWN,
+	EVENT_KEYUP,
+	EVENT_MOUSE,
+	EVENT_QUIT,
+	EVENT_NUM
+};
+
+struct event_key {
+	enum event_type type;
+	enum key key;
+};
+
+struct event_mouse {
+	enum event_type type;
+	enum mouse_button buttons;
+	int x;
+	int y;
+};
+
+struct event_click {
+	enum event_type type;
+	enum mouse_button button;
+	int x;
+	int y;
+	unsigned int clicks;
+};
+
+union event {
+	enum event_type type;
+	struct event_key key;
+	struct event_mouse mouse;
+	struct event_click click;
+};
+
+CORE_BEGIN_DECLS
+
+int
+event_poll(union event *);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_EVENT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/font.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,128 @@
+/*
+ * font.c -- basic font management
+ *
+ * Copyright (c) 2020-2022 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 <string.h>
+
+#include <SDL_ttf.h>
+
+#include "color.h"
+#include "err.h"
+#include "error.h"
+#include "font.h"
+#include "texture_p.h"
+#include "util.h"
+
+int
+font_open(struct font *font, const char *path, unsigned int size)
+{
+	assert(font);
+	assert(path);
+
+	if (!(font->handle = TTF_OpenFont(path, size)))
+		return ERR_SDL;
+
+	return 0;
+}
+
+int
+font_openmem(struct font *font, const void *buffer, size_t buflen, unsigned int size)
+{
+	assert(font);
+	assert(buffer);
+
+	SDL_RWops *ops;
+
+	if (!(ops = SDL_RWFromConstMem(buffer, buflen)) ||
+	   (!(font->handle = TTF_OpenFontRW(ops, 1, size))))
+		return ERR_SDL;
+
+	return 0;
+}
+
+int
+font_ok(const struct font *font)
+{
+	return font && font->handle;
+}
+
+int
+font_render(struct font *font, struct texture *tex, const char *text, unsigned long color)
+{
+	assert(font_ok(font));
+	assert(text);
+
+	SDL_Color fg = {
+		.r = COLOR_R(color),
+		.g = COLOR_G(color),
+		.b = COLOR_B(color),
+		.a = COLOR_A(color)
+	};
+	SDL_Surface *surface;
+	SDL_Surface *(*func)(TTF_Font *, const char *, SDL_Color);
+
+	switch (font->style) {
+	case FONT_STYLE_ANTIALIASED:
+		func = TTF_RenderUTF8_Blended;
+		break;
+	default:
+		func = TTF_RenderUTF8_Solid;
+		break;
+	}
+
+	if (!(surface = func(font->handle, text, fg)))
+		return ERR_SDL;
+
+	return texture_from_surface(tex, surface);
+}
+
+unsigned int
+font_height(const struct font *font)
+{
+	assert(font_ok(font));
+
+	return TTF_FontHeight(font->handle);
+}
+
+int
+font_query(const struct font *font, const char *text, unsigned int *w, unsigned int *h)
+{
+	assert(font_ok(font));
+	assert(text);
+
+	if (w)
+		*w = 0;
+	if (h)
+		*h = 0;
+
+	if (TTF_SizeUTF8(font->handle, text, (int *)w, (int *)h) != 0)
+		return ERR_SDL;
+
+	return 0;
+}
+
+void
+font_finish(struct font *font)
+{
+	assert(font);
+
+	if (font->handle)
+		TTF_CloseFont(font->handle);
+
+	memset(font, 0, sizeof (*font));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/font.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,64 @@
+/*
+ * font.h -- basic font management
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_FONT_H
+#define MLK_CORE_FONT_H
+
+#include <stddef.h>
+
+#include "core.h"
+
+struct texture;
+
+enum font_style {
+	FONT_STYLE_ANTIALIASED,
+	FONT_STYLE_NONE,
+	FONT_STYLE_LAST
+};
+
+struct font {
+	enum font_style style;
+	void *handle;
+};
+
+CORE_BEGIN_DECLS
+
+int
+font_open(struct font *, const char *, unsigned int);
+
+int
+font_openmem(struct font *, const void *, size_t, unsigned int);
+
+int
+font_ok(const struct font *);
+
+int
+font_render(struct font *, struct texture *, const char *, unsigned long);
+
+unsigned int
+font_height(const struct font *);
+
+int
+font_query(const struct font *, const char *, unsigned int *, unsigned int *);
+
+void
+font_finish(struct font *);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_FONT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/game.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,140 @@
+/*
+ * game.c -- main game object
+ *
+ * Copyright (c) 2020-2022 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 <string.h>
+
+#include "clock.h"
+#include "event.h"
+#include "game.h"
+#include "state.h"
+#include "util.h"
+#include "window.h"
+
+struct game game = {0};
+
+void
+game_init(struct state **states, size_t statesz)
+{
+	assert(states);
+	assert(statesz);
+
+	memset(&game, 0, sizeof (game));
+
+	game.states = states;
+	game.statesz = statesz;
+
+	for (size_t i = 0; i < game.statesz; ++i)
+		game.states[i] = NULL;
+}
+
+void
+game_push(struct state *state)
+{
+	assert(state);
+	assert(!game.state || game.state != &game.states[game.statesz - 1]);
+
+	if (!game.state) {
+		game.state = &game.states[0];
+		state_start(*game.state = state);
+	} else {
+		state_suspend(*game.state);
+		state_start(*(++game.state) = state);
+	}
+}
+
+void
+game_pop(void)
+{
+	assert(game.state);
+
+	state_end(*game.state);
+	state_finish(*game.state);
+
+	if (game.state == game.states)
+		game.state = NULL;
+	else
+		state_resume(*--game.state);
+}
+
+void
+game_handle(const union event *ev)
+{
+	assert(ev);
+
+	if (*game.state && !(game.inhibit & INHIBIT_STATE_INPUT))
+		state_handle(*game.state, ev);
+}
+
+void
+game_update(unsigned int ticks)
+{
+	if (*game.state && !(game.inhibit & INHIBIT_STATE_UPDATE))
+		state_update(*game.state, ticks);
+}
+
+void
+game_draw(void)
+{
+	if (*game.state && !(game.inhibit & INHIBIT_STATE_DRAW))
+		state_draw(*game.state);
+}
+
+void
+game_loop(void)
+{
+	struct mlk_clock clock = {0};
+	unsigned int elapsed = 0;
+	unsigned int frametime;
+
+	if (window.framerate > 0)
+		frametime = 1000 / window.framerate;
+	else
+		/* Assuming 50.0 FPS. */
+		frametime = 1000.0 / 50.0;
+
+	while (*game.state) {
+		mlk_clock_start(&clock);
+
+		for (union event ev; event_poll(&ev); )
+			game_handle(&ev);
+
+		game_update(elapsed);
+		game_draw();
+
+		/*
+		 * If vsync is enabled, it should have wait, otherwise sleep
+		 * a little to save CPU cycles.
+		 */
+		if ((elapsed = mlk_clock_elapsed(&clock)) < frametime)
+			util_delay(frametime - elapsed);
+
+		elapsed = mlk_clock_elapsed(&clock);
+	}
+}
+
+void
+game_quit(void)
+{
+	for (size_t i = 0; i < game.statesz; ++i) {
+		if (game.states[i])
+			state_finish(game.states[i]);
+
+		game.states[i] = NULL;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/game.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,68 @@
+/*
+ * game.h -- main game object
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_GAME_H
+#define MLK_CORE_GAME_H
+
+#include <stddef.h>
+
+#include "core.h"
+#include "inhibit.h"
+
+struct state;
+
+union event;
+
+struct game {
+	enum inhibit inhibit;
+	struct state **states;
+	size_t statesz;
+	struct state **state;
+};
+
+extern struct game game;
+
+CORE_BEGIN_DECLS
+
+void
+game_init(struct state **, size_t);
+
+void
+game_push(struct state *);
+
+void
+game_pop(void);
+
+void
+game_handle(const union event *);
+
+void
+game_update(unsigned int);
+
+void
+game_draw(void);
+
+void
+game_loop(void);
+
+void
+game_quit(void);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_GAME_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/image.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,68 @@
+/*
+ * image.c -- basic image management
+ *
+ * Copyright (c) 2020-2022 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 <SDL_image.h>
+
+#include "error.h"
+#include "texture.h"
+#include "window.h"
+#include "window_p.h"
+
+static void
+dimensions(struct texture *tex)
+{
+	int w, h;
+
+	if (SDL_QueryTexture(tex->handle, NULL, NULL, &w, &h) < 0)
+		tex->w = tex->h = 0;
+	else {
+		tex->w = w;
+		tex->h = h;
+	}
+}
+
+int
+image_open(struct texture *tex, const char *path)
+{
+	assert(tex);
+	assert(path);
+
+	if (!(tex->handle = IMG_LoadTexture(RENDERER(), path)))
+		return ERR_SDL;
+
+	dimensions(tex);
+
+	return 0;
+}
+
+int
+image_openmem(struct texture *tex, const void *buffer, size_t size)
+{
+	assert(buffer);
+
+	SDL_RWops *ops = SDL_RWFromConstMem(buffer, size);
+
+	if (!ops || !(tex->handle = IMG_LoadTexture_RW(RENDERER(), ops, 1)))
+		return ERR_SDL;
+
+	dimensions(tex);
+
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/image.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,38 @@
+/*
+ * image.h -- basic image management
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_IMAGE_H
+#define MLK_CORE_IMAGE_H
+
+#include <stddef.h>
+
+#include "core.h"
+
+struct texture;
+
+CORE_BEGIN_DECLS
+
+int
+image_open(struct texture *, const char *);
+
+int
+image_openmem(struct texture *, const void *, size_t);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_IMAGE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/inhibit.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,29 @@
+/*
+ * inhibit.h -- disable specific game behavior
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_INHIBIT_H
+#define MLK_CORE_INHIBIT_H
+
+enum inhibit {
+	INHIBIT_NONE,
+	INHIBIT_STATE_INPUT        = (1 << 0),
+	INHIBIT_STATE_UPDATE       = (1 << 1),
+	INHIBIT_STATE_DRAW         = (1 << 2)
+};
+
+#endif /* !MLK_CORE_INHIBIT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/key.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,176 @@
+/*
+ * key.h -- keyboard definitions
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_KEY_H
+#define MLK_CORE_KEY_H
+
+enum key {
+	KEY_UNKNOWN,
+	KEY_ENTER,
+	KEY_ESCAPE,
+	KEY_BACKSPACE,
+	KEY_TAB,
+	KEY_SPACE,
+	KEY_EXCLAIM,
+	KEY_DOUBLE_QUOTE,
+	KEY_HASH,
+	KEY_PERCENT,
+	KEY_DOLLAR,
+	KEY_AMPERSAND,
+	KEY_QUOTE,
+	KEY_LEFT_PAREN,
+	KEY_RIGHT_PAREN,
+	KEY_ASTERISK,
+	KEY_PLUS,
+	KEY_COMMA,
+	KEY_MINUS,
+	KEY_PERIOD,
+	KEY_SLASH,
+	KEY_0,
+	KEY_1,
+	KEY_2,
+	KEY_3,
+	KEY_4,
+	KEY_5,
+	KEY_6,
+	KEY_7,
+	KEY_8,
+	KEY_9,
+	KEY_COLON,
+	KEY_SEMICOLON,
+	KEY_LESS,
+	KEY_EQUALS,
+	KEY_GREATER,
+	KEY_QUESTION,
+	KEY_AT,
+	KEY_LEFT_BRACKET,
+	KEY_BACKSLASH,
+	KEY_RIGHT_BRACKET,
+	KEY_CARET,
+	KEY_UNDERSCORE,
+	KEY_BACKQUOTE,
+	KEY_a,
+	KEY_b,
+	KEY_c,
+	KEY_d,
+	KEY_e,
+	KEY_f,
+	KEY_g,
+	KEY_h,
+	KEY_i,
+	KEY_j,
+	KEY_k,
+	KEY_l,
+	KEY_m,
+	KEY_n,
+	KEY_o,
+	KEY_p,
+	KEY_q,
+	KEY_r,
+	KEY_s,
+	KEY_t,
+	KEY_u,
+	KEY_v,
+	KEY_w,
+	KEY_x,
+	KEY_y,
+	KEY_z,
+	KEY_CAPSLOCK,
+	KEY_F1,
+	KEY_F2,
+	KEY_F3,
+	KEY_F4,
+	KEY_F5,
+	KEY_F6,
+	KEY_F7,
+	KEY_F8,
+	KEY_F9,
+	KEY_F10,
+	KEY_F11,
+	KEY_F12,
+	KEY_F13,
+	KEY_F14,
+	KEY_F15,
+	KEY_F16,
+	KEY_F17,
+	KEY_F18,
+	KEY_F19,
+	KEY_F20,
+	KEY_F21,
+	KEY_F22,
+	KEY_F23,
+	KEY_F24,
+	KEY_PRINTSCREEN,
+	KEY_SCROLL_LOCK,
+	KEY_PAUSE,
+	KEY_INSERT,
+	KEY_HOME,
+	KEY_PAGEUP,
+	KEY_DELETE,
+	KEY_END,
+	KEY_PAGEDOWN,
+	KEY_RIGHT,
+	KEY_LEFT,
+	KEY_DOWN,
+	KEY_UP,
+	KEY_NUMLOCKCLEAR,
+	KEY_KP_DIVIDE,
+	KEY_KP_MULTIPLY,
+	KEY_KP_MINUS,
+	KEY_KP_PLUS,
+	KEY_KP_ENTER,
+	KEY_KP_00,
+	KEY_KP_000,
+	KEY_KP_1,
+	KEY_KP_2,
+	KEY_KP_3,
+	KEY_KP_4,
+	KEY_KP_5,
+	KEY_KP_6,
+	KEY_KP_7,
+	KEY_KP_8,
+	KEY_KP_9,
+	KEY_KP_0,
+	KEY_KP_PERIOD,
+	KEY_KP_COMMA,
+	KEY_MENU,
+	KEY_MUTE,
+	KEY_VOLUME_UP,
+	KEY_VOLUME_DOWN,
+	KEY_LCTRL,
+	KEY_LSHIFT,
+	KEY_LALT,
+	KEY_LSUPER,
+	KEY_RCTRL,
+	KEY_RSHIFT,
+	KEY_RALT,
+	KEY_RSUPER,
+};
+
+enum keymod {
+	KEYMOD_LSHIFT   = 1 << 0,
+	KEYMOD_LCTRL    = 1 << 1,
+	KEYMOD_LALT     = 1 << 2,
+	KEYMOD_LSUPER   = 1 << 3,
+	KEYMOD_RSHIFT   = 1 << 4,
+	KEYMOD_RCTRL    = 1 << 5,
+	KEYMOD_RALT     = 1 << 6,
+	KEYMOD_RSUPER   = 1 << 7 
+};
+
+#endif /* !MLK_CORE_KEY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/maths.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,34 @@
+/*
+ * maths.c -- basic maths
+ *
+ * Copyright (c) 2020-2022 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 "maths.h"
+
+int
+maths_is_boxed(int x, int y, unsigned int w, unsigned int h, int px, int py)
+{
+	return px > x &&
+	       py > y &&
+	       px < x + (int)w &&
+	       py < y + (int)h;
+}
+
+float
+maths_scale(float in, float old_min, float old_max, float new_min, float new_max)
+{
+	return (in / ((old_max - old_min) / (new_max - new_min))) + new_min;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/maths.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,34 @@
+/*
+ * maths.h -- basic maths
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_MATHS_H
+#define MLK_CORE_MATHS_H
+
+#include "core.h"
+
+CORE_BEGIN_DECLS
+
+int
+maths_is_boxed(int, int, unsigned int, unsigned int, int, int);
+
+float
+maths_scale(float, float, float, float, float);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_MATHS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/mouse.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,29 @@
+/*
+ * mouse.h -- mouse definitions
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_MOUSE_H
+#define MLK_CORE_MOUSE_H
+
+enum mouse_button {
+	MOUSE_BUTTON_NONE       = 0,
+	MOUSE_BUTTON_LEFT       = (1 << 0),
+	MOUSE_BUTTON_MIDDLE     = (1 << 1),
+	MOUSE_BUTTON_RIGHT      = (1 << 2)
+};
+
+#endif /* !MLK_CORE_MOUSE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/music.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,109 @@
+/*
+ * music.h -- music support
+ *
+ * Copyright (c) 2020-2022 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 <string.h>
+
+#include "err.h"
+#include "music.h"
+#include "sys_p.h"
+
+#define SOURCE(mus) ((const struct audiostream *)mus->handle)->source
+
+int
+music_open(struct music *mus, const char *path)
+{
+	assert(mus);
+	assert(path);
+
+	if (!(mus->handle = audiostream_open(path)))
+		return -1;
+
+	return 0;
+}
+
+int
+music_openmem(struct music *mus, const void *buffer, size_t buffersz)
+{
+	assert(mus);
+	assert(buffer);
+
+	if (!(mus->handle = audiostream_openmem(buffer, buffersz)))
+		return -1;
+
+	return 0;
+}
+
+int
+music_ok(const struct music *mus)
+{
+	return mus && mus->handle;
+}
+
+int
+music_play(struct music *mus, enum music_flags flags)
+{
+	assert(mus);
+
+	if (flags & MUSIC_LOOP)
+		alSourcei(SOURCE(mus), AL_LOOPING, AL_TRUE);
+	else
+		alSourcei(SOURCE(mus), AL_LOOPING, AL_TRUE);
+
+	alSourceRewind(SOURCE(mus));
+	alSourcePlay(SOURCE(mus));
+
+	return 0;
+}
+
+void
+music_pause(struct music *mus)
+{
+	assert(music_ok(mus));
+
+	alSourcePause(SOURCE(mus));
+}
+
+void
+music_resume(struct music *mus)
+{
+	assert(music_ok(mus));
+
+	alSourcePlay(SOURCE(mus));
+}
+
+void
+music_stop(struct music *mus)
+{
+	assert(music_ok(mus));
+
+	alSourceStop(SOURCE(mus));
+}
+
+void
+music_finish(struct music *mus)
+{
+	assert(mus);
+
+	if (mus->handle) {
+		music_stop(mus);
+		audiostream_finish(mus->handle);
+	}
+
+	memset(mus, 0, sizeof (*mus));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/music.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,63 @@
+/*
+ * music.h -- music support
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_MUSIC_H
+#define MLK_CORE_MUSIC_H
+
+#include <stddef.h>
+
+#include "core.h"
+
+enum music_flags {
+	MUSIC_NONE      = 0,
+	MUSIC_LOOP      = (1 << 0)
+};
+
+struct music {
+	void *handle;
+};
+
+CORE_BEGIN_DECLS
+
+int
+music_open(struct music *, const char *);
+
+int
+music_openmem(struct music *, const void *, size_t);
+
+int
+music_ok(const struct music *);
+
+int
+music_play(struct music *, enum music_flags);
+
+void
+music_pause(struct music *);
+
+void
+music_resume(struct music *);
+
+void
+music_stop(struct music *);
+
+void
+music_finish(struct music *);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_MUSIC_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/painter.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,115 @@
+/*
+ * painter.c -- basic drawing routines
+ *
+ * Copyright (c) 2020-2022 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 <math.h>
+
+#include "color.h"
+#include "painter.h"
+#include "texture.h"
+#include "window.h"
+#include "window_p.h"
+
+/* Current texture renderer. */
+static struct texture *renderer;
+
+struct texture *
+painter_get_target(void)
+{
+	return renderer;
+}
+
+void
+painter_set_target(struct texture *tex)
+{
+	renderer = tex;
+	SDL_SetRenderTarget(RENDERER(), tex ? tex->handle : NULL);
+}
+
+unsigned long
+painter_get_color(void)
+{
+	Uint8 r = 0, g = 0, b = 0, a = 0;
+
+	SDL_GetRenderDrawColor(RENDERER(), &r, &g, &b, &a);
+
+	return COLOR_HEX(r, g, b, a);
+}
+
+void
+painter_set_color(unsigned long color)
+{
+	SDL_SetRenderDrawColor(
+		RENDERER(),
+		COLOR_R(color),
+		COLOR_G(color),
+		COLOR_B(color),
+		COLOR_A(color)
+	);
+}
+
+void
+painter_draw_line(int x1, int y1, int x2, int y2)
+{
+	SDL_RenderDrawLine(RENDERER(), x1, y1, x2, y2);
+}
+
+void
+painter_draw_point(int x1, int y1)
+{
+	SDL_RenderDrawPoint(RENDERER(), x1, y1);
+}
+
+void
+painter_draw_rectangle(int x, int y, unsigned int width, unsigned int height)
+{
+	const SDL_Rect rect = {
+		.w = width,
+		.h = height,
+		.x = x,
+		.y = y
+	};
+
+	SDL_RenderFillRect(RENDERER(), &rect);
+}
+
+void
+painter_draw_circle(int x, int y, int radius)
+{
+	// Note that there is more to altering the bitrate of this 
+	// method than just changing this value.  See how pixels are
+	// altered at the following web page for tips:
+	//   http://www.libsdl.org/intro.en/usingvideo.html
+	for (double dy = 1; dy <= radius; dy += 1.0) {
+		double dx = floor(sqrt((2.0 * radius * dy) - (dy * dy)));
+
+		SDL_RenderDrawLine(RENDERER(), x - dx, y + dy - radius, x + dx, y + dy - radius);
+		SDL_RenderDrawLine(RENDERER(), x - dx, y - dy + radius, x + dx, y - dy + radius);
+	}
+}
+
+void
+painter_clear(void)
+{
+	SDL_RenderClear(RENDERER());
+}
+
+void
+painter_present(void)
+{
+	SDL_RenderPresent(RENDERER());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/painter.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,71 @@
+/*
+ * painter.h -- basic drawing routines
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_PAINTER_H
+#define MLK_CORE_PAINTER_H
+
+#include "core.h"
+
+struct texture;
+
+CORE_BEGIN_DECLS
+
+struct texture *
+painter_get_target(void);
+
+void
+painter_set_target(struct texture *);
+
+unsigned long
+painter_get_color(void);
+
+void
+painter_set_color(unsigned long);
+
+void
+painter_draw_line(int, int, int, int);
+
+void
+painter_draw_point(int, int);
+
+void
+painter_draw_rectangle(int, int, unsigned int, unsigned int);
+
+void
+painter_draw_circle(int, int, int);
+
+void
+painter_clear(void);
+
+void
+painter_present(void);
+
+CORE_END_DECLS
+
+#define PAINTER_BEGIN(tex)                                              \
+do {                                                                    \
+        struct texture *__current_texture__;                            \
+                                                                        \
+        __current_texture__ = painter_get_target();                     \
+        painter_set_target((tex))
+
+#define PAINTER_END()                                                   \
+        painter_set_target(__current_texture__);                        \
+} while (0)
+
+#endif /* !MLK_CORE_PAINTER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/panic.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,78 @@
+/*
+ * panic.c -- unrecoverable error handling
+ *
+ * Copyright (c) 2020-2022 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 <stdio.h>
+#include <stdlib.h>
+
+#include "error.h"
+#include "panic.h"
+
+static void
+terminate(void)
+{
+	fprintf(stderr, "abort: %s\n", error());
+	abort();
+	exit(1);
+}
+
+void (*panic_handler)(void) = terminate;
+void *panic_data = NULL;
+
+void
+panicf(const char *fmt, ...)
+{
+	assert(fmt);
+
+	va_list ap;
+
+	/*
+	 * Store the error before calling panic because va_end would not be
+	 * called.
+	 */
+	va_start(ap, fmt);
+	errorva(fmt, ap);
+	va_end(ap);
+
+	panic();
+}
+
+void
+panicva(const char *fmt, va_list ap)
+{
+	assert(fmt);
+	assert(panic_handler);
+
+	errorva(fmt, ap);
+	panic();
+}
+
+void
+panic(void)
+{
+	assert(panic_handler);
+
+	panic_handler();
+
+	/*
+	 * This should not happen, if it does it means the user did not fully
+	 * satisfied the constraint of panic_handler.
+	 */
+	fprintf(stderr, "abort: panic handler returned\n");
+	exit(1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/panic.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,42 @@
+/*
+ * panic.h -- unrecoverable error handling
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_PANIC_H
+#define MLK_CORE_PANIC_H
+
+#include <stdarg.h>
+
+#include "core.h"
+
+extern void (*panic_handler)(void);
+extern void *panic_data;
+
+CORE_BEGIN_DECLS
+
+void
+panicf(const char *, ...);
+
+void
+panicva(const char *, va_list);
+
+void
+panic(void);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_PANIC_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/script.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,154 @@
+/*
+ * script.c -- convenient sequence of actions
+ *
+ * Copyright (c) 2020-2022 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 <stdlib.h>
+#include <string.h>
+
+#include "action.h"
+#include "err.h"
+#include "script.h"
+
+static struct action *
+current(struct script *s)
+{
+	if (s->cur >= s->actionsz)
+		return NULL;
+
+	return s->actions[s->cur];
+}
+
+static void
+handle(struct action *a, const union event *ev)
+{
+	script_handle(a->data, ev);
+}
+
+static int
+update(struct action *a, unsigned int ticks)
+{
+	return script_update(a->data, ticks);
+}
+
+static void
+draw(struct action *a)
+{
+	script_draw(a->data);
+}
+
+static void
+finish(struct action *a)
+{
+	script_finish(a->data);
+}
+
+void
+script_init(struct script *s)
+{
+	assert(s);
+
+	memset(s, 0, sizeof (*s));
+}
+
+int
+script_append(struct script *s, struct action *a)
+{
+	assert(s);
+	assert(a);
+
+	if (s->actionsz >= SCRIPT_ACTION_MAX)
+		return ERR_NO_MEM;
+
+	s->actions[s->actionsz++] = a;
+
+	return 0;
+}
+
+void
+script_handle(struct script *s, const union event *ev)
+{
+	assert(s);
+	assert(ev);
+
+	struct action *a = current(s);
+
+	if (a)
+		action_handle(a, ev);
+}
+
+int
+script_update(struct script *s, unsigned int ticks)
+{
+	assert(s);
+
+	struct action *a = current(s);
+
+	if (!a)
+		return 1;
+
+	if (action_update(a, ticks)) {
+		action_end(a);
+		s->cur++;
+	}
+
+	return s->cur >= s->actionsz;
+}
+
+void
+script_draw(struct script *s)
+{
+	assert(s);
+
+	struct action *a = current(s);
+
+	if (a)
+		action_draw(a);
+}
+
+int
+script_completed(const struct script *s)
+{
+	assert(s);
+
+	return s->cur >= s->actionsz;
+}
+
+void
+script_finish(struct script *s)
+{
+	assert(s);
+
+	for (size_t i = 0; i < s->actionsz; ++i)
+		action_finish(s->actions[i]);
+
+	memset(s, 0, sizeof (*s));
+}
+
+void
+script_action(struct script *s, struct action *action)
+{
+	assert(s);
+	assert(action);
+
+	memset(action, 0, sizeof (*action));
+	action->data = s;
+	action->handle = handle;
+	action->update = update;
+	action->draw = draw;
+	action->finish = finish;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/script.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,66 @@
+/*
+ * script.h -- convenient sequence of actions
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_SCRIPT_H
+#define MLK_CORE_SCRIPT_H
+
+#include <stddef.h>
+
+#include "core.h"
+
+#define SCRIPT_ACTION_MAX (128)
+
+struct action;
+
+union event;
+
+struct script {
+	struct action *actions[SCRIPT_ACTION_MAX];
+	size_t actionsz;
+	size_t cur;
+};
+
+CORE_BEGIN_DECLS
+
+void
+script_init(struct script *);
+
+int
+script_append(struct script *, struct action *);
+
+void
+script_handle(struct script *, const union event *);
+
+int
+script_update(struct script *, unsigned int);
+
+void
+script_draw(struct script *);
+
+int
+script_completed(const struct script *);
+
+void
+script_finish(struct script *);
+
+void
+script_action(struct script*s, struct action *);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_SCRIPT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/sound.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,104 @@
+/*
+ * sound.c -- sound support
+ *
+ * Copyright (c) 2020-2022 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 <stdio.h>
+#include <string.h>
+
+#include "error.h"
+#include "sound.h"
+#include "sys_p.h"
+
+#define SOURCE(snd) ((const struct audiostream *)snd->handle)->source
+
+int
+sound_open(struct sound *snd, const char *path)
+{
+	assert(snd);
+	assert(path);
+
+	if (!(snd->handle = audiostream_open(path)))
+		return -1;
+
+	return 0;
+}
+
+int
+sound_openmem(struct sound *snd, const void *buffer, size_t buffersz)
+{
+	assert(snd);
+	assert(buffer);
+
+	if (!(snd->handle = audiostream_openmem(buffer, buffersz)))
+		return -1;
+
+	return 0;
+}
+
+int
+sound_ok(const struct sound *snd)
+{
+	return snd && snd->handle;
+}
+
+int
+sound_play(struct sound *snd)
+{
+	assert(sound_ok(snd));
+
+	alSourcePlay(SOURCE(snd));
+
+	return 0;
+}
+
+void
+sound_pause(struct sound *snd)
+{
+	assert(sound_ok(snd));
+
+	alSourcePause(SOURCE(snd));
+}
+
+void
+sound_resume(struct sound *snd)
+{
+	assert(sound_ok(snd));
+
+	alSourcePlay(SOURCE(snd));
+}
+
+void
+sound_stop(struct sound *snd)
+{
+	assert(sound_ok(snd));
+
+	alSourceStop(SOURCE(snd));
+}
+
+void
+sound_finish(struct sound *snd)
+{
+	assert(snd);
+
+	if (snd->handle) {
+		sound_stop(snd);
+		audiostream_finish(snd->handle);
+	}
+
+	memset(snd, 0, sizeof (*snd));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/sound.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,66 @@
+/*
+ * sound.h -- sound support
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_SOUND_H
+#define MLK_CORE_SOUND_H
+
+#include <stddef.h>
+
+#include "core.h"
+
+#define SOUND_CHANNELS_MAX (256)
+
+struct vfs_file;
+
+struct sound {
+	void *handle;
+	int channel;
+};
+
+CORE_BEGIN_DECLS
+
+int
+sound_open(struct sound *, const char *);
+
+int
+sound_openmem(struct sound *, const void *, size_t);
+
+int
+sound_openvfs(struct sound *, struct vfs_file *);
+
+int
+sound_ok(const struct sound *);
+
+int
+sound_play(struct sound *);
+
+void
+sound_pause(struct sound *);
+
+void
+sound_resume(struct sound *);
+
+void
+sound_stop(struct sound *);
+
+void
+sound_finish(struct sound *);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_SOUND_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/sprite.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,77 @@
+/*
+ * sprite.c -- image sprites
+ *
+ * Copyright (c) 2020-2022 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 "sprite.h"
+#include "texture.h"
+
+void
+sprite_init(struct sprite *sprite,
+            struct texture *tex,
+            unsigned int cellw,
+            unsigned int cellh)
+{
+	assert(sprite);
+	assert(tex && texture_ok(tex));
+
+	sprite->texture = tex;
+	sprite->cellw = cellw;
+	sprite->cellh = cellh;
+	sprite->nrows = tex->h / cellh;
+	sprite->ncols = tex->w / cellw;
+}
+
+int
+sprite_ok(const struct sprite *sprite)
+{
+	return sprite && texture_ok(sprite->texture) && sprite->cellw != 0 && sprite->cellh != 0;
+}
+
+int
+sprite_draw(const struct sprite *sprite, unsigned int r, unsigned int c, int x, int y)
+{
+	return sprite_scale(sprite, r, c, x, y, sprite->cellw, sprite->cellh);
+}
+
+int
+sprite_scale(const struct sprite *sprite,
+	     unsigned int r,
+	     unsigned int c,
+	     int x,
+	     int y,
+	     unsigned int w,
+	     unsigned int h)
+{
+	assert(sprite_ok(sprite));
+	assert(r < sprite->nrows);
+	assert(c < sprite->ncols);
+
+	return texture_scale(
+		sprite->texture,
+		c * sprite->cellw,      /* src y */
+		r * sprite->cellh,      /* src x */
+		sprite->cellw,          /* src width */
+		sprite->cellh,          /* src height */
+		x,                      /* dst x */
+		y,                      /* dst y */
+		w,                      /* dst width */
+		h,                      /* dst height */
+		0.0                     /* angle */
+	);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/sprite.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,56 @@
+/*
+ * sprite.h -- image sprites
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_SPRITE_H
+#define MLK_CORE_SPRITE_H
+
+#include "core.h"
+
+struct texture;
+
+struct sprite {
+	struct texture *texture;
+	unsigned int cellw;
+	unsigned int cellh;
+	unsigned int nrows;
+	unsigned int ncols;
+};
+
+CORE_BEGIN_DECLS
+
+void
+sprite_init(struct sprite *, struct texture *, unsigned int, unsigned int);
+
+int
+sprite_ok(const struct sprite *);
+
+int
+sprite_draw(const struct sprite *, unsigned int, unsigned int, int, int);
+
+int
+sprite_scale(const struct sprite *,
+             unsigned int,
+             unsigned int,
+             int,
+             int,
+             unsigned int,
+             unsigned int);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_SPRITE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/state.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,94 @@
+/*
+ * state.c -- abstract state
+ *
+ * Copyright (c) 2020-2022 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 "state.h"
+
+void
+state_start(struct state *state)
+{
+	assert(state);
+
+	if (state->start)
+		state->start(state);
+}
+
+void
+state_handle(struct state *state, const union event *ev)
+{
+	assert(state);
+	assert(ev);
+
+	if (state->handle)
+		state->handle(state, ev);
+}
+
+void
+state_update(struct state *state, unsigned int ticks)
+{
+	assert(state);
+
+	if (state->update)
+		state->update(state, ticks);
+}
+
+void
+state_draw(struct state *state)
+{
+	assert(state);
+
+	if (state->draw)
+		state->draw(state);
+}
+
+void
+state_suspend(struct state *state)
+{
+	assert(state);
+
+	if (state->suspend)
+		state->suspend(state);
+}
+
+void
+state_resume(struct state *state)
+{
+	assert(state);
+
+	if (state->resume)
+		state->resume(state);
+}
+
+void
+state_end(struct state *state)
+{
+	assert(state);
+
+	if (state->end)
+		state->end(state);
+}
+
+void
+state_finish(struct state *state)
+{
+	assert(state);
+
+	if (state->finish)
+		state->finish(state);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/state.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,66 @@
+/*
+ * state.h -- abstract state
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_STATE_H
+#define MLK_CORE_STATE_H
+
+#include "core.h"
+
+union event;
+
+struct state {
+	void *data;
+	void (*start)(struct state *);
+	void (*handle)(struct state *, const union event *);
+	void (*update)(struct state *, unsigned int);
+	void (*draw)(struct state *);
+	void (*suspend)(struct state *);
+	void (*resume)(struct state *);
+	void (*end)(struct state *);
+	void (*finish)(struct state *);
+};
+
+CORE_BEGIN_DECLS
+
+void
+state_start(struct state *);
+
+void
+state_handle(struct state *, const union event *);
+
+void
+state_update(struct state *, unsigned int);
+
+void
+state_draw(struct state *);
+
+void
+state_suspend(struct state *);
+
+void
+state_resume(struct state *);
+
+void
+state_end(struct state *);
+
+void
+state_finish(struct state *);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_STATE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/sys.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,331 @@
+/*
+ * sys.c -- system routines
+ *
+ * Copyright (c) 2020-2022 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 <sys/stat.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#if defined(_WIN32)
+#       include <shlwapi.h>
+#       include <windows.h>
+#else
+#       include <errno.h>
+#       include <string.h>
+#endif
+
+#include <SDL.h>
+#include <SDL_image.h>
+#include <SDL_ttf.h>
+
+#include <sndfile.h>
+
+#include <util/util.h>
+
+#include "alloc.h"
+#include "error.h"
+#include "panic.h"
+#include "sound.h"
+#include "sys.h"
+#include "sys_p.h"
+
+ALCdevice *audio_dev = NULL;
+ALCcontext *audio_ctx = NULL;
+
+static struct {
+	char organization[128];
+	char name[128];
+} info = {
+	.organization = "fr.malikania",
+	.name = "molko"
+};
+
+static inline char *
+normalize(char *str)
+{
+	for (char *p = str; *p; ++p)
+		if (*p == '\\')
+			*p = '/';
+
+	return str;
+}
+
+static const char *
+user_directory(enum sys_dir kind)
+{
+	/* Kept for future use. */
+	(void)kind;
+
+	static char path[PATH_MAX];
+	char *pref;
+
+	if ((pref = SDL_GetPrefPath(info.organization, info.name))) {
+		util_strlcpy(path, pref, sizeof (path));
+		SDL_free(pref);
+	} else
+		util_strlcpy(path, "./", sizeof (path));
+
+	return path;
+}
+
+static inline int
+mkpath(const char *path)
+{
+#ifdef _WIN32
+	/* TODO: add error using the convenient FormatMessage function. */
+	if (!CreateDirectoryA(path, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
+		return errorf("unable to create directory: %s", path);
+#else
+	if (mkdir(path, 0755) < 0 && errno != EEXIST)
+		return errorf("%s", strerror(errno));
+#endif
+
+	return 0;
+}
+
+int
+sys_init(const char *organization, const char *name)
+{
+#if defined(__MINGW64__)
+	/* On MinGW buffering leads to painful debugging. */
+	setbuf(stderr, NULL);
+	setbuf(stdout, NULL);
+#endif
+
+	/* Kept for future use. */
+	(void)organization;
+	(void)name;
+
+	/* SDL2. */
+	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+		return errorf("%s", SDL_GetError());
+	if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG)
+		return errorf("%s", SDL_GetError());
+	if (TTF_Init() < 0)
+		return errorf("%s", SDL_GetError());
+
+	/* OpenAL. */
+#if defined(_WIN32)
+	SetEnvironmentVariable("ALSOFT_LOGLEVEL", "0");
+#else
+	putenv("ALSOFT_LOGLEVEL=0");
+#endif
+
+	if (!(audio_dev = alcOpenDevice(NULL)))
+		return errorf("unable to create audio device");
+	if (!(audio_ctx = alcCreateContext(audio_dev, NULL)))
+		return errorf("unable to create audio context");
+
+	alcMakeContextCurrent(audio_ctx);
+
+	return 0;
+}
+
+const char *
+sys_dir(enum sys_dir kind)
+{
+	return user_directory(kind);
+}
+
+int
+sys_mkdir(const char *directory)
+{
+	char path[PATH_MAX], *p;
+
+	/* Copy the directory to normalize and iterate over '/'. */
+	util_strlcpy(path, directory, sizeof (path));
+	normalize(path);
+
+#if defined(_WIN32)
+	/* Remove drive letter that we don't need. */
+	if ((p = strchr(path, ':')))
+		++p;
+	else
+		p = path;
+#else
+	p = path;
+#endif
+
+	for (p = p + 1; *p; ++p) {
+		if (*p == '/') {
+			*p = 0;
+
+			if (mkpath(path) < 0)
+				return -1;
+
+			*p = '/';
+		}
+	}
+
+	return mkpath(path);
+}
+
+void
+sys_finish(void)
+{
+	TTF_Quit();
+	IMG_Quit();
+	SDL_Quit();
+
+	alcMakeContextCurrent(NULL);
+
+	if (audio_ctx) {
+		alcDestroyContext(audio_ctx);
+		audio_ctx = NULL;
+	}
+	if (audio_dev) {
+		alcCloseDevice(audio_dev);
+		audio_dev = NULL;
+	}
+}
+
+struct audiostream *
+audiostream_create(SNDFILE *file, const SF_INFO *info)
+{
+	struct audiostream *stream;
+
+	stream = alloc_new(sizeof (*stream));
+	stream->samplerate = info->samplerate;
+	stream->samplesz = info->frames * info->channels;
+	stream->samples = alloc_array(stream->samplesz, sizeof (*stream->samples));
+	stream->format = info->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
+
+	sf_command(file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
+
+	if (sf_read_short(file, stream->samples, stream->samplesz) != stream->samplesz) {
+		free(stream->samples);
+		free(stream);
+		stream = NULL;
+	}
+
+	alGenBuffers(1, &stream->buffer);
+	alBufferData(stream->buffer, stream->format, stream->samples,
+	    stream->samplesz * sizeof (*stream->samples), stream->samplerate);
+	alGenSources(1, &stream->source);
+	alSourcei(stream->source, AL_BUFFER, stream->buffer);
+
+	sf_close(file);
+
+	return stream;
+}
+
+struct audiostream *
+audiostream_open(const char *path)
+{
+	assert(path);
+
+	SF_INFO info;
+	SNDFILE *file;
+
+	if (!(file = sf_open(path, SFM_READ, &info)))
+		return NULL;
+
+	return audiostream_create(file, &info);
+}
+
+struct viodata {
+	const unsigned char *data;
+	const size_t datasz;
+	sf_count_t offset;
+};
+
+static sf_count_t
+vio_get_filelen(void *data)
+{
+	const struct viodata *vio = data;
+
+	return (sf_count_t)vio->datasz;
+}
+
+static sf_count_t
+vio_seek(sf_count_t offset, int whence, void *data)
+{
+	struct viodata *vio = data;
+
+	switch (whence) {
+	case SEEK_SET:
+		vio->offset = offset;
+		break;
+	case SEEK_CUR:
+		vio->offset += offset;
+		break;
+	case SEEK_END:
+		vio->offset = vio->datasz - offset;
+		break;
+	default:
+		break;
+	}
+
+	return vio->offset;
+}
+
+static sf_count_t
+vio_read(void *ptr, sf_count_t count, void *data)
+{
+	struct viodata *vio = data;
+
+	memcpy(ptr, vio->data + vio->offset, count);
+	vio->offset += count;
+
+	return count;
+}
+
+static sf_count_t
+vio_tell(void *data)
+{
+	const struct viodata *vio = data;
+
+	return vio->offset;
+}
+
+struct audiostream *
+audiostream_openmem(const void *data, size_t datasz)
+{
+	assert(data);
+
+	SF_VIRTUAL_IO io = {
+		.get_filelen = vio_get_filelen,
+		.seek = vio_seek,
+		.read = vio_read,
+		.tell = vio_tell
+	};
+	SF_INFO info;
+	SNDFILE *file;
+	struct viodata viodata = {
+		.data = data,
+		.datasz = datasz,
+	};
+
+	if (!(file = sf_open_virtual(&io, SFM_READ, &info, &viodata)))
+		return NULL;
+
+	return audiostream_create(file, &info);
+}
+
+void
+audiostream_finish(struct audiostream *s)
+{
+	assert(s);
+
+	alDeleteBuffers(1, &s->buffer);
+	alSourcei(s->source, AL_BUFFER, 0);
+	alDeleteSources(1, &s->source);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/sys.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,46 @@
+/*
+ * sys.h -- system routines
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_SYS_H
+#define MLK_CORE_SYS_H
+
+#include <stdarg.h>
+
+#include "core.h"
+
+enum sys_dir {
+	SYS_DIR_SAVE
+};
+
+CORE_BEGIN_DECLS
+
+int
+sys_init(const char *, const char *);
+
+const char *
+sys_dir(enum sys_dir);
+
+int
+sys_mkdir(const char *);
+
+void
+sys_finish(void);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_SYS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/sys_p.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,55 @@
+/*
+ * sys_p.h -- libcore private definitions
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_SYS_P_H
+#define MLK_CORE_SYS_P_H
+
+#include <util/util.h>
+
+#include <stddef.h>
+
+#if defined(MLK_OS_APPLE)
+#       include <OpenAL/al.h>
+#       include <OpenAL/alc.h>
+#else
+#       include <al.h>
+#       include <alc.h>
+#endif
+
+extern ALCdevice *audio_dev;
+extern ALCcontext *audio_ctx;
+
+struct audiostream {
+	short *samples;
+	ALsizei samplesz;
+	ALsizei samplerate;
+	ALuint buffer;
+	ALuint source;
+	ALenum format;
+};
+
+struct audiostream *
+audiostream_open(const char *);
+
+struct audiostream *
+audiostream_openmem(const void *, size_t);
+
+void
+audiostream_finish(struct audiostream *);
+
+#endif /* !MLK_CORE_SYS_P_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/texture.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,178 @@
+/*
+ * texture.c -- basic texture management
+ *
+ * Copyright (c) 2020-2022 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 <string.h>
+
+#include "color.h"
+#include "error.h"
+#include "texture.h"
+#include "texture_p.h"
+#include "util.h"
+#include "window.h"
+#include "window_p.h"
+
+int
+texture_new(struct texture *tex, unsigned int w, unsigned int h)
+{
+	assert(tex);
+	assert(w);
+	assert(h);
+
+	tex->handle = SDL_CreateTexture(RENDERER(),
+	    SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h);
+
+	if (!tex->handle) {
+		tex->w = tex->h = 0;
+		return ERR_SDL;
+	}
+
+	tex->w = w;
+	tex->h = h;
+
+	return 0;
+}
+
+int
+texture_ok(const struct texture *tex)
+{
+	return tex && tex->handle && tex->w && tex->h;
+}
+
+int
+texture_set_blend_mode(struct texture *tex, enum texture_blend blend)
+{
+	assert(tex);
+	assert(blend >= TEXTURE_BLEND_NONE && blend <= TEXTURE_BLEND_MODULATE);
+
+	static const SDL_BlendMode table[] = {
+		[TEXTURE_BLEND_NONE] = SDL_BLENDMODE_NONE,
+		[TEXTURE_BLEND_BLEND] = SDL_BLENDMODE_BLEND,
+		[TEXTURE_BLEND_ADD] = SDL_BLENDMODE_ADD,
+		[TEXTURE_BLEND_MODULATE] = SDL_BLENDMODE_MOD
+	};
+
+	if (SDL_SetTextureBlendMode(tex->handle, table[blend]) < 0)
+		return errorf("%s", SDL_GetError());
+
+	return 0;
+}
+
+int
+texture_set_alpha_mod(struct texture *tex, unsigned int alpha)
+{
+	assert(texture_ok(tex));
+	assert(alpha <= 255);
+
+	if (SDL_SetTextureAlphaMod(tex->handle, alpha) < 0)
+		return errorf("%s", SDL_GetError());
+
+	return 0;
+}
+
+int
+texture_set_color_mod(struct texture *tex, unsigned long color)
+{
+	assert(texture_ok(tex));
+
+	if (SDL_SetTextureColorMod(tex->handle, COLOR_R(color), COLOR_G(color), COLOR_B(color)) < 0)
+		return errorf("%s", SDL_GetError());
+
+	return 0;
+}
+
+int
+texture_draw(const struct texture *tex, int x, int y)
+{
+	assert(tex);
+
+	SDL_Rect dst = {
+		.x = x,
+		.y = y,
+		.w = tex->w,
+		.h = tex->h
+	};
+
+	if (SDL_RenderCopy(RENDERER(), tex->handle, NULL, &dst) < 0)
+		return errorf("%s", SDL_GetError());
+
+	return 0;
+}
+
+int
+texture_scale(const struct texture *tex,
+              int src_x,
+              int src_y,
+              unsigned src_w,
+              unsigned src_h,
+              int dst_x,
+              int dst_y,
+              unsigned dst_w,
+              unsigned dst_h,
+              double angle)
+{
+	const SDL_Rect src = {
+		.x = src_x,
+		.y = src_y,
+		.w = src_w,
+		.h = src_h
+	};
+	const SDL_Rect dst = {
+		.x = dst_x,
+		.y = dst_y,
+		.w = dst_w,
+		.h = dst_h
+	};
+
+	if (SDL_RenderCopyEx(RENDERER(), tex->handle, &src, &dst, angle, NULL, SDL_FLIP_NONE) < 0)
+		return errorf("%s", SDL_GetError());
+
+	return 0;
+}
+
+void
+texture_finish(struct texture *tex)
+{
+	assert(tex);
+
+	if (tex->handle)
+		SDL_DestroyTexture(tex->handle);
+
+	memset(tex, 0, sizeof (*tex));
+}
+
+/* private */
+
+int
+texture_from_surface(struct texture *tex, SDL_Surface *surface)
+{
+	assert(tex);
+	assert(surface);
+
+	if (!(tex->handle = SDL_CreateTextureFromSurface(RENDERER(), surface))) {
+		tex->w = tex->h = 0;
+		return ERR_SDL;
+	}
+
+	tex->w = surface->w;
+	tex->h = surface->h;
+
+	SDL_FreeSurface(surface);
+
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/texture.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,76 @@
+/*
+ * texture.h -- basic texture management
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_TEXTURE_H
+#define MLK_CORE_TEXTURE_H
+
+#include "core.h"
+#include "err.h"
+
+struct texture {
+	unsigned int w;
+	unsigned int h;
+	void *handle;
+};
+
+enum texture_blend {
+	TEXTURE_BLEND_NONE,
+	TEXTURE_BLEND_BLEND,
+	TEXTURE_BLEND_ADD,
+	TEXTURE_BLEND_MODULATE,
+	TEXTURE_BLEND_LAST
+};
+
+CORE_BEGIN_DECLS
+
+int
+texture_new(struct texture *, unsigned int, unsigned int);
+
+int
+texture_ok(const struct texture *);
+
+int
+texture_set_blend_mode(struct texture *, enum texture_blend);
+
+int
+texture_set_alpha_mod(struct texture *, unsigned int);
+
+int
+texture_set_color_mod(struct texture *, unsigned long);
+
+int
+texture_draw(const struct texture *, int, int);
+
+int
+texture_scale(const struct texture *,
+              int,
+              int,
+              unsigned int,
+              unsigned int,
+              int,
+              int,
+              unsigned int,
+              unsigned int,
+              double);
+
+void
+texture_finish(struct texture *);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_TEXTURE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/texture_p.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,29 @@
+/*
+ * texture_p.h -- (PRIVATE) basic texture management
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_TEXTURE_P_H
+#define MLK_CORE_TEXTURE_P_H
+
+#include <SDL.h>
+
+struct texture;
+
+int
+texture_from_surface(struct texture *, SDL_Surface *);
+
+#endif /* !MLK_CORE_TEXTURE_P_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/trace.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,62 @@
+/*
+ * trace.h -- non-fatal message logs
+ *
+ * Copyright (c) 2020-2022 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 <stdio.h>
+
+#include "trace.h"
+
+static void
+default_handler(const char *line)
+{
+	assert(line);
+
+	puts(line);
+}
+
+void (*trace_handler)(const char *) = default_handler;
+void *trace_data = NULL;
+
+void
+tracef(const char *fmt, ...)
+{
+	assert(fmt);
+
+	va_list ap;
+
+	if (!trace_handler)
+		return;
+
+	va_start(ap, fmt);
+	traceva(fmt, ap);
+	va_end(ap);
+}
+
+void
+traceva(const char *fmt, va_list ap)
+{
+	assert(fmt);
+
+	char buf[TRACE_LINE_MAX];
+
+	if (!trace_handler)
+		return;
+
+	vsnprintf(buf, sizeof (buf), fmt, ap);
+	trace_handler(buf);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/trace.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,41 @@
+/*
+ * trace.h -- non-fatal message logs
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_TRACE_H
+#define MLK_CORE_TRACE_H
+
+#include <stdarg.h>
+
+#include "core.h"
+
+#define TRACE_LINE_MAX (1024)
+
+extern void (*trace_handler)(const char *);
+extern void *trace_data;
+
+CORE_BEGIN_DECLS
+
+void
+tracef(const char *, ...);
+
+void
+traceva(const char *, va_list);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_TRACE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/util.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,54 @@
+/*
+ * util.c -- utilities
+ *
+ * Copyright (c) 2020-2022 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 <limits.h>
+#include <stdlib.h>
+
+#include <SDL.h>
+
+#include <util/util.h>
+
+#include "util.h"
+
+void
+util_delay(unsigned int ms)
+{
+	SDL_Delay(ms);
+}
+
+const char *
+util_pathf(const char *fmt, ...)
+{
+	static char path[PATH_MAX];
+	va_list ap;
+
+	va_start(ap, fmt);
+	vsnprintf(path, sizeof (path), fmt, ap);
+	va_end(ap);
+
+	return path;
+}
+
+unsigned int
+util_nrand(unsigned int lower, unsigned int upper)
+{
+	assert(upper <= RAND_MAX);
+
+	return (rand() % (upper - lower)) + lower;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/util.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,39 @@
+/*
+ * util.h -- utilities
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_UTIL_H
+#define MLK_CORE_UTIL_H
+
+#include "core.h"
+
+#define UTIL_SIZE(x) sizeof ((x)) / sizeof ((x)[0])
+
+CORE_BEGIN_DECLS
+
+void
+util_delay(unsigned int);
+
+const char *
+util_pathf(const char *, ...);
+
+unsigned int
+util_nrand(unsigned int, unsigned int);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_UTIL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/window.c	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,117 @@
+/*
+ * window.c -- basic window management
+ *
+ * Copyright (c) 2020-2022 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 <string.h>
+
+#include <SDL.h>
+
+#include "err.h"
+#include "util.h"
+#include "window.h"
+#include "window_p.h"
+
+static struct window_handle handle = {
+	.win = NULL,
+	.renderer = NULL
+};
+
+static SDL_Cursor *cursors[WINDOW_CURSOR_LAST];
+
+struct window window = {
+	.handle = &handle
+};
+
+static void
+load_cursors(void)
+{
+	cursors[WINDOW_CURSOR_ARROW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
+	cursors[WINDOW_CURSOR_EDIT] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
+	cursors[WINDOW_CURSOR_WAIT] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT);
+	cursors[WINDOW_CURSOR_CROSSHAIR] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_CROSSHAIR);
+	cursors[WINDOW_CURSOR_SIZE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
+	cursors[WINDOW_CURSOR_NO] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
+	cursors[WINDOW_CURSOR_HAND] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
+}
+
+static void
+load_framerate(void)
+{
+	SDL_DisplayMode mode;
+
+	if (SDL_GetWindowDisplayMode(handle.win, &mode) == 0)
+		window.framerate = mode.refresh_rate;
+}
+
+static void
+finish_cursors(void)
+{
+	for (size_t i = 0; i < UTIL_SIZE(cursors); ++i)
+		if (cursors[i])
+			SDL_FreeCursor(cursors[i]);
+}
+
+static int
+load_window(const char *title, unsigned int w, unsigned int h)
+{
+	return (handle.win = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, 0)) != NULL;
+}
+
+static int
+load_renderer(void)
+{
+	return (handle.renderer = SDL_CreateRenderer(handle.win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)) != NULL;
+}
+
+int
+window_open(const char *title, unsigned int w, unsigned int h)
+{
+	assert(title);
+
+	if (!load_window(title, w, h) || !load_renderer())
+		return ERR_SDL;
+
+	window.w = w;
+	window.h = h;
+
+	load_framerate();
+	load_cursors();
+
+	return 0;
+}
+
+void
+window_set_cursor(enum window_cursor cursor)
+{
+	assert(cursor < WINDOW_CURSOR_LAST);
+
+	SDL_SetCursor(cursors[cursor]);
+}
+
+void
+window_finish(void)
+{
+	if (handle.renderer)
+		SDL_DestroyRenderer(handle.renderer);
+	if (handle.win)
+		SDL_DestroyWindow(handle.win);
+
+	finish_cursors();
+
+	memset(&handle, 0, sizeof (handle));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/window.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,57 @@
+/*
+ * window.h -- basic window management
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_WINDOW_H
+#define MLK_CORE_WINDOW_H
+
+#include "core.h"
+
+struct window {
+	unsigned int w;
+	unsigned int h;
+	unsigned int framerate;
+	void *handle;
+};
+
+enum window_cursor {
+	WINDOW_CURSOR_ARROW,
+	WINDOW_CURSOR_EDIT,
+	WINDOW_CURSOR_WAIT,
+	WINDOW_CURSOR_CROSSHAIR,
+	WINDOW_CURSOR_SIZE,
+	WINDOW_CURSOR_NO,
+	WINDOW_CURSOR_HAND,
+	WINDOW_CURSOR_LAST
+};
+
+extern struct window window;
+
+CORE_BEGIN_DECLS
+
+int
+window_open(const char *, unsigned int, unsigned int);
+
+void
+window_set_cursor(enum window_cursor);
+
+void
+window_finish(void);
+
+CORE_END_DECLS
+
+#endif /* !MLK_CORE_WINDOW_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-core/mlk/core/window_p.h	Sat Oct 15 20:23:14 2022 +0200
@@ -0,0 +1,33 @@
+/*
+ * window.c -- (PRIVATE) basic window management
+ *
+ * Copyright (c) 2020-2022 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.
+ */
+
+#ifndef MLK_CORE_WINDOW_P_H
+#define MLK_CORE_WINDOW_P_H
+
+#include <SDL.h>
+
+struct window_handle {
+	SDL_Window *win;
+	SDL_Renderer *renderer;
+};
+
+/* Convenient macros to access the native handle from global window object. */
+#define WINDOW()        (((struct window_handle *)window.handle)->win)
+#define RENDERER()      (((struct window_handle *)window.handle)->renderer)
+
+#endif /* !MLK_CORE_WINDOW_P_H */
--- a/src/libmlk-core/core/action-stack.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * action-stack.h -- convenient stack of actions
- *
- * Copyright (c) 2020-2022 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 <string.h>
-
-#include "action-stack.h"
-#include "action.h"
-#include "err.h"
-
-#define ACTION_FOREACH(st, iter) \
-	for (size_t i = 0; i < (st)->actionsz && ((iter) = (st)->actions[i], 1); ++i)
-
-void
-action_stack_init(struct action_stack *st, struct action **actions, size_t actionsz)
-{
-	assert(st);
-
-	st->actions = actions;
-	st->actionsz = actionsz;
-
-	for (size_t i = 0; i < st->actionsz; ++i)
-		st->actions[i] = NULL;
-}
-
-int
-action_stack_add(struct action_stack *st, struct action *act)
-{
-	assert(st);
-	assert(act);
-
-	for (size_t i = 0; i < st->actionsz; ++i) {
-		if (!st->actions[i]) {
-			st->actions[i] = act;
-			return 0;
-		}
-	}
-
-	return ERR_NO_MEM;
-}
-
-void
-action_stack_handle(struct action_stack *st, const union event *ev)
-{
-	assert(st);
-	assert(ev);
-
-	struct action *act;
-
-	ACTION_FOREACH(st, act)
-		if (act)
-			action_handle(act, ev);
-}
-
-int
-action_stack_update(struct action_stack *st, unsigned int ticks)
-{
-	assert(st);
-
-	struct action *act;
-
-	for (size_t i = 0; i < st->actionsz; ++i) {
-		act = st->actions[i];
-
-		if (act && action_update(act, ticks)) {
-			action_end(act);
-			action_finish(act);
-			st->actions[i] = NULL;
-		}
-	}
-
-	/*
-	 * We process all actions again in case the user modified the stack
-	 * within their update function.
-	 */
-	return action_stack_completed(st);
-}
-
-void
-action_stack_draw(const struct action_stack *st)
-{
-	assert(st);
-
-	struct action *act;
-
-	ACTION_FOREACH(st, act)
-		if (act)
-			action_draw(act);
-}
-
-int
-action_stack_completed(const struct action_stack *st)
-{
-	assert(st);
-
-	struct action *act;
-
-	ACTION_FOREACH(st, act)
-		if (act)
-			return 0;
-
-	return 1;
-}
-
-void
-action_stack_finish(struct action_stack *st)
-{
-	assert(st);
-
-	struct action *act;
-
-	ACTION_FOREACH(st, act) {
-		if (act) {
-			action_end(act);
-			action_finish(act);
-		}
-	}
-
-	memset(st, 0, sizeof (*st));
-}
--- a/src/libmlk-core/core/action-stack.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * action-stack.h -- convenient stack of actions
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_ACTION_STACK_H
-#define MLK_CORE_ACTION_STACK_H
-
-#include <stddef.h>
-
-#include "core.h"
-
-union event;
-
-struct action_stack {
-	struct action **actions;
-	size_t actionsz;
-};
-
-CORE_BEGIN_DECLS
-
-void
-action_stack_init(struct action_stack *, struct action **, size_t);
-
-int
-action_stack_add(struct action_stack *, struct action *);
-
-void
-action_stack_handle(struct action_stack *, const union event *);
-
-int
-action_stack_update(struct action_stack *, unsigned int);
-
-void
-action_stack_draw(const struct action_stack *);
-
-int
-action_stack_completed(const struct action_stack *);
-
-void
-action_stack_finish(struct action_stack *);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_ACTION_STACK_H */
--- a/src/libmlk-core/core/action.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * action.c -- action states
- *
- * Copyright (c) 2020-2022 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 "action.h"
-
-void
-action_handle(struct action *act, const union event *ev)
-{
-	assert(act);
-	assert(ev);
-
-	if (act->handle)
-		act->handle(act, ev);
-}
-
-int
-action_update(struct action *act, unsigned int ticks)
-{
-	assert(act);
-
-	if (act->update)
-		return act->update(act, ticks);
-
-	/* No function means immortal action. */
-	return 0;
-}
-
-void
-action_draw(struct action *act)
-{
-	assert(act);
-
-	if (act->draw)
-		act->draw(act);
-}
-
-void
-action_end(struct action *act)
-{
-	assert(act);
-
-	if (act->end)
-		act->end(act);
-}
-
-void
-action_finish(struct action *act)
-{
-	assert(act);
-
-	if (act->finish)
-		act->finish(act);
-}
--- a/src/libmlk-core/core/action.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * action.h -- action states
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_ACTION_H
-#define MLK_CORE_ACTION_H
-
-#include "core.h"
-
-union event;
-
-struct action {
-	void *data;
-	void (*handle)(struct action *, const union event *);
-	int (*update)(struct action *, unsigned int);
-	void (*draw)(struct action *);
-	void (*end)(struct action *);
-	void (*finish)(struct action *);
-};
-
-CORE_BEGIN_DECLS
-
-void
-action_handle(struct action *, const union event *);
-
-int
-action_update(struct action *, unsigned int);
-
-void
-action_draw(struct action *);
-
-void
-action_end(struct action *);
-
-void
-action_finish(struct action *);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_ACTION_H */
--- a/src/libmlk-core/core/alloc.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,237 +0,0 @@
-/*
- * alloc.h -- custom allocators
- *
- * Copyright (c) 2020-2022 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 <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <SDL.h>
-
-#include "alloc.h"
-#include "buf.h"
-#include "error.h"
-#include "panic.h"
-
-static void *
-panic_alloc(size_t size)
-{
-	void *mem;
-
-	if (!(mem = malloc(size)))
-		panicf("%s", strerror(errno));
-
-	return mem;
-}
-
-static void *
-panic_realloc(void *ptr, size_t size)
-{
-	void *mem;
-
-	if (!(mem = realloc(ptr, size)) && size != 0)
-		panicf("%s", strerror(errno));
-
-	return mem;
-}
-
-static const struct alloc_funcs default_alloc_funcs = {
-	.alloc = panic_alloc,
-	.realloc = panic_realloc,
-	.free = free
-};
-
-static const struct alloc_funcs *funcs = &default_alloc_funcs;
-
-void
-alloc_set(const struct alloc_funcs *newfuncs)
-{
-	assert(funcs);
-	assert(funcs->alloc);
-	assert(funcs->realloc);
-	assert(funcs->free);
-
-	funcs = newfuncs;
-
-	/* Change SDL allocators as well. */
-	SDL_SetMemoryFunctions(alloc_new, alloc_array0, alloc_renew, free);
-}
-
-void *
-alloc_new(size_t size)
-{
-	assert(size != 0);
-
-	return funcs->alloc(size);
-}
-
-void *
-alloc_new0(size_t size)
-{
-	assert(size != 0);
-
-	return memset(funcs->alloc(size), 0, size);
-}
-
-void *
-alloc_array(size_t len, size_t elemsize)
-{
-	assert(len != 0);
-	assert(elemsize != 0);
-
-	return funcs->alloc(len * elemsize);
-}
-
-void *
-alloc_array0(size_t len, size_t elemsize)
-{
-	assert(len != 0);
-	assert(elemsize != 0);
-
-	return alloc_new0(len * elemsize);
-}
-
-void *
-alloc_renew(void *ptr, size_t size)
-{
-	return funcs->realloc(ptr, size);
-}
-
-void *
-alloc_rearray(void *ptr, size_t len, size_t elemsize)
-{
-	assert(elemsize != 0);
-
-	return funcs->realloc(ptr, len * elemsize);
-}
-
-void *
-alloc_rearray0(void *ptr, size_t oldlen, size_t newlen, size_t elemsize)
-{
-	ptr = funcs->realloc(ptr, newlen * elemsize);
-
-	if (newlen > oldlen)
-		memset((unsigned char *)ptr + (oldlen * elemsize), 0, (newlen - oldlen) * elemsize);
-
-	return ptr;
-}
-
-void *
-alloc_dup(const void *ptr, size_t size)
-{
-	assert(ptr);
-	assert(size != 0);
-
-	return memcpy(funcs->alloc(size), ptr, size);
-}
-
-char *
-alloc_sdup(const char *src)
-{
-	assert(src);
-
-	size_t len = strlen(src) + 1;
-
-	return memcpy(funcs->alloc(len), src, len);
-}
-
-char *
-alloc_sdupf(const char *fmt, ...)
-{
-	struct buf buf = {0};
-	va_list ap;
-
-	va_start(ap, fmt);
-	buf_vprintf(&buf, fmt, ap);
-	va_end(ap);
-
-	return buf.data;
-}
-
-void
-alloc_free(void *ptr)
-{
-	funcs->free(ptr);
-}
-
-void
-alloc_pool_init(struct alloc_pool *pool, size_t elemsize, void (*finalizer)(void *))
-{
-	assert(pool);
-	assert(elemsize != 0);
-
-	pool->data = alloc_array(ALLOC_POOL_INIT_DEFAULT, elemsize);
-	pool->elemsize = elemsize;
-	pool->size = 0;
-	pool->capacity = ALLOC_POOL_INIT_DEFAULT;
-	pool->finalizer = finalizer;
-}
-
-void *
-alloc_pool_new(struct alloc_pool *pool)
-{
-	assert(pool);
-
-	if (pool->size >= pool->capacity) {
-		pool->capacity *= 2;
-		pool->data = alloc_rearray(pool->data, pool->capacity, pool->elemsize);
-	}
-
-	return ((unsigned char *)pool->data) + pool->size++ * pool->elemsize;
-}
-
-void *
-alloc_pool_get(const struct alloc_pool *pool, size_t index)
-{
-	assert(pool);
-	assert(index < pool->size);
-
-	return ((unsigned char *)pool->data) + index * pool->elemsize;
-}
-
-void *
-alloc_pool_shrink(struct alloc_pool *pool)
-{
-	assert(pool);
-
-	void *ptr;
-
-	ptr = alloc_rearray(pool->data, pool->size, pool->elemsize);
-	memset(pool, 0, sizeof (*pool));
-
-	return ptr;
-}
-
-void
-alloc_pool_finish(struct alloc_pool *pool)
-{
-	unsigned char *tab;
-
-	if (!pool)
-		return;
-
-	if (pool->finalizer) {
-		tab = pool->data;
-
-		for (size_t i = 0; i < pool->size; ++i)
-			pool->finalizer(tab + i * pool->elemsize);
-	}
-
-	free(pool->data);
-	memset(pool, 0, sizeof (*pool));
-}
--- a/src/libmlk-core/core/alloc.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * alloc.h -- custom allocators
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_ALLOC_H
-#define MLK_CORE_ALLOC_H
-
-#include <stddef.h>
-
-#include "core.h"
-#include "util.h"
-
-/* Must be power of 2. */
-#define ALLOC_POOL_INIT_DEFAULT (32)
-
-/* Custom allocator. */
-struct alloc_funcs {
-	void *(*alloc)(size_t);
-	void *(*realloc)(void *, size_t);
-	void (*free)(void *);
-};
-
-/* Minimalist growable array for loading data. */
-struct alloc_pool {
-	void *data;
-	size_t elemsize;
-	size_t size;
-	size_t capacity;
-	void (*finalizer)(void *);
-};
-
-CORE_BEGIN_DECLS
-
-/* allocator functions. */
-void
-alloc_set(const struct alloc_funcs *);
-
-void *
-alloc_new(size_t);
-
-void *
-alloc_new0(size_t);
-
-void *
-alloc_array(size_t, size_t);
-
-void *
-alloc_array0(size_t, size_t);
-
-void *
-alloc_renew(void *, size_t);
-
-void *
-alloc_rearray(void *, size_t, size_t);
-
-void *
-alloc_rearray0(void *, size_t, size_t, size_t);
-
-void *
-alloc_dup(const void *, size_t);
-
-char *
-alloc_sdup(const char *);
-
-char *
-alloc_sdupf(const char *, ...);
-
-void
-alloc_free(void *);
-
-/* alloc_pool functions. */
-void
-alloc_pool_init(struct alloc_pool *, size_t , void (*)(void *));
-
-void *
-alloc_pool_new(struct alloc_pool *);
-
-void *
-alloc_pool_get(const struct alloc_pool *, size_t);
-
-void *
-alloc_pool_shrink(struct alloc_pool *);
-
-void
-alloc_pool_finish(struct alloc_pool *);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_ALLOC_H */
--- a/src/libmlk-core/core/animation.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * animation.c -- basic animations
- *
- * Copyright (c) 2020-2022 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 <string.h>
-
-#include "drawable.h"
-#include "animation.h"
-#include "sprite.h"
-
-static int
-update(struct drawable *dw, unsigned int ticks)
-{
-	return animation_update(dw->data, ticks);
-}
-
-static void
-draw(struct drawable *dw)
-{
-	animation_draw(dw->data, dw->x, dw->y);
-}
-
-void
-animation_init(struct animation *an, const struct sprite *sprite, unsigned int delay)
-{
-	assert(an);
-	assert(sprite);
-
-	an->sprite = sprite;
-	an->row = 0;
-	an->column = 0;
-	an->delay = delay;
-	an->elapsed = 0;
-}
-
-void
-animation_start(struct animation *an)
-{
-	assert(an);
-
-	an->row = 0;
-	an->column = 0;
-	an->elapsed = 0;
-}
-
-int
-animation_completed(const struct animation *an)
-{
-	assert(an);
-
-	return an->elapsed >= an->delay &&
-	       an->row >= an->sprite->nrows &&
-	       an->column >= an->sprite->ncols;
-}
-
-int
-animation_update(struct animation *an, unsigned int ticks)
-{
-	assert(an);
-
-	an->elapsed += ticks;
-
-	if (an->elapsed < an->delay)
-		return 0;
-
-	/* Increment column first */
-	if (++an->column >= an->sprite->ncols) {
-		/*
-		 * Increment row, if we reach the last row it means we are
-		 * at the last frame.
-		 */
-		if (++an->row >= an->sprite->nrows)
-			an->row = an->sprite->nrows;
-		else
-			an->column = an->elapsed = 0;
-	} else
-		an->elapsed = 0;
-
-	return animation_completed(an);
-}
-
-int
-animation_draw(const struct animation *an, int x, int y)
-{
-	assert(an);
-
-	return sprite_draw(an->sprite, an->row, an->column, x, y);
-}
-
-void
-animation_drawable(struct animation *an, struct drawable *dw, int x, int y)
-{
-	assert(an);
-	assert(dw);
-
-	memset(dw, 0, sizeof (*dw));
-	
-	dw->data = an;
-	dw->x = x - (an->sprite->cellw / 2);
-	dw->y = y - (an->sprite->cellh / 2);
-	dw->update = update;
-	dw->draw = draw;
-
-	animation_start(an);
-}
--- a/src/libmlk-core/core/animation.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * animation.h -- basic animations
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_ANIMATION_H
-#define MLK_CORE_ANIMATION_H
-
-#include "core.h"
-
-struct drawable;
-struct sprite;
-
-struct animation {
-	const struct sprite *sprite;
-	unsigned int row;
-	unsigned int column;
-	unsigned int delay;
-	unsigned int elapsed;
-};
-
-CORE_BEGIN_DECLS
-
-void
-animation_init(struct animation *, const struct sprite *, unsigned int);
-
-void
-animation_start(struct animation *);
-
-int
-animation_completed(const struct animation *);
-
-int
-animation_update(struct animation *, unsigned int);
-
-int
-animation_draw(const struct animation *, int, int);
-
-void
-animation_drawable(struct animation *, struct drawable *, int, int);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_ANIMATION_H */
--- a/src/libmlk-core/core/buf.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,346 +0,0 @@
-/*
- * buf.c -- simple string buffer for C
- *
- * Copyright (c) 2019-2022 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 <errno.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "buf.h"
-
-/*
- * Try to increase the buffer length by a power of two until we have enough
- * space to fit `desired'.
- *
- * Detects overflow and return -1 if happened or reallocation could not
- * occur.
- */
-static int
-growdbl(struct buf *b, size_t desired)
-{
-	size_t newcap = b->capacity;
-	void *newptr;
-
-	while (desired > newcap - b->length) {
-		const size_t r = newcap * 2;
-
-		/* Overflow occured. */
-		if (r / newcap != 2) {
-#if defined(ENOMEM)
-			errno = ENOMEM;
-#endif
-			return -1;
-		}
-
-		newcap = r;
-	}
-
-	/* At this step we must have enough room. */
-	assert(newcap - b->length >= desired);
-
-	/* Pretty much impossible to reach but always assume it's possible. */
-	if (newcap == SIZE_MAX) {
-#if defined(ENOMEM)
-		errno = ENOMEM;
-#endif
-		return -1;
-	}
-
-	if (!(newptr = BUF_REALLOC(b->data, newcap + 1)))
-		return -1;
-
-	b->data = newptr;
-	b->capacity = newcap;
-
-	return 0;
-}
-
-/*
- * Try to allocate just enough space for the `desired' amount of space. This is
- * only used when the buffer is already too large but hasn't reached SIZE_MAX
- * yet.
- *
- * Returns -1 if allocation failed.
- */
-static int
-growmin(struct buf *b, size_t desired)
-{
-	size_t newcap;
-	void *newptr;
-
-	if (desired >= SIZE_MAX - b->length) {
-#if defined(ENOMEM)
-		errno = ENOMEM;
-#endif
-		return -1;
-	}
-
-	/* Don't forget to keep what's remaining between capacity and length. */
-	newcap = b->capacity + (desired - (b->capacity - b->length));
-
-	/* Try to reallocate. */
-	if (!(newptr = BUF_REALLOC(b->data, newcap + 1)))
-		return -1;
-
-	b->data = newptr;
-	b->capacity = newcap;
-
-	return 0;
-}
-
-/*
- * Entry point for reallocating data. Will try to allocate twice until we have
- * enough room and then only the minimal amount.
- */
-static int
-grow(struct buf *b, size_t desired)
-{
-	const size_t avail = b->capacity - b->length;
-
-	if (avail >= desired)
-		return 0;
-
-	if (!b->capacity) {
-		if (!(b->data = BUF_MALLOC(desired + 1)))
-			return -1;
-
-		b->capacity = desired;
-	} else if (growdbl(b, desired) < 0 && growmin(b, desired) < 0)
-		return -1;
-
-	return 0;
-}
-
-void
-buf_init(struct buf *b)
-{
-	assert(b);
-
-	memset(b, 0, sizeof (*b));
-}
-
-int
-buf_reserve(struct buf *b, size_t amount)
-{
-	assert(b);
-
-	if (grow(b, amount) < 0)
-		return -1;
-
-	return 0;
-}
-
-int
-buf_resize(struct buf *b, size_t size, char ch)
-{
-	assert(b);
-
-	/* New size is smaller than curren't length, just update it. */
-	if (size < b->length) {
-		b->data[b->length = size] = 0;
-		return 0;
-	}
-
-	/* New size is bigger, data may be reallocated. */
-	if (grow(b, size - b->length) < 0)
-		return -1;
-
-	memset(&b->data[b->length], ch, size - b->length);
-	b->length = size;
-	b->data[b->length] = 0;
-
-	return 0;
-}
-
-int
-buf_shrink(struct buf *b)
-{
-	assert(b);
-
-	void *newptr;
-
-	if (b->length == 0) {
-		free(b->data);
-		b->data = NULL;
-		b->length = b->capacity = 0;
-		return 0;
-	}
-
-	if (!(newptr = BUF_REALLOC(b->data, b->length + 1)))
-		return -1;
-
-	b->data = newptr;
-	b->capacity = b->length;
-
-	return 0;
-}
-
-void
-buf_erase(struct buf *b, size_t pos, size_t count)
-{
-	assert(b);
-	assert(pos <= b->length);
-
-	if (count > b->length - pos) {
-		/* Optimize whole erase at pos. */
-		b->data[pos] = 0;
-		b->length = pos;
-	} else {
-		memmove(&b->data[pos], &b->data[pos + count], b->length - count);
-		b->length -= count;
-	}
-}
-
-int
-buf_putc(struct buf *b, char c)
-{
-	assert(b);
-
-	if (grow(b, 1) < 0)
-		return -1;
-
-	b->data[b->length++] = c;
-	b->data[b->length] = 0;
-
-	return 0;
-}
-
-int
-buf_puts(struct buf *b, const char *s)
-{
-	assert(b);
-	assert(s);
-
-	const size_t len = strlen(s);
-
-	if (grow(b, len) < 0)
-		return -1;
-
-	memcpy(&b->data[b->length], s, len + 1);
-	b->length += len;
-
-	return 0;
-}
-
-int
-buf_printf(struct buf *b, const char *fmt, ...)
-{
-	assert(b);
-	assert(fmt);
-
-	va_list ap;
-	int ret;
-
-	va_start(ap, fmt);
-	ret = buf_vprintf(b, fmt, ap);
-	va_end(ap);
-
-	return ret;
-}
-
-int
-buf_vprintf(struct buf *b, const char *fmt, va_list args)
-{
-	assert(b);
-	assert(fmt);
-
-	va_list ap;
-	int amount;
-
-	/* Determine length. */
-	va_copy(ap, args);
-	amount = vsnprintf(NULL, 0, fmt, ap);
-	va_end(ap);
-
-	if (amount < 0)
-		return -1;
-
-	/* Do actual copy. */
-	if (grow(b, amount) < 0)
-		return -1;
-
-	va_copy(ap, args);
-	amount = vsprintf(&b->data[b->length], fmt, ap);
-	va_end(ap);
-
-	if (amount < 0)
-		return -1;
-
-	b->length += amount;
-
-	return 0;
-}
-
-int
-buf_sub(struct buf *b, const struct buf *src, size_t pos, size_t count)
-{
-	assert(b);
-	assert(src);
-	assert(pos <= src->length);
-
-	if (count >= src->length)
-		count = src->length - pos;
-	if (!(b->data = BUF_MALLOC(count + 1)))
-		return -1;
-
-	strncpy(b->data, &src->data[pos], count);
-	b->length = count;
-	b->capacity = count;
-	b->data[b->length] = 0;
-
-	return 0;
-}
-
-int
-buf_dup(struct buf *b, const struct buf *src)
-{
-	assert(b);
-	assert(src);
-
-	if (!src->data)
-		return 0;
-	if (!(b->data = BUF_MALLOC(src->length + 1)))
-		return -1;
-
-	memcpy(b->data, src->data, src->length + 1);
-	b->capacity = src->length;
-	b->length = src->length;
-
-	return 0;
-}
-
-void
-buf_clear(struct buf *b)
-{
-	assert(b);
-
-	if (b->data)
-		b->data[b->length = 0] = 0;
-}
-
-void
-buf_finish(struct buf *b)
-{
-	assert(b);
-
-	BUF_FREE(b->data);
-	b->data = NULL;
-	b->capacity = b->length = 0;
-}
--- a/src/libmlk-core/core/buf.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * buf.h -- simple string buffer for C
- *
- * Copyright (c) 2019-2022 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.
- */
-
-#ifndef BUF_H
-#define BUF_H
-
-#include <stdarg.h>
-#include <stddef.h>
-
-#include "alloc.h"
-
-#if !defined(BUF_MALLOC)
-#	define BUF_MALLOC alloc_new
-#endif
-
-#if !defined(BUF_REALLOC)
-#	define BUF_REALLOC alloc_renew
-#endif
-
-#if !defined(BUF_FREE)
-#	define BUF_FREE alloc_free
-#endif
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-struct buf {
-	char *data;
-	size_t length;
-	size_t capacity;
-};
-
-void
-buf_init(struct buf *);
-
-int
-buf_reserve(struct buf *, size_t);
-
-int
-buf_resize(struct buf *, size_t, char);
-
-int
-buf_shrink(struct buf *);
-
-void
-buf_erase(struct buf *, size_t, size_t);
-
-int
-buf_putc(struct buf *, char);
-
-int
-buf_puts(struct buf *, const char *);
-
-int
-buf_printf(struct buf *, const char *, ...);
-
-int
-buf_vprintf(struct buf *, const char *, va_list);
-
-int
-buf_sub(struct buf *, const struct buf *, size_t, size_t);
-
-int
-buf_dup(struct buf *, const struct buf *);
-
-void
-buf_clear(struct buf *);
-
-void
-buf_finish(struct buf *);
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif /* !BUF_H */
--- a/src/libmlk-core/core/clock.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * clock.c -- track elapsed time
- *
- * Copyright (c) 2020-2022 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 <SDL.h>
-
-#include "clock.h"
-
-void
-mlk_clock_start(struct mlk_clock *clock)
-{
-	clock->ticks = SDL_GetTicks();
-}
-
-unsigned int
-mlk_clock_elapsed(const struct mlk_clock *clock)
-{
-	return SDL_GetTicks() - clock->ticks;
-}
--- a/src/libmlk-core/core/clock.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * clock.h -- track elapsed time
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_CLOCK_H
-#define MLK_CORE_CLOCK_H
-
-#include "core.h"
-
-struct mlk_clock {
-	unsigned int ticks;
-};
-
-CORE_BEGIN_DECLS
-
-void
-mlk_clock_start(struct mlk_clock *);
-
-unsigned int
-mlk_clock_elapsed(const struct mlk_clock *);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_CLOCK_H */
--- a/src/libmlk-core/core/color.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * color.h -- basic color routines
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_COLOR_H
-#define MLK_CORE_COLOR_H
-
-#define COLOR_R(c)              (c >> 24 & 0xff)
-#define COLOR_G(c)              (c >> 16 & 0xff)
-#define COLOR_B(c)              (c >> 8  & 0xff)
-#define COLOR_A(c)              (c       & 0xff)
-#define COLOR_HEX(r, g, b, a)   \
-        ((r << 24 & 0xff000000) | \
-         (g << 16 & 0x00ff0000) | \
-         (b << 8  & 0x0000ff00) | \
-         (a       & 0x000000ff))
-
-#endif /* !MLK_CORE_COLOR_H */
--- a/src/libmlk-core/core/core.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * core.c -- libcore main entry
- *
- * Copyright (c) 2020-2022 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 <stddef.h>
-#include <stdlib.h>
-#include <time.h>
-
-#include "core.h"
-#include "sys.h"
-
-int
-core_init(const char *organization, const char *name)
-{
-	assert(organization);
-	assert(name);
-
-	srand(time(NULL));
-
-	if (sys_init(organization, name) < 0)
-		return -1;
-
-	return 0;
-}
-
-void
-core_finish(void)
-{
-	sys_finish();
-}
--- a/src/libmlk-core/core/core.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * core.c -- libcore main entry
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_CORE_H
-#define MLK_CORE_CORE_H
-
-#if defined(__cplusplus)
-#       define CORE_BEGIN_DECLS extern "C" {
-#       define CORE_END_DECLS }
-#else
-#       define CORE_BEGIN_DECLS
-#       define CORE_END_DECLS
-#endif
-
-CORE_BEGIN_DECLS
-
-int
-core_init(const char *, const char *);
-
-void
-core_finish(void);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_CORE_H */
--- a/src/libmlk-core/core/drawable-stack.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * drawable-stack.c -- convenient stack of drawables
- *
- * Copyright (c) 2020-2022 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 <string.h>
-
-#include "drawable.h"
-#include "drawable-stack.h"
-#include "err.h"
-
-#define DRAWABLE_FOREACH(st, iter) \
-	for (size_t i = 0; i < (st)->objectsz && ((iter) = (st)->objects[i], 1); ++i)
-
-void
-drawable_stack_init(struct drawable_stack *st, struct drawable **objects, size_t objectsz)
-{
-	assert(st);
-
-	st->objects = objects;
-	st->objectsz = objectsz;
-
-	for (size_t i = 0; i < st->objectsz; ++i)
-		st->objects[i] = NULL;
-}
-
-int
-drawable_stack_add(struct drawable_stack *st, struct drawable *dw)
-{
-	assert(st);
-	assert(dw);
-
-	for (size_t i = 0; i < st->objectsz; ++i) {
-		if (!st->objects[i]) {
-			st->objects[i] = dw;
-			return 0;
-		}
-	}
-
-	return ERR_NO_MEM;
-}
-
-int
-drawable_stack_update(struct drawable_stack *st, unsigned int ticks)
-{
-	assert(st);
-
-	struct drawable *dw;
-
-	for (size_t i = 0; i < st->objectsz; ++i) {
-		dw = st->objects[i];
-
-		if (dw && drawable_update(dw, ticks)) {
-			drawable_end(dw);
-			drawable_finish(dw);
-			st->objects[i] = NULL;
-		}
-	}
-
-	/*
-	 * We process the array again in case a drawable added a new drawable
-	 * within the update function.
-	 */
-	return drawable_stack_completed(st);
-}
-
-void
-drawable_stack_draw(struct drawable_stack *st)
-{
-	assert(st);
-
-	struct drawable *dw;
-
-	DRAWABLE_FOREACH(st, dw)
-		if (dw)
-			drawable_draw(dw);
-}
-
-int
-drawable_stack_completed(const struct drawable_stack *st)
-{
-	assert(st);
-
-	struct drawable *dw;
-
-	DRAWABLE_FOREACH(st, dw)
-		if (dw)
-			return 0;
-
-	return 1;
-}
-
-void
-drawable_stack_finish(struct drawable_stack *st)
-{
-	assert(st);
-
-	struct drawable *dw;
-
-	DRAWABLE_FOREACH(st, dw) {
-		if (dw) {
-			drawable_end(dw);
-			drawable_finish(dw);
-		}
-	}
-
-	memset(st, 0, sizeof (*st));
-}
--- a/src/libmlk-core/core/drawable-stack.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * drawable-stack.h -- convenient stack of drawables
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_DRAWABLE_STACK_H
-#define MLK_CORE_DRAWABLE_STACK_H
-
-#include <stddef.h>
-
-#include "core.h"
-
-struct drawable_stack {
-	struct drawable **objects;
-	size_t objectsz;
-};
-
-CORE_BEGIN_DECLS
-
-void
-drawable_stack_init(struct drawable_stack *, struct drawable **, size_t);
-
-int
-drawable_stack_add(struct drawable_stack *, struct drawable *);
-
-int
-drawable_stack_update(struct drawable_stack *, unsigned int);
-
-void
-drawable_stack_draw(struct drawable_stack *);
-
-int
-drawable_stack_completed(const struct drawable_stack *);
-
-void
-drawable_stack_finish(struct drawable_stack *);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_DRAWABLE_STACK_H */
--- a/src/libmlk-core/core/drawable.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * drawable.c -- automatic drawable objects
- *
- * Copyright (c) 2020-2022 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 "drawable.h"
-
-int
-drawable_update(struct drawable *dw, unsigned int ticks)
-{
-	assert(dw);
-
-	return dw->update(dw, ticks);
-}
-
-void
-drawable_draw(struct drawable *dw)
-{
-	assert(dw);
-
-	dw->draw(dw);
-}
-
-void
-drawable_end(struct drawable *dw)
-{
-	assert(dw);
-
-	if (dw->end)
-		dw->end(dw);
-}
-
-void
-drawable_finish(struct drawable *dw)
-{
-	assert(dw);
-
-	if (dw->finish)
-		dw->finish(dw);
-}
--- a/src/libmlk-core/core/drawable.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * drawable.h -- automatic drawable objects
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_DRAWABLE_H
-#define MLK_CORE_DRAWABLE_H
-
-#include "core.h"
-
-struct drawable {
-	void *data;
-	int x;
-	int y;
-	int (*update)(struct drawable *, unsigned int);
-	void (*draw)(struct drawable *);
-	void (*end)(struct drawable *);
-	void (*finish)(struct drawable *);
-};
-
-CORE_BEGIN_DECLS
-
-int
-drawable_update(struct drawable *, unsigned int);
-
-void
-drawable_draw(struct drawable *);
-
-void
-drawable_end(struct drawable *);
-
-void
-drawable_finish(struct drawable *);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_DRAWABLE_H */
--- a/src/libmlk-core/core/err.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * err.h -- error routines
- *
- * Copyright (c) 2020-2022 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 <SDL.h>
-
-#include "err.h"
-
-const char *
-err_string(int e)
-{
-	switch (e) {
-	case ERR_SDL:
-		return SDL_GetError();
-	case ERR_NO_MEM:
-		return "out of memory";
-	case ERR_NO_SUPPORT:
-		return "operation not supported";
-	default:
-		return "no error";
-	}
-}
--- a/src/libmlk-core/core/err.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * err.h -- error handing
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_ERR_H
-#define MLK_ERR_H
-
-#define ERR_NONE         0
-#define ERR_SDL         -1
-#define ERR_NO_MEM      -2
-#define ERR_NO_SUPPORT  -3
-
-const char *
-err_string(int e);
-
-#endif /* !MLK_ERROR_H */
--- a/src/libmlk-core/core/error.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * error.c -- error routines
- *
- * Copyright (c) 2020-2022 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 <stdio.h>
-
-#include "error.h"
-
-#include <SDL.h>
-
-static char buffer[2048];
-
-const char *
-error(void)
-{
-	return buffer;
-}
-
-int
-errorf(const char *fmt, ...)
-{
-	assert(fmt);
-
-	va_list ap;
-
-	va_start(ap, fmt);
-	errorva(fmt, ap);
-	va_end(ap);
-
-	return -1;
-}
-
-int
-errorva(const char *fmt, va_list ap)
-{
-	assert(fmt);
-
-	vsnprintf(buffer, sizeof (buffer), fmt, ap);
-
-	return -1;
-}
--- a/src/libmlk-core/core/error.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * error.h -- error routines
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_ERROR_H
-#define MLK_CORE_ERROR_H
-
-#include <stdarg.h>
-
-#include "core.h"
-
-CORE_BEGIN_DECLS
-
-const char *
-error(void);
-
-int
-errorf(const char *, ...);
-
-int
-errorva(const char *, va_list);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_ERROR_H */
--- a/src/libmlk-core/core/event.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,256 +0,0 @@
-/*
- * event.c -- event management
- *
- * Copyright (c) 2020-2022 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 <SDL.h>
-
-#include "event.h"
-
-/* Maintain with enum key constants in key.h */
-static const struct {
-	SDL_Keycode key;
-	enum key value;
-} keymap[] = {
-	{ SDLK_RETURN,          KEY_ENTER               },
-	{ SDLK_ESCAPE,          KEY_ESCAPE              },
-	{ SDLK_BACKSPACE,       KEY_BACKSPACE           },
-	{ SDLK_TAB,             KEY_TAB                 },
-	{ SDLK_SPACE,           KEY_SPACE               },
-	{ SDLK_EXCLAIM,         KEY_EXCLAIM             },
-	{ SDLK_QUOTEDBL,        KEY_DOUBLE_QUOTE        },
-	{ SDLK_HASH,            KEY_HASH                },
-	{ SDLK_PERCENT,         KEY_PERCENT             },
-	{ SDLK_DOLLAR,          KEY_DOLLAR              },
-	{ SDLK_AMPERSAND,       KEY_AMPERSAND           },
-	{ SDLK_QUOTE,           KEY_QUOTE               },
-	{ SDLK_LEFTPAREN,       KEY_LEFT_PAREN          },
-	{ SDLK_RIGHTPAREN,      KEY_RIGHT_PAREN         },
-	{ SDLK_ASTERISK,        KEY_ASTERISK            },
-	{ SDLK_PLUS,            KEY_PLUS                },
-	{ SDLK_COMMA,           KEY_COMMA               },
-	{ SDLK_MINUS,           KEY_MINUS               },
-	{ SDLK_PERIOD,          KEY_PERIOD              },
-	{ SDLK_SLASH,           KEY_SLASH               },
-	{ SDLK_0,               KEY_0                   },
-	{ SDLK_1,               KEY_1                   },
-	{ SDLK_2,               KEY_2                   },
-	{ SDLK_3,               KEY_3                   },
-	{ SDLK_4,               KEY_4                   },
-	{ SDLK_5,               KEY_5                   },
-	{ SDLK_6,               KEY_6                   },
-	{ SDLK_7,               KEY_7                   },
-	{ SDLK_8,               KEY_8                   },
-	{ SDLK_9,               KEY_9                   },
-	{ SDLK_COLON,           KEY_COLON               },
-	{ SDLK_SEMICOLON,       KEY_SEMICOLON           },
-	{ SDLK_LESS,            KEY_LESS                },
-	{ SDLK_EQUALS,          KEY_EQUALS              },
-	{ SDLK_GREATER,         KEY_GREATER             },
-	{ SDLK_QUESTION,        KEY_QUESTION            },
-	{ SDLK_AT,              KEY_AT                  },
-	{ SDLK_LEFTBRACKET,     KEY_LEFT_BRACKET        },
-	{ SDLK_BACKSLASH,       KEY_BACKSLASH           },
-	{ SDLK_RIGHTBRACKET,    KEY_RIGHT_BRACKET       },
-	{ SDLK_CARET,           KEY_CARET               },
-	{ SDLK_UNDERSCORE,      KEY_UNDERSCORE          },
-	{ SDLK_BACKQUOTE,       KEY_BACKQUOTE           },
-	{ SDLK_a,               KEY_a                   },
-	{ SDLK_b,               KEY_b                   },
-	{ SDLK_c,               KEY_c                   },
-	{ SDLK_d,               KEY_d                   },
-	{ SDLK_e,               KEY_e                   },
-	{ SDLK_f,               KEY_f                   },
-	{ SDLK_g,               KEY_g                   },
-	{ SDLK_h,               KEY_h                   },
-	{ SDLK_i,               KEY_i                   },
-	{ SDLK_j,               KEY_j                   },
-	{ SDLK_k,               KEY_k                   },
-	{ SDLK_l,               KEY_l                   },
-	{ SDLK_m,               KEY_m                   },
-	{ SDLK_n,               KEY_n                   },
-	{ SDLK_o,               KEY_o                   },
-	{ SDLK_p,               KEY_p                   },
-	{ SDLK_q,               KEY_q                   },
-	{ SDLK_r,               KEY_r                   },
-	{ SDLK_s,               KEY_s                   },
-	{ SDLK_t,               KEY_t                   },
-	{ SDLK_u,               KEY_u                   },
-	{ SDLK_v,               KEY_v                   },
-	{ SDLK_w,               KEY_w                   },
-	{ SDLK_x,               KEY_x                   },
-	{ SDLK_y,               KEY_y                   },
-	{ SDLK_z,               KEY_z                   },
-	{ SDLK_CAPSLOCK,        KEY_CAPSLOCK            },
-	{ SDLK_F1,              KEY_F1                  },
-	{ SDLK_F2,              KEY_F2                  },
-	{ SDLK_F3,              KEY_F3                  },
-	{ SDLK_F4,              KEY_F4                  },
-	{ SDLK_F5,              KEY_F5                  },
-	{ SDLK_F6,              KEY_F6                  },
-	{ SDLK_F7,              KEY_F7                  },
-	{ SDLK_F8,              KEY_F8                  },
-	{ SDLK_F9,              KEY_F9                  },
-	{ SDLK_F10,             KEY_F10                 },
-	{ SDLK_F11,             KEY_F11                 },
-	{ SDLK_F12,             KEY_F12                 },
-	{ SDLK_F13,             KEY_F13                 },
-	{ SDLK_F14,             KEY_F14                 },
-	{ SDLK_F15,             KEY_F15                 },
-	{ SDLK_F16,             KEY_F16                 },
-	{ SDLK_F17,             KEY_F17                 },
-	{ SDLK_F18,             KEY_F18                 },
-	{ SDLK_F19,             KEY_F19                 },
-	{ SDLK_F20,             KEY_F20                 },
-	{ SDLK_F21,             KEY_F21                 },
-	{ SDLK_F22,             KEY_F22                 },
-	{ SDLK_F23,             KEY_F23                 },
-	{ SDLK_F24,             KEY_F24                 },
-	{ SDLK_PRINTSCREEN,     KEY_PRINTSCREEN         },
-	{ SDLK_SCROLLLOCK,      KEY_SCROLL_LOCK         },
-	{ SDLK_PAUSE,           KEY_PAUSE               },
-	{ SDLK_INSERT,          KEY_INSERT              },
-	{ SDLK_HOME,            KEY_HOME                },
-	{ SDLK_PAGEUP,          KEY_PAGEUP              },
-	{ SDLK_DELETE,          KEY_DELETE              },
-	{ SDLK_END,             KEY_END                 },
-	{ SDLK_PAGEDOWN,        KEY_PAGEDOWN            },
-	{ SDLK_RIGHT,           KEY_RIGHT               },
-	{ SDLK_LEFT,            KEY_LEFT                },
-	{ SDLK_DOWN,            KEY_DOWN                },
-	{ SDLK_UP,              KEY_UP                  },
-	{ SDLK_KP_DIVIDE,       KEY_KP_DIVIDE           },
-	{ SDLK_KP_MULTIPLY,     KEY_KP_MULTIPLY         },
-	{ SDLK_KP_MINUS,        KEY_KP_MINUS            },
-	{ SDLK_KP_PLUS,         KEY_KP_PLUS             },
-	{ SDLK_KP_ENTER,        KEY_KP_ENTER            },
-	{ SDLK_KP_1,            KEY_KP_1                },
-	{ SDLK_KP_2,            KEY_KP_2                },
-	{ SDLK_KP_3,            KEY_KP_3                },
-	{ SDLK_KP_4,            KEY_KP_4                },
-	{ SDLK_KP_5,            KEY_KP_5                },
-	{ SDLK_KP_6,            KEY_KP_6                },
-	{ SDLK_KP_7,            KEY_KP_7                },
-	{ SDLK_KP_8,            KEY_KP_8                },
-	{ SDLK_KP_9,            KEY_KP_9                },
-	{ SDLK_KP_0,            KEY_KP_0                },
-	{ SDLK_KP_PERIOD,       KEY_KP_PERIOD           },
-	{ SDLK_KP_COMMA,        KEY_KP_COMMA            },
-	{ SDLK_MENU,            KEY_MENU                },
-	{ SDLK_MUTE,            KEY_MUTE                },
-	{ SDLK_VOLUMEUP,        KEY_VOLUME_UP           },
-	{ SDLK_VOLUMEDOWN,      KEY_VOLUME_DOWN         },
-	{ SDLK_LCTRL,           KEY_LCTRL               },
-	{ SDLK_LSHIFT,          KEY_LSHIFT              },
-	{ SDLK_LALT,            KEY_LALT                },
-	{ SDLK_LGUI,            KEY_LSUPER              },
-	{ SDLK_RCTRL,           KEY_RCTRL               },
-	{ SDLK_RSHIFT,          KEY_RSHIFT              },
-	{ SDLK_RALT,            KEY_RALT                },
-	{ SDLK_RGUI,            KEY_RSUPER              },
-	{ 0,                    -1                      }
-};
-
-/* Maintain with enum mouse_button constants in mouse.h */
-static const struct {
-	int key;
-	enum mouse_button value;
-} buttons[] = {
-	{ SDL_BUTTON_LEFT,      MOUSE_BUTTON_LEFT       },
-	{ SDL_BUTTON_MIDDLE,    MOUSE_BUTTON_MIDDLE     },
-	{ SDL_BUTTON_RIGHT,     MOUSE_BUTTON_RIGHT      },
-	{ -1,                   MOUSE_BUTTON_NONE       }
-};
-
-static void
-convert_key(const SDL_Event *event, union event *ev)
-{
-	ev->type = event->type == SDL_KEYDOWN ? EVENT_KEYDOWN : EVENT_KEYUP;
-	ev->key.key = KEY_UNKNOWN;
-
-	for (size_t i = 0; keymap[i].key != 0; ++i) {
-		if (keymap[i].key == event->key.keysym.sym) {
-			ev->key.key = keymap[i].value;
-			break;
-		}
-	}
-}
-
-static void
-convert_mouse(const SDL_Event *event, union event *ev)
-{
-	ev->type = EVENT_MOUSE;
-	ev->mouse.buttons = 0;
-	ev->mouse.x = event->motion.x;
-	ev->mouse.y = event->motion.y;
-
-	if (event->motion.state & SDL_BUTTON_LMASK)
-		ev->mouse.buttons |= MOUSE_BUTTON_LEFT;
-	if (event->motion.state & SDL_BUTTON_MMASK)
-		ev->mouse.buttons |= MOUSE_BUTTON_MIDDLE;
-	if (event->motion.state & SDL_BUTTON_RMASK)
-		ev->mouse.buttons |= MOUSE_BUTTON_RIGHT;
-}
-
-static void
-convert_click(const SDL_Event *event, union event *ev)
-{
-	ev->type = event->type == SDL_MOUSEBUTTONDOWN ? EVENT_CLICKDOWN : EVENT_CLICKUP;
-	ev->click.button = MOUSE_BUTTON_NONE;
-	ev->click.x = event->button.x;
-	ev->click.y = event->button.y;
-	ev->click.clicks = event->button.clicks;
-
-	for (size_t i = 0; buttons[i].value != MOUSE_BUTTON_NONE; ++i) {
-		if (buttons[i].key == event->button.button) {
-			ev->click.button = buttons[i].value;
-			break;
-		}
-	}
-}
-
-int
-event_poll(union event *ev)
-{
-	SDL_Event event;
-
-	/*
-	 * Loop until we find an event we want to report, we skip unneeded
-	 * ones.
-	 */
-	while (SDL_PollEvent(&event)) {
-		switch (event.type) {
-		case SDL_QUIT:
-			ev->type = EVENT_QUIT;
-			return 1;
-		case SDL_KEYDOWN:
-		case SDL_KEYUP:
-			convert_key(&event, ev);
-			return 1;
-		case SDL_MOUSEMOTION:
-			convert_mouse(&event, ev);
-			return 1;
-		case SDL_MOUSEBUTTONDOWN:
-		case SDL_MOUSEBUTTONUP:
-			convert_click(&event, ev);
-			return 1;
-		default:
-			continue;
-		}
-	}
-
-	return 0;
-}
--- a/src/libmlk-core/core/event.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * event.h -- event management
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_EVENT_H
-#define MLK_CORE_EVENT_H
-
-#include "core.h"
-#include "key.h"
-#include "mouse.h"
-
-enum event_type {
-	EVENT_CLICKDOWN,
-	EVENT_CLICKUP,
-	EVENT_KEYDOWN,
-	EVENT_KEYUP,
-	EVENT_MOUSE,
-	EVENT_QUIT,
-	EVENT_NUM
-};
-
-struct event_key {
-	enum event_type type;
-	enum key key;
-};
-
-struct event_mouse {
-	enum event_type type;
-	enum mouse_button buttons;
-	int x;
-	int y;
-};
-
-struct event_click {
-	enum event_type type;
-	enum mouse_button button;
-	int x;
-	int y;
-	unsigned int clicks;
-};
-
-union event {
-	enum event_type type;
-	struct event_key key;
-	struct event_mouse mouse;
-	struct event_click click;
-};
-
-CORE_BEGIN_DECLS
-
-int
-event_poll(union event *);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_EVENT_H */
--- a/src/libmlk-core/core/font.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/*
- * font.c -- basic font management
- *
- * Copyright (c) 2020-2022 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 <string.h>
-
-#include <SDL_ttf.h>
-
-#include "color.h"
-#include "err.h"
-#include "error.h"
-#include "font.h"
-#include "texture_p.h"
-#include "util.h"
-
-int
-font_open(struct font *font, const char *path, unsigned int size)
-{
-	assert(font);
-	assert(path);
-
-	if (!(font->handle = TTF_OpenFont(path, size)))
-		return ERR_SDL;
-
-	return 0;
-}
-
-int
-font_openmem(struct font *font, const void *buffer, size_t buflen, unsigned int size)
-{
-	assert(font);
-	assert(buffer);
-
-	SDL_RWops *ops;
-
-	if (!(ops = SDL_RWFromConstMem(buffer, buflen)) ||
-	   (!(font->handle = TTF_OpenFontRW(ops, 1, size))))
-		return ERR_SDL;
-
-	return 0;
-}
-
-int
-font_ok(const struct font *font)
-{
-	return font && font->handle;
-}
-
-int
-font_render(struct font *font, struct texture *tex, const char *text, unsigned long color)
-{
-	assert(font_ok(font));
-	assert(text);
-
-	SDL_Color fg = {
-		.r = COLOR_R(color),
-		.g = COLOR_G(color),
-		.b = COLOR_B(color),
-		.a = COLOR_A(color)
-	};
-	SDL_Surface *surface;
-	SDL_Surface *(*func)(TTF_Font *, const char *, SDL_Color);
-
-	switch (font->style) {
-	case FONT_STYLE_ANTIALIASED:
-		func = TTF_RenderUTF8_Blended;
-		break;
-	default:
-		func = TTF_RenderUTF8_Solid;
-		break;
-	}
-
-	if (!(surface = func(font->handle, text, fg)))
-		return ERR_SDL;
-
-	return texture_from_surface(tex, surface);
-}
-
-unsigned int
-font_height(const struct font *font)
-{
-	assert(font_ok(font));
-
-	return TTF_FontHeight(font->handle);
-}
-
-int
-font_query(const struct font *font, const char *text, unsigned int *w, unsigned int *h)
-{
-	assert(font_ok(font));
-	assert(text);
-
-	if (w)
-		*w = 0;
-	if (h)
-		*h = 0;
-
-	if (TTF_SizeUTF8(font->handle, text, (int *)w, (int *)h) != 0)
-		return ERR_SDL;
-
-	return 0;
-}
-
-void
-font_finish(struct font *font)
-{
-	assert(font);
-
-	if (font->handle)
-		TTF_CloseFont(font->handle);
-
-	memset(font, 0, sizeof (*font));
-}
--- a/src/libmlk-core/core/font.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * font.h -- basic font management
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_FONT_H
-#define MLK_CORE_FONT_H
-
-#include <stddef.h>
-
-#include "core.h"
-
-struct texture;
-
-enum font_style {
-	FONT_STYLE_ANTIALIASED,
-	FONT_STYLE_NONE,
-	FONT_STYLE_LAST
-};
-
-struct font {
-	enum font_style style;
-	void *handle;
-};
-
-CORE_BEGIN_DECLS
-
-int
-font_open(struct font *, const char *, unsigned int);
-
-int
-font_openmem(struct font *, const void *, size_t, unsigned int);
-
-int
-font_ok(const struct font *);
-
-int
-font_render(struct font *, struct texture *, const char *, unsigned long);
-
-unsigned int
-font_height(const struct font *);
-
-int
-font_query(const struct font *, const char *, unsigned int *, unsigned int *);
-
-void
-font_finish(struct font *);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_FONT_H */
--- a/src/libmlk-core/core/game.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-/*
- * game.c -- main game object
- *
- * Copyright (c) 2020-2022 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 <string.h>
-
-#include "clock.h"
-#include "event.h"
-#include "game.h"
-#include "state.h"
-#include "util.h"
-#include "window.h"
-
-struct game game = {0};
-
-void
-game_init(struct state **states, size_t statesz)
-{
-	assert(states);
-	assert(statesz);
-
-	memset(&game, 0, sizeof (game));
-
-	game.states = states;
-	game.statesz = statesz;
-
-	for (size_t i = 0; i < game.statesz; ++i)
-		game.states[i] = NULL;
-}
-
-void
-game_push(struct state *state)
-{
-	assert(state);
-	assert(!game.state || game.state != &game.states[game.statesz - 1]);
-
-	if (!game.state) {
-		game.state = &game.states[0];
-		state_start(*game.state = state);
-	} else {
-		state_suspend(*game.state);
-		state_start(*(++game.state) = state);
-	}
-}
-
-void
-game_pop(void)
-{
-	assert(game.state);
-
-	state_end(*game.state);
-	state_finish(*game.state);
-
-	if (game.state == game.states)
-		game.state = NULL;
-	else
-		state_resume(*--game.state);
-}
-
-void
-game_handle(const union event *ev)
-{
-	assert(ev);
-
-	if (*game.state && !(game.inhibit & INHIBIT_STATE_INPUT))
-		state_handle(*game.state, ev);
-}
-
-void
-game_update(unsigned int ticks)
-{
-	if (*game.state && !(game.inhibit & INHIBIT_STATE_UPDATE))
-		state_update(*game.state, ticks);
-}
-
-void
-game_draw(void)
-{
-	if (*game.state && !(game.inhibit & INHIBIT_STATE_DRAW))
-		state_draw(*game.state);
-}
-
-void
-game_loop(void)
-{
-	struct mlk_clock clock = {0};
-	unsigned int elapsed = 0;
-	unsigned int frametime;
-
-	if (window.framerate > 0)
-		frametime = 1000 / window.framerate;
-	else
-		/* Assuming 50.0 FPS. */
-		frametime = 1000.0 / 50.0;
-
-	while (*game.state) {
-		mlk_clock_start(&clock);
-
-		for (union event ev; event_poll(&ev); )
-			game_handle(&ev);
-
-		game_update(elapsed);
-		game_draw();
-
-		/*
-		 * If vsync is enabled, it should have wait, otherwise sleep
-		 * a little to save CPU cycles.
-		 */
-		if ((elapsed = mlk_clock_elapsed(&clock)) < frametime)
-			util_delay(frametime - elapsed);
-
-		elapsed = mlk_clock_elapsed(&clock);
-	}
-}
-
-void
-game_quit(void)
-{
-	for (size_t i = 0; i < game.statesz; ++i) {
-		if (game.states[i])
-			state_finish(game.states[i]);
-
-		game.states[i] = NULL;
-	}
-}
--- a/src/libmlk-core/core/game.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * game.h -- main game object
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_GAME_H
-#define MLK_CORE_GAME_H
-
-#include <stddef.h>
-
-#include "core.h"
-#include "inhibit.h"
-
-struct state;
-
-union event;
-
-struct game {
-	enum inhibit inhibit;
-	struct state **states;
-	size_t statesz;
-	struct state **state;
-};
-
-extern struct game game;
-
-CORE_BEGIN_DECLS
-
-void
-game_init(struct state **, size_t);
-
-void
-game_push(struct state *);
-
-void
-game_pop(void);
-
-void
-game_handle(const union event *);
-
-void
-game_update(unsigned int);
-
-void
-game_draw(void);
-
-void
-game_loop(void);
-
-void
-game_quit(void);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_GAME_H */
--- a/src/libmlk-core/core/image.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * image.c -- basic image management
- *
- * Copyright (c) 2020-2022 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 <SDL_image.h>
-
-#include "error.h"
-#include "texture.h"
-#include "window.h"
-#include "window_p.h"
-
-static void
-dimensions(struct texture *tex)
-{
-	int w, h;
-
-	if (SDL_QueryTexture(tex->handle, NULL, NULL, &w, &h) < 0)
-		tex->w = tex->h = 0;
-	else {
-		tex->w = w;
-		tex->h = h;
-	}
-}
-
-int
-image_open(struct texture *tex, const char *path)
-{
-	assert(tex);
-	assert(path);
-
-	if (!(tex->handle = IMG_LoadTexture(RENDERER(), path)))
-		return ERR_SDL;
-
-	dimensions(tex);
-
-	return 0;
-}
-
-int
-image_openmem(struct texture *tex, const void *buffer, size_t size)
-{
-	assert(buffer);
-
-	SDL_RWops *ops = SDL_RWFromConstMem(buffer, size);
-
-	if (!ops || !(tex->handle = IMG_LoadTexture_RW(RENDERER(), ops, 1)))
-		return ERR_SDL;
-
-	dimensions(tex);
-
-	return 0;
-}
--- a/src/libmlk-core/core/image.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * image.h -- basic image management
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_IMAGE_H
-#define MLK_CORE_IMAGE_H
-
-#include <stddef.h>
-
-#include "core.h"
-
-struct texture;
-
-CORE_BEGIN_DECLS
-
-int
-image_open(struct texture *, const char *);
-
-int
-image_openmem(struct texture *, const void *, size_t);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_IMAGE_H */
--- a/src/libmlk-core/core/inhibit.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * inhibit.h -- disable specific game behavior
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_INHIBIT_H
-#define MLK_CORE_INHIBIT_H
-
-enum inhibit {
-	INHIBIT_NONE,
-	INHIBIT_STATE_INPUT        = (1 << 0),
-	INHIBIT_STATE_UPDATE       = (1 << 1),
-	INHIBIT_STATE_DRAW         = (1 << 2)
-};
-
-#endif /* !MLK_CORE_INHIBIT_H */
--- a/src/libmlk-core/core/key.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-/*
- * key.h -- keyboard definitions
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_KEY_H
-#define MLK_CORE_KEY_H
-
-enum key {
-	KEY_UNKNOWN,
-	KEY_ENTER,
-	KEY_ESCAPE,
-	KEY_BACKSPACE,
-	KEY_TAB,
-	KEY_SPACE,
-	KEY_EXCLAIM,
-	KEY_DOUBLE_QUOTE,
-	KEY_HASH,
-	KEY_PERCENT,
-	KEY_DOLLAR,
-	KEY_AMPERSAND,
-	KEY_QUOTE,
-	KEY_LEFT_PAREN,
-	KEY_RIGHT_PAREN,
-	KEY_ASTERISK,
-	KEY_PLUS,
-	KEY_COMMA,
-	KEY_MINUS,
-	KEY_PERIOD,
-	KEY_SLASH,
-	KEY_0,
-	KEY_1,
-	KEY_2,
-	KEY_3,
-	KEY_4,
-	KEY_5,
-	KEY_6,
-	KEY_7,
-	KEY_8,
-	KEY_9,
-	KEY_COLON,
-	KEY_SEMICOLON,
-	KEY_LESS,
-	KEY_EQUALS,
-	KEY_GREATER,
-	KEY_QUESTION,
-	KEY_AT,
-	KEY_LEFT_BRACKET,
-	KEY_BACKSLASH,
-	KEY_RIGHT_BRACKET,
-	KEY_CARET,
-	KEY_UNDERSCORE,
-	KEY_BACKQUOTE,
-	KEY_a,
-	KEY_b,
-	KEY_c,
-	KEY_d,
-	KEY_e,
-	KEY_f,
-	KEY_g,
-	KEY_h,
-	KEY_i,
-	KEY_j,
-	KEY_k,
-	KEY_l,
-	KEY_m,
-	KEY_n,
-	KEY_o,
-	KEY_p,
-	KEY_q,
-	KEY_r,
-	KEY_s,
-	KEY_t,
-	KEY_u,
-	KEY_v,
-	KEY_w,
-	KEY_x,
-	KEY_y,
-	KEY_z,
-	KEY_CAPSLOCK,
-	KEY_F1,
-	KEY_F2,
-	KEY_F3,
-	KEY_F4,
-	KEY_F5,
-	KEY_F6,
-	KEY_F7,
-	KEY_F8,
-	KEY_F9,
-	KEY_F10,
-	KEY_F11,
-	KEY_F12,
-	KEY_F13,
-	KEY_F14,
-	KEY_F15,
-	KEY_F16,
-	KEY_F17,
-	KEY_F18,
-	KEY_F19,
-	KEY_F20,
-	KEY_F21,
-	KEY_F22,
-	KEY_F23,
-	KEY_F24,
-	KEY_PRINTSCREEN,
-	KEY_SCROLL_LOCK,
-	KEY_PAUSE,
-	KEY_INSERT,
-	KEY_HOME,
-	KEY_PAGEUP,
-	KEY_DELETE,
-	KEY_END,
-	KEY_PAGEDOWN,
-	KEY_RIGHT,
-	KEY_LEFT,
-	KEY_DOWN,
-	KEY_UP,
-	KEY_NUMLOCKCLEAR,
-	KEY_KP_DIVIDE,
-	KEY_KP_MULTIPLY,
-	KEY_KP_MINUS,
-	KEY_KP_PLUS,
-	KEY_KP_ENTER,
-	KEY_KP_00,
-	KEY_KP_000,
-	KEY_KP_1,
-	KEY_KP_2,
-	KEY_KP_3,
-	KEY_KP_4,
-	KEY_KP_5,
-	KEY_KP_6,
-	KEY_KP_7,
-	KEY_KP_8,
-	KEY_KP_9,
-	KEY_KP_0,
-	KEY_KP_PERIOD,
-	KEY_KP_COMMA,
-	KEY_MENU,
-	KEY_MUTE,
-	KEY_VOLUME_UP,
-	KEY_VOLUME_DOWN,
-	KEY_LCTRL,
-	KEY_LSHIFT,
-	KEY_LALT,
-	KEY_LSUPER,
-	KEY_RCTRL,
-	KEY_RSHIFT,
-	KEY_RALT,
-	KEY_RSUPER,
-};
-
-enum keymod {
-	KEYMOD_LSHIFT   = 1 << 0,
-	KEYMOD_LCTRL    = 1 << 1,
-	KEYMOD_LALT     = 1 << 2,
-	KEYMOD_LSUPER   = 1 << 3,
-	KEYMOD_RSHIFT   = 1 << 4,
-	KEYMOD_RCTRL    = 1 << 5,
-	KEYMOD_RALT     = 1 << 6,
-	KEYMOD_RSUPER   = 1 << 7 
-};
-
-#endif /* !MLK_CORE_KEY_H */
--- a/src/libmlk-core/core/maths.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * maths.c -- basic maths
- *
- * Copyright (c) 2020-2022 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 "maths.h"
-
-int
-maths_is_boxed(int x, int y, unsigned int w, unsigned int h, int px, int py)
-{
-	return px > x &&
-	       py > y &&
-	       px < x + (int)w &&
-	       py < y + (int)h;
-}
-
-float
-maths_scale(float in, float old_min, float old_max, float new_min, float new_max)
-{
-	return (in / ((old_max - old_min) / (new_max - new_min))) + new_min;
-}
--- a/src/libmlk-core/core/maths.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * maths.h -- basic maths
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_MATHS_H
-#define MLK_CORE_MATHS_H
-
-#include "core.h"
-
-CORE_BEGIN_DECLS
-
-int
-maths_is_boxed(int, int, unsigned int, unsigned int, int, int);
-
-float
-maths_scale(float, float, float, float, float);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_MATHS_H */
--- a/src/libmlk-core/core/mouse.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * mouse.h -- mouse definitions
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_MOUSE_H
-#define MLK_CORE_MOUSE_H
-
-enum mouse_button {
-	MOUSE_BUTTON_NONE       = 0,
-	MOUSE_BUTTON_LEFT       = (1 << 0),
-	MOUSE_BUTTON_MIDDLE     = (1 << 1),
-	MOUSE_BUTTON_RIGHT      = (1 << 2)
-};
-
-#endif /* !MLK_CORE_MOUSE_H */
--- a/src/libmlk-core/core/music.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * music.h -- music support
- *
- * Copyright (c) 2020-2022 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 <string.h>
-
-#include "err.h"
-#include "music.h"
-#include "sys_p.h"
-
-#define SOURCE(mus) ((const struct audiostream *)mus->handle)->source
-
-int
-music_open(struct music *mus, const char *path)
-{
-	assert(mus);
-	assert(path);
-
-	if (!(mus->handle = audiostream_open(path)))
-		return -1;
-
-	return 0;
-}
-
-int
-music_openmem(struct music *mus, const void *buffer, size_t buffersz)
-{
-	assert(mus);
-	assert(buffer);
-
-	if (!(mus->handle = audiostream_openmem(buffer, buffersz)))
-		return -1;
-
-	return 0;
-}
-
-int
-music_ok(const struct music *mus)
-{
-	return mus && mus->handle;
-}
-
-int
-music_play(struct music *mus, enum music_flags flags)
-{
-	assert(mus);
-
-	if (flags & MUSIC_LOOP)
-		alSourcei(SOURCE(mus), AL_LOOPING, AL_TRUE);
-	else
-		alSourcei(SOURCE(mus), AL_LOOPING, AL_TRUE);
-
-	alSourceRewind(SOURCE(mus));
-	alSourcePlay(SOURCE(mus));
-
-	return 0;
-}
-
-void
-music_pause(struct music *mus)
-{
-	assert(music_ok(mus));
-
-	alSourcePause(SOURCE(mus));
-}
-
-void
-music_resume(struct music *mus)
-{
-	assert(music_ok(mus));
-
-	alSourcePlay(SOURCE(mus));
-}
-
-void
-music_stop(struct music *mus)
-{
-	assert(music_ok(mus));
-
-	alSourceStop(SOURCE(mus));
-}
-
-void
-music_finish(struct music *mus)
-{
-	assert(mus);
-
-	if (mus->handle) {
-		music_stop(mus);
-		audiostream_finish(mus->handle);
-	}
-
-	memset(mus, 0, sizeof (*mus));
-}
--- a/src/libmlk-core/core/music.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * music.h -- music support
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_MUSIC_H
-#define MLK_CORE_MUSIC_H
-
-#include <stddef.h>
-
-#include "core.h"
-
-enum music_flags {
-	MUSIC_NONE      = 0,
-	MUSIC_LOOP      = (1 << 0)
-};
-
-struct music {
-	void *handle;
-};
-
-CORE_BEGIN_DECLS
-
-int
-music_open(struct music *, const char *);
-
-int
-music_openmem(struct music *, const void *, size_t);
-
-int
-music_ok(const struct music *);
-
-int
-music_play(struct music *, enum music_flags);
-
-void
-music_pause(struct music *);
-
-void
-music_resume(struct music *);
-
-void
-music_stop(struct music *);
-
-void
-music_finish(struct music *);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_MUSIC_H */
--- a/src/libmlk-core/core/painter.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * painter.c -- basic drawing routines
- *
- * Copyright (c) 2020-2022 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 <math.h>
-
-#include "color.h"
-#include "painter.h"
-#include "texture.h"
-#include "window.h"
-#include "window_p.h"
-
-/* Current texture renderer. */
-static struct texture *renderer;
-
-struct texture *
-painter_get_target(void)
-{
-	return renderer;
-}
-
-void
-painter_set_target(struct texture *tex)
-{
-	renderer = tex;
-	SDL_SetRenderTarget(RENDERER(), tex ? tex->handle : NULL);
-}
-
-unsigned long
-painter_get_color(void)
-{
-	Uint8 r = 0, g = 0, b = 0, a = 0;
-
-	SDL_GetRenderDrawColor(RENDERER(), &r, &g, &b, &a);
-
-	return COLOR_HEX(r, g, b, a);
-}
-
-void
-painter_set_color(unsigned long color)
-{
-	SDL_SetRenderDrawColor(
-		RENDERER(),
-		COLOR_R(color),
-		COLOR_G(color),
-		COLOR_B(color),
-		COLOR_A(color)
-	);
-}
-
-void
-painter_draw_line(int x1, int y1, int x2, int y2)
-{
-	SDL_RenderDrawLine(RENDERER(), x1, y1, x2, y2);
-}
-
-void
-painter_draw_point(int x1, int y1)
-{
-	SDL_RenderDrawPoint(RENDERER(), x1, y1);
-}
-
-void
-painter_draw_rectangle(int x, int y, unsigned int width, unsigned int height)
-{
-	const SDL_Rect rect = {
-		.w = width,
-		.h = height,
-		.x = x,
-		.y = y
-	};
-
-	SDL_RenderFillRect(RENDERER(), &rect);
-}
-
-void
-painter_draw_circle(int x, int y, int radius)
-{
-	// Note that there is more to altering the bitrate of this 
-	// method than just changing this value.  See how pixels are
-	// altered at the following web page for tips:
-	//   http://www.libsdl.org/intro.en/usingvideo.html
-	for (double dy = 1; dy <= radius; dy += 1.0) {
-		double dx = floor(sqrt((2.0 * radius * dy) - (dy * dy)));
-
-		SDL_RenderDrawLine(RENDERER(), x - dx, y + dy - radius, x + dx, y + dy - radius);
-		SDL_RenderDrawLine(RENDERER(), x - dx, y - dy + radius, x + dx, y - dy + radius);
-	}
-}
-
-void
-painter_clear(void)
-{
-	SDL_RenderClear(RENDERER());
-}
-
-void
-painter_present(void)
-{
-	SDL_RenderPresent(RENDERER());
-}
--- a/src/libmlk-core/core/painter.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * painter.h -- basic drawing routines
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_PAINTER_H
-#define MLK_CORE_PAINTER_H
-
-#include "core.h"
-
-struct texture;
-
-CORE_BEGIN_DECLS
-
-struct texture *
-painter_get_target(void);
-
-void
-painter_set_target(struct texture *);
-
-unsigned long
-painter_get_color(void);
-
-void
-painter_set_color(unsigned long);
-
-void
-painter_draw_line(int, int, int, int);
-
-void
-painter_draw_point(int, int);
-
-void
-painter_draw_rectangle(int, int, unsigned int, unsigned int);
-
-void
-painter_draw_circle(int, int, int);
-
-void
-painter_clear(void);
-
-void
-painter_present(void);
-
-CORE_END_DECLS
-
-#define PAINTER_BEGIN(tex)                                              \
-do {                                                                    \
-        struct texture *__current_texture__;                            \
-                                                                        \
-        __current_texture__ = painter_get_target();                     \
-        painter_set_target((tex))
-
-#define PAINTER_END()                                                   \
-        painter_set_target(__current_texture__);                        \
-} while (0)
-
-#endif /* !MLK_CORE_PAINTER_H */
--- a/src/libmlk-core/core/panic.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * panic.c -- unrecoverable error handling
- *
- * Copyright (c) 2020-2022 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 <stdio.h>
-#include <stdlib.h>
-
-#include "error.h"
-#include "panic.h"
-
-static void
-terminate(void)
-{
-	fprintf(stderr, "abort: %s\n", error());
-	abort();
-	exit(1);
-}
-
-void (*panic_handler)(void) = terminate;
-void *panic_data = NULL;
-
-void
-panicf(const char *fmt, ...)
-{
-	assert(fmt);
-
-	va_list ap;
-
-	/*
-	 * Store the error before calling panic because va_end would not be
-	 * called.
-	 */
-	va_start(ap, fmt);
-	errorva(fmt, ap);
-	va_end(ap);
-
-	panic();
-}
-
-void
-panicva(const char *fmt, va_list ap)
-{
-	assert(fmt);
-	assert(panic_handler);
-
-	errorva(fmt, ap);
-	panic();
-}
-
-void
-panic(void)
-{
-	assert(panic_handler);
-
-	panic_handler();
-
-	/*
-	 * This should not happen, if it does it means the user did not fully
-	 * satisfied the constraint of panic_handler.
-	 */
-	fprintf(stderr, "abort: panic handler returned\n");
-	exit(1);
-}
--- a/src/libmlk-core/core/panic.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * panic.h -- unrecoverable error handling
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_PANIC_H
-#define MLK_CORE_PANIC_H
-
-#include <stdarg.h>
-
-#include "core.h"
-
-extern void (*panic_handler)(void);
-extern void *panic_data;
-
-CORE_BEGIN_DECLS
-
-void
-panicf(const char *, ...);
-
-void
-panicva(const char *, va_list);
-
-void
-panic(void);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_PANIC_H */
--- a/src/libmlk-core/core/script.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-/*
- * script.c -- convenient sequence of actions
- *
- * Copyright (c) 2020-2022 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 <stdlib.h>
-#include <string.h>
-
-#include "action.h"
-#include "err.h"
-#include "script.h"
-
-static struct action *
-current(struct script *s)
-{
-	if (s->cur >= s->actionsz)
-		return NULL;
-
-	return s->actions[s->cur];
-}
-
-static void
-handle(struct action *a, const union event *ev)
-{
-	script_handle(a->data, ev);
-}
-
-static int
-update(struct action *a, unsigned int ticks)
-{
-	return script_update(a->data, ticks);
-}
-
-static void
-draw(struct action *a)
-{
-	script_draw(a->data);
-}
-
-static void
-finish(struct action *a)
-{
-	script_finish(a->data);
-}
-
-void
-script_init(struct script *s)
-{
-	assert(s);
-
-	memset(s, 0, sizeof (*s));
-}
-
-int
-script_append(struct script *s, struct action *a)
-{
-	assert(s);
-	assert(a);
-
-	if (s->actionsz >= SCRIPT_ACTION_MAX)
-		return ERR_NO_MEM;
-
-	s->actions[s->actionsz++] = a;
-
-	return 0;
-}
-
-void
-script_handle(struct script *s, const union event *ev)
-{
-	assert(s);
-	assert(ev);
-
-	struct action *a = current(s);
-
-	if (a)
-		action_handle(a, ev);
-}
-
-int
-script_update(struct script *s, unsigned int ticks)
-{
-	assert(s);
-
-	struct action *a = current(s);
-
-	if (!a)
-		return 1;
-
-	if (action_update(a, ticks)) {
-		action_end(a);
-		s->cur++;
-	}
-
-	return s->cur >= s->actionsz;
-}
-
-void
-script_draw(struct script *s)
-{
-	assert(s);
-
-	struct action *a = current(s);
-
-	if (a)
-		action_draw(a);
-}
-
-int
-script_completed(const struct script *s)
-{
-	assert(s);
-
-	return s->cur >= s->actionsz;
-}
-
-void
-script_finish(struct script *s)
-{
-	assert(s);
-
-	for (size_t i = 0; i < s->actionsz; ++i)
-		action_finish(s->actions[i]);
-
-	memset(s, 0, sizeof (*s));
-}
-
-void
-script_action(struct script *s, struct action *action)
-{
-	assert(s);
-	assert(action);
-
-	memset(action, 0, sizeof (*action));
-	action->data = s;
-	action->handle = handle;
-	action->update = update;
-	action->draw = draw;
-	action->finish = finish;
-}
--- a/src/libmlk-core/core/script.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * script.h -- convenient sequence of actions
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_SCRIPT_H
-#define MLK_CORE_SCRIPT_H
-
-#include <stddef.h>
-
-#include "core.h"
-
-#define SCRIPT_ACTION_MAX (128)
-
-struct action;
-
-union event;
-
-struct script {
-	struct action *actions[SCRIPT_ACTION_MAX];
-	size_t actionsz;
-	size_t cur;
-};
-
-CORE_BEGIN_DECLS
-
-void
-script_init(struct script *);
-
-int
-script_append(struct script *, struct action *);
-
-void
-script_handle(struct script *, const union event *);
-
-int
-script_update(struct script *, unsigned int);
-
-void
-script_draw(struct script *);
-
-int
-script_completed(const struct script *);
-
-void
-script_finish(struct script *);
-
-void
-script_action(struct script*s, struct action *);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_SCRIPT_H */
--- a/src/libmlk-core/core/sound.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * sound.c -- sound support
- *
- * Copyright (c) 2020-2022 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 <stdio.h>
-#include <string.h>
-
-#include "error.h"
-#include "sound.h"
-#include "sys_p.h"
-
-#define SOURCE(snd) ((const struct audiostream *)snd->handle)->source
-
-int
-sound_open(struct sound *snd, const char *path)
-{
-	assert(snd);
-	assert(path);
-
-	if (!(snd->handle = audiostream_open(path)))
-		return -1;
-
-	return 0;
-}
-
-int
-sound_openmem(struct sound *snd, const void *buffer, size_t buffersz)
-{
-	assert(snd);
-	assert(buffer);
-
-	if (!(snd->handle = audiostream_openmem(buffer, buffersz)))
-		return -1;
-
-	return 0;
-}
-
-int
-sound_ok(const struct sound *snd)
-{
-	return snd && snd->handle;
-}
-
-int
-sound_play(struct sound *snd)
-{
-	assert(sound_ok(snd));
-
-	alSourcePlay(SOURCE(snd));
-
-	return 0;
-}
-
-void
-sound_pause(struct sound *snd)
-{
-	assert(sound_ok(snd));
-
-	alSourcePause(SOURCE(snd));
-}
-
-void
-sound_resume(struct sound *snd)
-{
-	assert(sound_ok(snd));
-
-	alSourcePlay(SOURCE(snd));
-}
-
-void
-sound_stop(struct sound *snd)
-{
-	assert(sound_ok(snd));
-
-	alSourceStop(SOURCE(snd));
-}
-
-void
-sound_finish(struct sound *snd)
-{
-	assert(snd);
-
-	if (snd->handle) {
-		sound_stop(snd);
-		audiostream_finish(snd->handle);
-	}
-
-	memset(snd, 0, sizeof (*snd));
-}
--- a/src/libmlk-core/core/sound.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * sound.h -- sound support
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_SOUND_H
-#define MLK_CORE_SOUND_H
-
-#include <stddef.h>
-
-#include "core.h"
-
-#define SOUND_CHANNELS_MAX (256)
-
-struct vfs_file;
-
-struct sound {
-	void *handle;
-	int channel;
-};
-
-CORE_BEGIN_DECLS
-
-int
-sound_open(struct sound *, const char *);
-
-int
-sound_openmem(struct sound *, const void *, size_t);
-
-int
-sound_openvfs(struct sound *, struct vfs_file *);
-
-int
-sound_ok(const struct sound *);
-
-int
-sound_play(struct sound *);
-
-void
-sound_pause(struct sound *);
-
-void
-sound_resume(struct sound *);
-
-void
-sound_stop(struct sound *);
-
-void
-sound_finish(struct sound *);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_SOUND_H */
--- a/src/libmlk-core/core/sprite.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * sprite.c -- image sprites
- *
- * Copyright (c) 2020-2022 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 "sprite.h"
-#include "texture.h"
-
-void
-sprite_init(struct sprite *sprite,
-            struct texture *tex,
-            unsigned int cellw,
-            unsigned int cellh)
-{
-	assert(sprite);
-	assert(tex && texture_ok(tex));
-
-	sprite->texture = tex;
-	sprite->cellw = cellw;
-	sprite->cellh = cellh;
-	sprite->nrows = tex->h / cellh;
-	sprite->ncols = tex->w / cellw;
-}
-
-int
-sprite_ok(const struct sprite *sprite)
-{
-	return sprite && texture_ok(sprite->texture) && sprite->cellw != 0 && sprite->cellh != 0;
-}
-
-int
-sprite_draw(const struct sprite *sprite, unsigned int r, unsigned int c, int x, int y)
-{
-	return sprite_scale(sprite, r, c, x, y, sprite->cellw, sprite->cellh);
-}
-
-int
-sprite_scale(const struct sprite *sprite,
-	     unsigned int r,
-	     unsigned int c,
-	     int x,
-	     int y,
-	     unsigned int w,
-	     unsigned int h)
-{
-	assert(sprite_ok(sprite));
-	assert(r < sprite->nrows);
-	assert(c < sprite->ncols);
-
-	return texture_scale(
-		sprite->texture,
-		c * sprite->cellw,      /* src y */
-		r * sprite->cellh,      /* src x */
-		sprite->cellw,          /* src width */
-		sprite->cellh,          /* src height */
-		x,                      /* dst x */
-		y,                      /* dst y */
-		w,                      /* dst width */
-		h,                      /* dst height */
-		0.0                     /* angle */
-	);
-}
--- a/src/libmlk-core/core/sprite.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * sprite.h -- image sprites
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_SPRITE_H
-#define MLK_CORE_SPRITE_H
-
-#include "core.h"
-
-struct texture;
-
-struct sprite {
-	struct texture *texture;
-	unsigned int cellw;
-	unsigned int cellh;
-	unsigned int nrows;
-	unsigned int ncols;
-};
-
-CORE_BEGIN_DECLS
-
-void
-sprite_init(struct sprite *, struct texture *, unsigned int, unsigned int);
-
-int
-sprite_ok(const struct sprite *);
-
-int
-sprite_draw(const struct sprite *, unsigned int, unsigned int, int, int);
-
-int
-sprite_scale(const struct sprite *,
-             unsigned int,
-             unsigned int,
-             int,
-             int,
-             unsigned int,
-             unsigned int);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_SPRITE_H */
--- a/src/libmlk-core/core/state.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * state.c -- abstract state
- *
- * Copyright (c) 2020-2022 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 "state.h"
-
-void
-state_start(struct state *state)
-{
-	assert(state);
-
-	if (state->start)
-		state->start(state);
-}
-
-void
-state_handle(struct state *state, const union event *ev)
-{
-	assert(state);
-	assert(ev);
-
-	if (state->handle)
-		state->handle(state, ev);
-}
-
-void
-state_update(struct state *state, unsigned int ticks)
-{
-	assert(state);
-
-	if (state->update)
-		state->update(state, ticks);
-}
-
-void
-state_draw(struct state *state)
-{
-	assert(state);
-
-	if (state->draw)
-		state->draw(state);
-}
-
-void
-state_suspend(struct state *state)
-{
-	assert(state);
-
-	if (state->suspend)
-		state->suspend(state);
-}
-
-void
-state_resume(struct state *state)
-{
-	assert(state);
-
-	if (state->resume)
-		state->resume(state);
-}
-
-void
-state_end(struct state *state)
-{
-	assert(state);
-
-	if (state->end)
-		state->end(state);
-}
-
-void
-state_finish(struct state *state)
-{
-	assert(state);
-
-	if (state->finish)
-		state->finish(state);
-}
--- a/src/libmlk-core/core/state.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * state.h -- abstract state
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_STATE_H
-#define MLK_CORE_STATE_H
-
-#include "core.h"
-
-union event;
-
-struct state {
-	void *data;
-	void (*start)(struct state *);
-	void (*handle)(struct state *, const union event *);
-	void (*update)(struct state *, unsigned int);
-	void (*draw)(struct state *);
-	void (*suspend)(struct state *);
-	void (*resume)(struct state *);
-	void (*end)(struct state *);
-	void (*finish)(struct state *);
-};
-
-CORE_BEGIN_DECLS
-
-void
-state_start(struct state *);
-
-void
-state_handle(struct state *, const union event *);
-
-void
-state_update(struct state *, unsigned int);
-
-void
-state_draw(struct state *);
-
-void
-state_suspend(struct state *);
-
-void
-state_resume(struct state *);
-
-void
-state_end(struct state *);
-
-void
-state_finish(struct state *);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_STATE_H */
--- a/src/libmlk-core/core/sys.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,331 +0,0 @@
-/*
- * sys.c -- system routines
- *
- * Copyright (c) 2020-2022 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 <sys/stat.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#if defined(_WIN32)
-#       include <shlwapi.h>
-#       include <windows.h>
-#else
-#       include <errno.h>
-#       include <string.h>
-#endif
-
-#include <SDL.h>
-#include <SDL_image.h>
-#include <SDL_ttf.h>
-
-#include <sndfile.h>
-
-#include <util/util.h>
-
-#include "alloc.h"
-#include "error.h"
-#include "panic.h"
-#include "sound.h"
-#include "sys.h"
-#include "sys_p.h"
-
-ALCdevice *audio_dev = NULL;
-ALCcontext *audio_ctx = NULL;
-
-static struct {
-	char organization[128];
-	char name[128];
-} info = {
-	.organization = "fr.malikania",
-	.name = "molko"
-};
-
-static inline char *
-normalize(char *str)
-{
-	for (char *p = str; *p; ++p)
-		if (*p == '\\')
-			*p = '/';
-
-	return str;
-}
-
-static const char *
-user_directory(enum sys_dir kind)
-{
-	/* Kept for future use. */
-	(void)kind;
-
-	static char path[PATH_MAX];
-	char *pref;
-
-	if ((pref = SDL_GetPrefPath(info.organization, info.name))) {
-		util_strlcpy(path, pref, sizeof (path));
-		SDL_free(pref);
-	} else
-		util_strlcpy(path, "./", sizeof (path));
-
-	return path;
-}
-
-static inline int
-mkpath(const char *path)
-{
-#ifdef _WIN32
-	/* TODO: add error using the convenient FormatMessage function. */
-	if (!CreateDirectoryA(path, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
-		return errorf("unable to create directory: %s", path);
-#else
-	if (mkdir(path, 0755) < 0 && errno != EEXIST)
-		return errorf("%s", strerror(errno));
-#endif
-
-	return 0;
-}
-
-int
-sys_init(const char *organization, const char *name)
-{
-#if defined(__MINGW64__)
-	/* On MinGW buffering leads to painful debugging. */
-	setbuf(stderr, NULL);
-	setbuf(stdout, NULL);
-#endif
-
-	/* Kept for future use. */
-	(void)organization;
-	(void)name;
-
-	/* SDL2. */
-	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
-		return errorf("%s", SDL_GetError());
-	if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG)
-		return errorf("%s", SDL_GetError());
-	if (TTF_Init() < 0)
-		return errorf("%s", SDL_GetError());
-
-	/* OpenAL. */
-#if defined(_WIN32)
-	SetEnvironmentVariable("ALSOFT_LOGLEVEL", "0");
-#else
-	putenv("ALSOFT_LOGLEVEL=0");
-#endif
-
-	if (!(audio_dev = alcOpenDevice(NULL)))
-		return errorf("unable to create audio device");
-	if (!(audio_ctx = alcCreateContext(audio_dev, NULL)))
-		return errorf("unable to create audio context");
-
-	alcMakeContextCurrent(audio_ctx);
-
-	return 0;
-}
-
-const char *
-sys_dir(enum sys_dir kind)
-{
-	return user_directory(kind);
-}
-
-int
-sys_mkdir(const char *directory)
-{
-	char path[PATH_MAX], *p;
-
-	/* Copy the directory to normalize and iterate over '/'. */
-	util_strlcpy(path, directory, sizeof (path));
-	normalize(path);
-
-#if defined(_WIN32)
-	/* Remove drive letter that we don't need. */
-	if ((p = strchr(path, ':')))
-		++p;
-	else
-		p = path;
-#else
-	p = path;
-#endif
-
-	for (p = p + 1; *p; ++p) {
-		if (*p == '/') {
-			*p = 0;
-
-			if (mkpath(path) < 0)
-				return -1;
-
-			*p = '/';
-		}
-	}
-
-	return mkpath(path);
-}
-
-void
-sys_finish(void)
-{
-	TTF_Quit();
-	IMG_Quit();
-	SDL_Quit();
-
-	alcMakeContextCurrent(NULL);
-
-	if (audio_ctx) {
-		alcDestroyContext(audio_ctx);
-		audio_ctx = NULL;
-	}
-	if (audio_dev) {
-		alcCloseDevice(audio_dev);
-		audio_dev = NULL;
-	}
-}
-
-struct audiostream *
-audiostream_create(SNDFILE *file, const SF_INFO *info)
-{
-	struct audiostream *stream;
-
-	stream = alloc_new(sizeof (*stream));
-	stream->samplerate = info->samplerate;
-	stream->samplesz = info->frames * info->channels;
-	stream->samples = alloc_array(stream->samplesz, sizeof (*stream->samples));
-	stream->format = info->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
-
-	sf_command(file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
-
-	if (sf_read_short(file, stream->samples, stream->samplesz) != stream->samplesz) {
-		free(stream->samples);
-		free(stream);
-		stream = NULL;
-	}
-
-	alGenBuffers(1, &stream->buffer);
-	alBufferData(stream->buffer, stream->format, stream->samples,
-	    stream->samplesz * sizeof (*stream->samples), stream->samplerate);
-	alGenSources(1, &stream->source);
-	alSourcei(stream->source, AL_BUFFER, stream->buffer);
-
-	sf_close(file);
-
-	return stream;
-}
-
-struct audiostream *
-audiostream_open(const char *path)
-{
-	assert(path);
-
-	SF_INFO info;
-	SNDFILE *file;
-
-	if (!(file = sf_open(path, SFM_READ, &info)))
-		return NULL;
-
-	return audiostream_create(file, &info);
-}
-
-struct viodata {
-	const unsigned char *data;
-	const size_t datasz;
-	sf_count_t offset;
-};
-
-static sf_count_t
-vio_get_filelen(void *data)
-{
-	const struct viodata *vio = data;
-
-	return (sf_count_t)vio->datasz;
-}
-
-static sf_count_t
-vio_seek(sf_count_t offset, int whence, void *data)
-{
-	struct viodata *vio = data;
-
-	switch (whence) {
-	case SEEK_SET:
-		vio->offset = offset;
-		break;
-	case SEEK_CUR:
-		vio->offset += offset;
-		break;
-	case SEEK_END:
-		vio->offset = vio->datasz - offset;
-		break;
-	default:
-		break;
-	}
-
-	return vio->offset;
-}
-
-static sf_count_t
-vio_read(void *ptr, sf_count_t count, void *data)
-{
-	struct viodata *vio = data;
-
-	memcpy(ptr, vio->data + vio->offset, count);
-	vio->offset += count;
-
-	return count;
-}
-
-static sf_count_t
-vio_tell(void *data)
-{
-	const struct viodata *vio = data;
-
-	return vio->offset;
-}
-
-struct audiostream *
-audiostream_openmem(const void *data, size_t datasz)
-{
-	assert(data);
-
-	SF_VIRTUAL_IO io = {
-		.get_filelen = vio_get_filelen,
-		.seek = vio_seek,
-		.read = vio_read,
-		.tell = vio_tell
-	};
-	SF_INFO info;
-	SNDFILE *file;
-	struct viodata viodata = {
-		.data = data,
-		.datasz = datasz,
-	};
-
-	if (!(file = sf_open_virtual(&io, SFM_READ, &info, &viodata)))
-		return NULL;
-
-	return audiostream_create(file, &info);
-}
-
-void
-audiostream_finish(struct audiostream *s)
-{
-	assert(s);
-
-	alDeleteBuffers(1, &s->buffer);
-	alSourcei(s->source, AL_BUFFER, 0);
-	alDeleteSources(1, &s->source);
-}
--- a/src/libmlk-core/core/sys.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * sys.h -- system routines
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_SYS_H
-#define MLK_CORE_SYS_H
-
-#include <stdarg.h>
-
-#include "core.h"
-
-enum sys_dir {
-	SYS_DIR_SAVE
-};
-
-CORE_BEGIN_DECLS
-
-int
-sys_init(const char *, const char *);
-
-const char *
-sys_dir(enum sys_dir);
-
-int
-sys_mkdir(const char *);
-
-void
-sys_finish(void);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_SYS_H */
--- a/src/libmlk-core/core/sys_p.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * sys_p.h -- libcore private definitions
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_SYS_P_H
-#define MLK_CORE_SYS_P_H
-
-#include <util/util.h>
-
-#include <stddef.h>
-
-#if defined(MLK_OS_APPLE)
-#       include <OpenAL/al.h>
-#       include <OpenAL/alc.h>
-#else
-#       include <al.h>
-#       include <alc.h>
-#endif
-
-extern ALCdevice *audio_dev;
-extern ALCcontext *audio_ctx;
-
-struct audiostream {
-	short *samples;
-	ALsizei samplesz;
-	ALsizei samplerate;
-	ALuint buffer;
-	ALuint source;
-	ALenum format;
-};
-
-struct audiostream *
-audiostream_open(const char *);
-
-struct audiostream *
-audiostream_openmem(const void *, size_t);
-
-void
-audiostream_finish(struct audiostream *);
-
-#endif /* !MLK_CORE_SYS_P_H */
--- a/src/libmlk-core/core/texture.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,178 +0,0 @@
-/*
- * texture.c -- basic texture management
- *
- * Copyright (c) 2020-2022 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 <string.h>
-
-#include "color.h"
-#include "error.h"
-#include "texture.h"
-#include "texture_p.h"
-#include "util.h"
-#include "window.h"
-#include "window_p.h"
-
-int
-texture_new(struct texture *tex, unsigned int w, unsigned int h)
-{
-	assert(tex);
-	assert(w);
-	assert(h);
-
-	tex->handle = SDL_CreateTexture(RENDERER(),
-	    SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h);
-
-	if (!tex->handle) {
-		tex->w = tex->h = 0;
-		return ERR_SDL;
-	}
-
-	tex->w = w;
-	tex->h = h;
-
-	return 0;
-}
-
-int
-texture_ok(const struct texture *tex)
-{
-	return tex && tex->handle && tex->w && tex->h;
-}
-
-int
-texture_set_blend_mode(struct texture *tex, enum texture_blend blend)
-{
-	assert(tex);
-	assert(blend >= TEXTURE_BLEND_NONE && blend <= TEXTURE_BLEND_MODULATE);
-
-	static const SDL_BlendMode table[] = {
-		[TEXTURE_BLEND_NONE] = SDL_BLENDMODE_NONE,
-		[TEXTURE_BLEND_BLEND] = SDL_BLENDMODE_BLEND,
-		[TEXTURE_BLEND_ADD] = SDL_BLENDMODE_ADD,
-		[TEXTURE_BLEND_MODULATE] = SDL_BLENDMODE_MOD
-	};
-
-	if (SDL_SetTextureBlendMode(tex->handle, table[blend]) < 0)
-		return errorf("%s", SDL_GetError());
-
-	return 0;
-}
-
-int
-texture_set_alpha_mod(struct texture *tex, unsigned int alpha)
-{
-	assert(texture_ok(tex));
-	assert(alpha <= 255);
-
-	if (SDL_SetTextureAlphaMod(tex->handle, alpha) < 0)
-		return errorf("%s", SDL_GetError());
-
-	return 0;
-}
-
-int
-texture_set_color_mod(struct texture *tex, unsigned long color)
-{
-	assert(texture_ok(tex));
-
-	if (SDL_SetTextureColorMod(tex->handle, COLOR_R(color), COLOR_G(color), COLOR_B(color)) < 0)
-		return errorf("%s", SDL_GetError());
-
-	return 0;
-}
-
-int
-texture_draw(const struct texture *tex, int x, int y)
-{
-	assert(tex);
-
-	SDL_Rect dst = {
-		.x = x,
-		.y = y,
-		.w = tex->w,
-		.h = tex->h
-	};
-
-	if (SDL_RenderCopy(RENDERER(), tex->handle, NULL, &dst) < 0)
-		return errorf("%s", SDL_GetError());
-
-	return 0;
-}
-
-int
-texture_scale(const struct texture *tex,
-              int src_x,
-              int src_y,
-              unsigned src_w,
-              unsigned src_h,
-              int dst_x,
-              int dst_y,
-              unsigned dst_w,
-              unsigned dst_h,
-              double angle)
-{
-	const SDL_Rect src = {
-		.x = src_x,
-		.y = src_y,
-		.w = src_w,
-		.h = src_h
-	};
-	const SDL_Rect dst = {
-		.x = dst_x,
-		.y = dst_y,
-		.w = dst_w,
-		.h = dst_h
-	};
-
-	if (SDL_RenderCopyEx(RENDERER(), tex->handle, &src, &dst, angle, NULL, SDL_FLIP_NONE) < 0)
-		return errorf("%s", SDL_GetError());
-
-	return 0;
-}
-
-void
-texture_finish(struct texture *tex)
-{
-	assert(tex);
-
-	if (tex->handle)
-		SDL_DestroyTexture(tex->handle);
-
-	memset(tex, 0, sizeof (*tex));
-}
-
-/* private */
-
-int
-texture_from_surface(struct texture *tex, SDL_Surface *surface)
-{
-	assert(tex);
-	assert(surface);
-
-	if (!(tex->handle = SDL_CreateTextureFromSurface(RENDERER(), surface))) {
-		tex->w = tex->h = 0;
-		return ERR_SDL;
-	}
-
-	tex->w = surface->w;
-	tex->h = surface->h;
-
-	SDL_FreeSurface(surface);
-
-	return 0;
-}
--- a/src/libmlk-core/core/texture.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * texture.h -- basic texture management
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_TEXTURE_H
-#define MLK_CORE_TEXTURE_H
-
-#include "core.h"
-#include "err.h"
-
-struct texture {
-	unsigned int w;
-	unsigned int h;
-	void *handle;
-};
-
-enum texture_blend {
-	TEXTURE_BLEND_NONE,
-	TEXTURE_BLEND_BLEND,
-	TEXTURE_BLEND_ADD,
-	TEXTURE_BLEND_MODULATE,
-	TEXTURE_BLEND_LAST
-};
-
-CORE_BEGIN_DECLS
-
-int
-texture_new(struct texture *, unsigned int, unsigned int);
-
-int
-texture_ok(const struct texture *);
-
-int
-texture_set_blend_mode(struct texture *, enum texture_blend);
-
-int
-texture_set_alpha_mod(struct texture *, unsigned int);
-
-int
-texture_set_color_mod(struct texture *, unsigned long);
-
-int
-texture_draw(const struct texture *, int, int);
-
-int
-texture_scale(const struct texture *,
-              int,
-              int,
-              unsigned int,
-              unsigned int,
-              int,
-              int,
-              unsigned int,
-              unsigned int,
-              double);
-
-void
-texture_finish(struct texture *);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_TEXTURE_H */
--- a/src/libmlk-core/core/texture_p.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * texture_p.h -- (PRIVATE) basic texture management
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_TEXTURE_P_H
-#define MLK_CORE_TEXTURE_P_H
-
-#include <SDL.h>
-
-struct texture;
-
-int
-texture_from_surface(struct texture *, SDL_Surface *);
-
-#endif /* !MLK_CORE_TEXTURE_P_H */
--- a/src/libmlk-core/core/trace.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * trace.h -- non-fatal message logs
- *
- * Copyright (c) 2020-2022 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 <stdio.h>
-
-#include "trace.h"
-
-static void
-default_handler(const char *line)
-{
-	assert(line);
-
-	puts(line);
-}
-
-void (*trace_handler)(const char *) = default_handler;
-void *trace_data = NULL;
-
-void
-tracef(const char *fmt, ...)
-{
-	assert(fmt);
-
-	va_list ap;
-
-	if (!trace_handler)
-		return;
-
-	va_start(ap, fmt);
-	traceva(fmt, ap);
-	va_end(ap);
-}
-
-void
-traceva(const char *fmt, va_list ap)
-{
-	assert(fmt);
-
-	char buf[TRACE_LINE_MAX];
-
-	if (!trace_handler)
-		return;
-
-	vsnprintf(buf, sizeof (buf), fmt, ap);
-	trace_handler(buf);
-}
--- a/src/libmlk-core/core/trace.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * trace.h -- non-fatal message logs
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_TRACE_H
-#define MLK_CORE_TRACE_H
-
-#include <stdarg.h>
-
-#include "core.h"
-
-#define TRACE_LINE_MAX (1024)
-
-extern void (*trace_handler)(const char *);
-extern void *trace_data;
-
-CORE_BEGIN_DECLS
-
-void
-tracef(const char *, ...);
-
-void
-traceva(const char *, va_list);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_TRACE_H */
--- a/src/libmlk-core/core/util.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * util.c -- utilities
- *
- * Copyright (c) 2020-2022 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 <limits.h>
-#include <stdlib.h>
-
-#include <SDL.h>
-
-#include <util/util.h>
-
-#include "util.h"
-
-void
-util_delay(unsigned int ms)
-{
-	SDL_Delay(ms);
-}
-
-const char *
-util_pathf(const char *fmt, ...)
-{
-	static char path[PATH_MAX];
-	va_list ap;
-
-	va_start(ap, fmt);
-	vsnprintf(path, sizeof (path), fmt, ap);
-	va_end(ap);
-
-	return path;
-}
-
-unsigned int
-util_nrand(unsigned int lower, unsigned int upper)
-{
-	assert(upper <= RAND_MAX);
-
-	return (rand() % (upper - lower)) + lower;
-}
--- a/src/libmlk-core/core/util.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * util.h -- utilities
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_UTIL_H
-#define MLK_CORE_UTIL_H
-
-#include "core.h"
-
-#define UTIL_SIZE(x) sizeof ((x)) / sizeof ((x)[0])
-
-CORE_BEGIN_DECLS
-
-void
-util_delay(unsigned int);
-
-const char *
-util_pathf(const char *, ...);
-
-unsigned int
-util_nrand(unsigned int, unsigned int);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_UTIL_H */
--- a/src/libmlk-core/core/window.c	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * window.c -- basic window management
- *
- * Copyright (c) 2020-2022 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 <string.h>
-
-#include <SDL.h>
-
-#include "err.h"
-#include "util.h"
-#include "window.h"
-#include "window_p.h"
-
-static struct window_handle handle = {
-	.win = NULL,
-	.renderer = NULL
-};
-
-static SDL_Cursor *cursors[WINDOW_CURSOR_LAST];
-
-struct window window = {
-	.handle = &handle
-};
-
-static void
-load_cursors(void)
-{
-	cursors[WINDOW_CURSOR_ARROW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
-	cursors[WINDOW_CURSOR_EDIT] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
-	cursors[WINDOW_CURSOR_WAIT] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT);
-	cursors[WINDOW_CURSOR_CROSSHAIR] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_CROSSHAIR);
-	cursors[WINDOW_CURSOR_SIZE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
-	cursors[WINDOW_CURSOR_NO] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
-	cursors[WINDOW_CURSOR_HAND] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
-}
-
-static void
-load_framerate(void)
-{
-	SDL_DisplayMode mode;
-
-	if (SDL_GetWindowDisplayMode(handle.win, &mode) == 0)
-		window.framerate = mode.refresh_rate;
-}
-
-static void
-finish_cursors(void)
-{
-	for (size_t i = 0; i < UTIL_SIZE(cursors); ++i)
-		if (cursors[i])
-			SDL_FreeCursor(cursors[i]);
-}
-
-static int
-load_window(const char *title, unsigned int w, unsigned int h)
-{
-	return (handle.win = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, 0)) != NULL;
-}
-
-static int
-load_renderer(void)
-{
-	return (handle.renderer = SDL_CreateRenderer(handle.win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)) != NULL;
-}
-
-int
-window_open(const char *title, unsigned int w, unsigned int h)
-{
-	assert(title);
-
-	if (!load_window(title, w, h) || !load_renderer())
-		return ERR_SDL;
-
-	window.w = w;
-	window.h = h;
-
-	load_framerate();
-	load_cursors();
-
-	return 0;
-}
-
-void
-window_set_cursor(enum window_cursor cursor)
-{
-	assert(cursor < WINDOW_CURSOR_LAST);
-
-	SDL_SetCursor(cursors[cursor]);
-}
-
-void
-window_finish(void)
-{
-	if (handle.renderer)
-		SDL_DestroyRenderer(handle.renderer);
-	if (handle.win)
-		SDL_DestroyWindow(handle.win);
-
-	finish_cursors();
-
-	memset(&handle, 0, sizeof (handle));
-}
--- a/src/libmlk-core/core/window.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * window.h -- basic window management
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_WINDOW_H
-#define MLK_CORE_WINDOW_H
-
-#include "core.h"
-
-struct window {
-	unsigned int w;
-	unsigned int h;
-	unsigned int framerate;
-	void *handle;
-};
-
-enum window_cursor {
-	WINDOW_CURSOR_ARROW,
-	WINDOW_CURSOR_EDIT,
-	WINDOW_CURSOR_WAIT,
-	WINDOW_CURSOR_CROSSHAIR,
-	WINDOW_CURSOR_SIZE,
-	WINDOW_CURSOR_NO,
-	WINDOW_CURSOR_HAND,
-	WINDOW_CURSOR_LAST
-};
-
-extern struct window window;
-
-CORE_BEGIN_DECLS
-
-int
-window_open(const char *, unsigned int, unsigned int);
-
-void
-window_set_cursor(enum window_cursor);
-
-void
-window_finish(void);
-
-CORE_END_DECLS
-
-#endif /* !MLK_CORE_WINDOW_H */
--- a/src/libmlk-core/core/window_p.h	Sat Oct 15 17:18:45 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * window.c -- (PRIVATE) basic window management
- *
- * Copyright (c) 2020-2022 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.
- */
-
-#ifndef MLK_CORE_WINDOW_P_H
-#define MLK_CORE_WINDOW_P_H
-
-#include <SDL.h>
-
-struct window_handle {
-	SDL_Window *win;
-	SDL_Renderer *renderer;
-};
-
-/* Convenient macros to access the native handle from global window object. */
-#define WINDOW()        (((struct window_handle *)window.handle)->win)
-#define RENDERER()      (((struct window_handle *)window.handle)->renderer)
-
-#endif /* !MLK_CORE_WINDOW_P_H */
--- a/src/libmlk-rpg/rpg/battle-bar-default.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-bar-default.c	Sat Oct 15 20:23:14 2022 +0200
@@ -21,13 +21,13 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <core/alloc.h>
-#include <core/event.h>
-#include <core/font.h>
-#include <core/sprite.h>
-#include <core/trace.h>
-#include <core/util.h>
-#include <core/window.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/event.h>
+#include <mlk/core/font.h>
+#include <mlk/core/sprite.h>
+#include <mlk/core/trace.h>
+#include <mlk/core/util.h>
+#include <mlk/core/window.h>
 
 #include <ui/align.h>
 #include <ui/theme.h>
--- a/src/libmlk-rpg/rpg/battle-bar-default.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-bar-default.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_BATTLE_BAR_DEFAULT_H
 #define MLK_RPG_BATTLE_BAR_DEFAULT_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 #include <ui/gridmenu.h>
 
--- a/src/libmlk-rpg/rpg/battle-bar.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-bar.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_BATTLE_BAR_H
 #define MLK_RPG_BATTLE_BAR_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 struct battle;
 struct selection;
--- a/src/libmlk-rpg/rpg/battle-entity-state-attacking.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-entity-state-attacking.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,10 +19,10 @@
 #include <assert.h>
 #include <stdlib.h>
 
-#include <core/alloc.h>
-#include <core/animation.h>
-#include <core/panic.h>
-#include <core/sprite.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/animation.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/sprite.h>
 
 #include "battle-entity-state-attacking.h"
 #include "battle-entity-state.h"
--- a/src/libmlk-rpg/rpg/battle-entity-state-attacking.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-entity-state-attacking.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_BATTLE_ENTITY_STATE_ATTACKING_H
 #define MLK_RPG_BATTLE_ENTITY_STATE_ATTACKING_H
 
-#include <core/animation.h>
+#include <mlk/core/animation.h>
 
 struct battle_entity;
 struct sprite;
--- a/src/libmlk-rpg/rpg/battle-entity-state-blinking.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-entity-state-blinking.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,10 +19,10 @@
 #include <assert.h>
 #include <stdlib.h>
 
-#include <core/alloc.h>
-#include <core/panic.h>
-#include <core/sprite.h>
-#include <core/texture.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/sprite.h>
+#include <mlk/core/texture.h>
 
 #include "battle-entity-state-blinking.h"
 #include "battle-entity-state.h"
--- a/src/libmlk-rpg/rpg/battle-entity-state-moving.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-entity-state-moving.c	Sat Oct 15 20:23:14 2022 +0200
@@ -20,8 +20,8 @@
 #include <math.h>
 #include <stdlib.h>
 
-#include <core/alloc.h>
-#include <core/panic.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/panic.h>
 
 #include "battle-entity-state-moving.h"
 #include "battle-entity-state.h"
--- a/src/libmlk-rpg/rpg/battle-entity-state.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-entity-state.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_BATTLE_ENTITY_STATE_H
 #define MLK_RPG_BATTLE_ENTITY_STATE_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 struct battle_entity;
 struct sprite;
--- a/src/libmlk-rpg/rpg/battle-entity.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-entity.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,8 +18,8 @@
 
 #include <assert.h>
 
-#include <core/sprite.h>
-#include <core/texture.h>
+#include <mlk/core/sprite.h>
+#include <mlk/core/texture.h>
 
 #include <ui/theme.h>
 
--- a/src/libmlk-rpg/rpg/battle-entity.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-entity.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_BATTLE_ENTITY_H
 #define MLK_RPG_BATTLE_ENTITY_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 #include <ui/label.h>
 
--- a/src/libmlk-rpg/rpg/battle-indicator.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-indicator.c	Sat Oct 15 20:23:14 2022 +0200
@@ -21,9 +21,9 @@
 #include <stdio.h>
 #include <string.h>
 
-#include <core/color.h>
-#include <core/font.h>
-#include <core/panic.h>
+#include <mlk/core/color.h>
+#include <mlk/core/font.h>
+#include <mlk/core/panic.h>
 
 #include <ui/theme.h>
 
@@ -61,7 +61,7 @@
 	bti->cur = 0xffffffff;
 	bti->elapsed = 0;
 	bti->alpha = 250;
-	
+
 	if (font_render(theme->fonts[THEME_FONT_INTERFACE], &bti->tex[0], buf, bti->cur) < 0||
 	    font_render(theme->fonts[THEME_FONT_INTERFACE], &bti->tex[1], buf, 0x000000ff) < 0)
 		panic();
--- a/src/libmlk-rpg/rpg/battle-indicator.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-indicator.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,8 +19,8 @@
 #ifndef MLK_RPG_BATTLE_INDICATOR_H
 #define MLK_RPG_BATTLE_INDICATOR_H
 
-#include <core/core.h>
-#include <core/texture.h>
+#include <mlk/core/core.h>
+#include <mlk/core/texture.h>
 
 #define BATTLE_INDICATOR_HP_COLOR (0xa5303000)
 #define BATTLE_INDICATOR_MP_COLOR (0xa23e8c00)
--- a/src/libmlk-rpg/rpg/battle-message.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-message.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,7 +18,7 @@
 
 #include <assert.h>
 
-#include <core/window.h>
+#include <mlk/core/window.h>
 
 #include <ui/align.h>
 #include <ui/frame.h>
--- a/src/libmlk-rpg/rpg/battle-message.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-message.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_BATTLE_MESSAGE_H
 #define MLK_RPG_BATTLE_MESSAGE_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 struct theme;
 
--- a/src/libmlk-rpg/rpg/battle-state-ai.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-state-ai.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #include <assert.h>
 #include <stdlib.h>
 
-#include <core/alloc.h>
+#include <mlk/core/alloc.h>
 
 #include "battle-state-ai.h"
 #include "battle-state.h"
--- a/src/libmlk-rpg/rpg/battle-state-attacking.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-state-attacking.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,9 +19,9 @@
 #include <assert.h>
 #include <stdlib.h>
 
-#include <core/alloc.h>
-#include <core/panic.h>
-#include <core/sprite.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/sprite.h>
 
 #include "battle-entity-state-attacking.h"
 #include "battle-entity-state-blinking.h"
--- a/src/libmlk-rpg/rpg/battle-state-check.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-state-check.c	Sat Oct 15 20:23:14 2022 +0200
@@ -20,11 +20,11 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <core/alloc.h>
-#include <core/panic.h>
-#include <core/sprite.h>
-#include <core/texture.h>
-#include <core/trace.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/sprite.h>
+#include <mlk/core/texture.h>
+#include <mlk/core/trace.h>
 
 #include "battle-state-check.h"
 #include "battle-state-lost.h"
--- a/src/libmlk-rpg/rpg/battle-state-closing.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-state-closing.c	Sat Oct 15 20:23:14 2022 +0200
@@ -20,12 +20,12 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <core/alloc.h>
-#include <core/music.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/texture.h>
-#include <core/window.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/music.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/texture.h>
+#include <mlk/core/window.h>
 
 #include "battle-state-closing.h"
 #include "battle.h"
@@ -74,7 +74,7 @@
 	painter_clear();
 	painter_draw_rectangle(0, 0, window.w, window.h);
 	PAINTER_END();
-	
+
 	texture_set_alpha_mod(&cls->texture, 0);
 }
 
--- a/src/libmlk-rpg/rpg/battle-state-closing.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-state-closing.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_BATTLE_STATE_CLOSING_H
 #define MLK_RPG_BATTLE_STATE_CLOSING_H
 
-#include <core/texture.h>
+#include <mlk/core/texture.h>
 
 struct battle;
 
--- a/src/libmlk-rpg/rpg/battle-state-item.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-state-item.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,8 +19,8 @@
 #include <assert.h>
 #include <stdlib.h>
 
-#include <core/alloc.h>
-#include <core/panic.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/panic.h>
 
 #include <rpg/inventory.h>
 #include <rpg/item.h>
--- a/src/libmlk-rpg/rpg/battle-state-lost.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-state-lost.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,10 +18,10 @@
 
 #include <assert.h>
 
-#include <core/alloc.h>
-#include <core/music.h>
-#include <core/panic.h>
-#include <core/window.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/music.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/window.h>
 
 #include "battle-state-closing.h"
 #include "battle-state-lost.h"
--- a/src/libmlk-rpg/rpg/battle-state-menu.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-state-menu.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #include <assert.h>
 #include <stdlib.h>
 
-#include <core/alloc.h>
+#include <mlk/core/alloc.h>
 
 #include "battle-bar.h"
 #include "battle-state-menu.h"
--- a/src/libmlk-rpg/rpg/battle-state-opening.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-state-opening.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,10 +19,10 @@
 #include <assert.h>
 #include <stdlib.h>
 
-#include <core/alloc.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/window.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/window.h>
 
 #include "battle-state-check.h"
 #include "battle-state-opening.h"
--- a/src/libmlk-rpg/rpg/battle-state-rendering.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-state-rendering.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,8 +19,8 @@
 #include <assert.h>
 #include <stdlib.h>
 
-#include <core/alloc.h>
-#include <core/drawable.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/drawable.h>
 
 #include "battle-state-rendering.h"
 #include "battle.h"
--- a/src/libmlk-rpg/rpg/battle-state-selection.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-state-selection.c	Sat Oct 15 20:23:14 2022 +0200
@@ -20,11 +20,11 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <core/alloc.h>
-#include <core/event.h>
-#include <core/panic.h>
-#include <core/sprite.h>
-#include <core/util.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/event.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/sprite.h>
+#include <mlk/core/util.h>
 
 #include <ui/theme.h>
 
--- a/src/libmlk-rpg/rpg/battle-state-victory.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-state-victory.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,10 +18,10 @@
 
 #include <assert.h>
 
-#include <core/alloc.h>
-#include <core/music.h>
-#include <core/panic.h>
-#include <core/window.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/music.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/window.h>
 
 #include "battle-state-closing.h"
 #include "battle-state-victory.h"
--- a/src/libmlk-rpg/rpg/battle-state.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle-state.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_BATTLE_STATE_H
 #define MLK_RPG_BATTLE_STATE_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 struct battle;
 struct character;
--- a/src/libmlk-rpg/rpg/battle.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle.c	Sat Oct 15 20:23:14 2022 +0200
@@ -21,15 +21,15 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <core/alloc.h>
-#include <core/event.h>
-#include <core/font.h>
-#include <core/music.h>
-#include <core/sprite.h>
-#include <core/texture.h>
-#include <core/trace.h>
-#include <core/util.h>
-#include <core/window.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/event.h>
+#include <mlk/core/font.h>
+#include <mlk/core/music.h>
+#include <mlk/core/sprite.h>
+#include <mlk/core/texture.h>
+#include <mlk/core/trace.h>
+#include <mlk/core/util.h>
+#include <mlk/core/window.h>
 
 #include <ui/align.h>
 #include <ui/frame.h>
--- a/src/libmlk-rpg/rpg/battle.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/battle.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,11 +19,11 @@
 #ifndef MLK_RPG_BATTLE_H
 #define MLK_RPG_BATTLE_H
 
-#include <core/action.h>
-#include <core/action-stack.h>
-#include <core/core.h>
-#include <core/drawable.h>
-#include <core/drawable-stack.h>
+#include <mlk/core/action.h>
+#include <mlk/core/action-stack.h>
+#include <mlk/core/core.h>
+#include <mlk/core/drawable.h>
+#include <mlk/core/drawable-stack.h>
 
 #include <ui/frame.h>
 #include <ui/gridmenu.h>
--- a/src/libmlk-rpg/rpg/character.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/character.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,7 +18,7 @@
 
 #include <assert.h>
 
-#include <core/sprite.h>
+#include <mlk/core/sprite.h>
 
 #include <assets/sql/character-save.h>
 #include <assets/sql/character-load.h>
--- a/src/libmlk-rpg/rpg/character.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/character.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_CHARACTER_H
 #define MLK_RPG_CHARACTER_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 #define CHARACTER_SPELL_MAX (64)
 
--- a/src/libmlk-rpg/rpg/equipment.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/equipment.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_EQUIPMENT_H
 #define MLK_RPG_EQUIPMENT_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 struct character;
 struct texture;
--- a/src/libmlk-rpg/rpg/inventory.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/inventory.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_INVENTORY_H
 #define MLK_RPG_INVENTORY_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 #define INVENTORY_ITEM_MAX (512)
 
--- a/src/libmlk-rpg/rpg/item.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/item.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_ITEM_H
 #define MLK_RPG_ITEM_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 struct battle;
 struct character;
--- a/src/libmlk-rpg/rpg/map-file.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/map-file.c	Sat Oct 15 20:23:14 2022 +0200
@@ -26,10 +26,10 @@
 
 #include <util/util.h>
 
-#include <core/alloc.h>
-#include <core/error.h>
-#include <core/image.h>
-#include <core/trace.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/error.h>
+#include <mlk/core/image.h>
+#include <mlk/core/trace.h>
 
 #include "map-file.h"
 
--- a/src/libmlk-rpg/rpg/map-file.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/map-file.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,10 +19,10 @@
 #ifndef MLK_RPG_MAP_FILE_H
 #define MLK_RPG_MAP_FILE_H
 
-#include <core/alloc.h>
-#include <core/core.h>
-#include <core/sprite.h>
-#include <core/texture.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/core.h>
+#include <mlk/core/sprite.h>
+#include <mlk/core/texture.h>
 
 #include "map.h"
 #include "tileset.h"
--- a/src/libmlk-rpg/rpg/map.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/map.c	Sat Oct 15 20:23:14 2022 +0200
@@ -21,15 +21,15 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <core/error.h>
-#include <core/event.h>
-#include <core/image.h>
-#include <core/maths.h>
-#include <core/painter.h>
-#include <core/sprite.h>
-#include <core/sys.h>
-#include <core/texture.h>
-#include <core/window.h>
+#include <mlk/core/error.h>
+#include <mlk/core/event.h>
+#include <mlk/core/image.h>
+#include <mlk/core/maths.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/sprite.h>
+#include <mlk/core/sys.h>
+#include <mlk/core/texture.h>
+#include <mlk/core/window.h>
 
 #include <ui/debug.h>
 
@@ -140,7 +140,7 @@
 	        (drow > 0 && new->y < now->y) ||
 	        (dcol < 0 && new->x + new->w > now->x + now->w) ||
 		(dcol > 0 && new->x < now->x));
-		
+
 }
 
 static void
--- a/src/libmlk-rpg/rpg/map.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/map.h	Sat Oct 15 20:23:14 2022 +0200
@@ -21,9 +21,9 @@
 
 #include <stddef.h>
 
-#include <core/action.h>
-#include <core/action-stack.h>
-#include <core/core.h>
+#include <mlk/core/action.h>
+#include <mlk/core/action-stack.h>
+#include <mlk/core/core.h>
 
 #include "walksprite.h"
 
--- a/src/libmlk-rpg/rpg/message.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/message.c	Sat Oct 15 20:23:14 2022 +0200
@@ -20,15 +20,15 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <core/action.h>
-#include <core/event.h>
-#include <core/font.h>
-#include <core/maths.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/sprite.h>
-#include <core/trace.h>
-#include <core/util.h>
+#include <mlk/core/action.h>
+#include <mlk/core/event.h>
+#include <mlk/core/font.h>
+#include <mlk/core/maths.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/sprite.h>
+#include <mlk/core/trace.h>
+#include <mlk/core/util.h>
 
 #include <ui/align.h>
 #include <ui/frame.h>
--- a/src/libmlk-rpg/rpg/message.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/message.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,8 +19,8 @@
 #ifndef MLK_RPG_MESSAGE_H
 #define MLK_RPG_MESSAGE_H
 
-#include <core/core.h>
-#include <core/texture.h>
+#include <mlk/core/core.h>
+#include <mlk/core/texture.h>
 
 struct action;
 struct font;
--- a/src/libmlk-rpg/rpg/property.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/property.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_PROPERTY_H
 #define MLK_RPG_PROPERTY_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 #define PROPERTY_KEY_MAX        (64)
 #define PROPERTY_VALUE_MAX      (1024)
--- a/src/libmlk-rpg/rpg/quest.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/quest.h	Sat Oct 15 20:23:14 2022 +0200
@@ -21,7 +21,7 @@
 
 #include <stddef.h>
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 struct save;
 
--- a/src/libmlk-rpg/rpg/rpg.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/rpg.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_RPG_H
 #define MLK_RPG_RPG_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 CORE_BEGIN_DECLS
 
--- a/src/libmlk-rpg/rpg/save.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/save.c	Sat Oct 15 20:23:14 2022 +0200
@@ -25,9 +25,9 @@
 
 #include <util/util.h>
 
-#include <core/error.h>
-#include <core/sys.h>
-#include <core/util.h>
+#include <mlk/core/error.h>
+#include <mlk/core/sys.h>
+#include <mlk/core/util.h>
 
 #include <assets/sql/init.h>
 
--- a/src/libmlk-rpg/rpg/save.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/save.h	Sat Oct 15 20:23:14 2022 +0200
@@ -21,7 +21,7 @@
 
 #include <time.h>
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 struct save {
 	time_t created;
--- a/src/libmlk-rpg/rpg/selection.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/selection.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,7 +18,7 @@
 
 #include <assert.h>
 
-#include <core/util.h>
+#include <mlk/core/util.h>
 
 #include "battle.h"
 #include "character.h"
--- a/src/libmlk-rpg/rpg/selection.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/selection.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_SELECTION_H
 #define MLK_RPG_SELECTION_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 struct battle;
 
@@ -39,7 +39,7 @@
 struct selection {
 	enum selection_kind allowed_kinds;
 	enum selection_side allowed_sides;
-	
+
 	/* Character index in battle entity array. */
 	unsigned int index_character;
 
--- a/src/libmlk-rpg/rpg/spell.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/spell.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_SPELL_H
 #define MLK_RPG_SPELL_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 #include "selection.h"
 
--- a/src/libmlk-rpg/rpg/tileset-file.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/tileset-file.c	Sat Oct 15 20:23:14 2022 +0200
@@ -26,11 +26,11 @@
 
 #include <util/util.h>
 
-#include <core/alloc.h>
-#include <core/animation.h>
-#include <core/error.h>
-#include <core/image.h>
-#include <core/util.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/animation.h>
+#include <mlk/core/error.h>
+#include <mlk/core/image.h>
+#include <mlk/core/util.h>
 
 #include "tileset-file.h"
 #include "tileset.h"
--- a/src/libmlk-rpg/rpg/tileset-file.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/tileset-file.h	Sat Oct 15 20:23:14 2022 +0200
@@ -21,10 +21,10 @@
 
 #include <stddef.h>
 
-#include <core/alloc.h>
-#include <core/core.h>
-#include <core/sprite.h>
-#include <core/texture.h>
+#include <mlk/core/alloc.h>
+#include <mlk/core/core.h>
+#include <mlk/core/sprite.h>
+#include <mlk/core/texture.h>
 
 struct tileset;
 struct tileset_tiledef;
--- a/src/libmlk-rpg/rpg/tileset.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/tileset.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,8 +19,8 @@
 #include <assert.h>
 #include <stdlib.h>
 
-#include <core/animation.h>
-#include <core/sprite.h>
+#include <mlk/core/animation.h>
+#include <mlk/core/sprite.h>
 
 #include "tileset.h"
 
--- a/src/libmlk-rpg/rpg/tileset.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/tileset.h	Sat Oct 15 20:23:14 2022 +0200
@@ -21,7 +21,7 @@
 
 #include <stddef.h>
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 struct sprite;
 
--- a/src/libmlk-rpg/rpg/walksprite.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/walksprite.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #include <assert.h>
 #include <string.h>
 
-#include <core/sprite.h>
+#include <mlk/core/sprite.h>
 
 #include "walksprite.h"
 
--- a/src/libmlk-rpg/rpg/walksprite.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-rpg/rpg/walksprite.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_RPG_WALKSPRITE_H
 #define MLK_RPG_WALKSPRITE_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 struct sprite;
 
--- a/src/libmlk-ui/ui/align.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/align.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_UI_ALIGN_H
 #define MLK_UI_ALIGN_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 enum align {
 	ALIGN_NONE,
--- a/src/libmlk-ui/ui/button.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/button.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,10 +19,10 @@
 #include <assert.h>
 #include <string.h>
 
-#include <core/event.h>
-#include <core/maths.h>
-#include <core/painter.h>
-#include <core/trace.h>
+#include <mlk/core/event.h>
+#include <mlk/core/maths.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/trace.h>
 
 #include "align.h"
 #include "button.h"
--- a/src/libmlk-ui/ui/button.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/button.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_UI_BUTTON_H
 #define MLK_UI_BUTTON_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 union event;
 
--- a/src/libmlk-ui/ui/checkbox.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/checkbox.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,9 +19,9 @@
 #include <assert.h>
 #include <string.h>
 
-#include <core/event.h>
-#include <core/maths.h>
-#include <core/painter.h>
+#include <mlk/core/event.h>
+#include <mlk/core/maths.h>
+#include <mlk/core/painter.h>
 
 #include "label.h"
 #include "checkbox.h"
--- a/src/libmlk-ui/ui/checkbox.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/checkbox.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_UI_CHECKBOX_H
 #define MLK_UI_CHECKBOX_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 union event;
 
--- a/src/libmlk-ui/ui/debug.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/debug.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #include <assert.h>
 #include <stdio.h>
 
-#include <core/texture.h>
+#include <mlk/core/texture.h>
 
 #include "debug.h"
 #include "theme.h"
--- a/src/libmlk-ui/ui/debug.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/debug.h	Sat Oct 15 20:23:14 2022 +0200
@@ -21,8 +21,8 @@
 
 #include <stdarg.h>
 
-#include <core/core.h>
-#include <core/font.h>
+#include <mlk/core/core.h>
+#include <mlk/core/font.h>
 
 #define DEBUG_LINE_MAX 1024
 
--- a/src/libmlk-ui/ui/frame.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/frame.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #include <assert.h>
 #include <string.h>
 
-#include <core/painter.h>
+#include <mlk/core/painter.h>
 
 #include "frame.h"
 #include "theme.h"
--- a/src/libmlk-ui/ui/frame.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/frame.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_UI_FRAME_H
 #define MLK_UI_FRAME_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 struct theme;
 
--- a/src/libmlk-ui/ui/gridmenu.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/gridmenu.c	Sat Oct 15 20:23:14 2022 +0200
@@ -20,12 +20,12 @@
 #include <math.h>
 #include <string.h>
 
-#include <core/event.h>
-#include <core/maths.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/texture.h>
-#include <core/trace.h>
+#include <mlk/core/event.h>
+#include <mlk/core/maths.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/texture.h>
+#include <mlk/core/trace.h>
 
 #include "frame.h"
 #include "label.h"
--- a/src/libmlk-ui/ui/gridmenu.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/gridmenu.h	Sat Oct 15 20:23:14 2022 +0200
@@ -21,7 +21,7 @@
 
 #include <stddef.h>
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 #include "label.h"
 
--- a/src/libmlk-ui/ui/label.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/label.c	Sat Oct 15 20:23:14 2022 +0200
@@ -19,9 +19,9 @@
 #include <assert.h>
 #include <string.h>
 
-#include <core/font.h>
-#include <core/panic.h>
-#include <core/texture.h>
+#include <mlk/core/font.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/texture.h>
 
 #include "label.h"
 #include "theme.h"
--- a/src/libmlk-ui/ui/label.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/label.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_UI_LABEL_H
 #define MLK_UI_LABEL_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 struct theme;
 
--- a/src/libmlk-ui/ui/notify.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/notify.c	Sat Oct 15 20:23:14 2022 +0200
@@ -20,10 +20,10 @@
 #include <stddef.h>
 #include <string.h>
 
-#include <core/font.h>
-#include <core/texture.h>
-#include <core/trace.h>
-#include <core/window.h>
+#include <mlk/core/font.h>
+#include <mlk/core/texture.h>
+#include <mlk/core/trace.h>
+#include <mlk/core/window.h>
 
 #include "align.h"
 #include "frame.h"
--- a/src/libmlk-ui/ui/notify.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/notify.h	Sat Oct 15 20:23:14 2022 +0200
@@ -21,7 +21,7 @@
 
 #include <stddef.h>
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 #define NOTIFY_MAX              (4)
 #define NOTIFY_TIMEOUT_DEFAULT  (5000)
--- a/src/libmlk-ui/ui/theme.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/theme.c	Sat Oct 15 20:23:14 2022 +0200
@@ -20,12 +20,12 @@
 #include <stddef.h>
 #include <string.h>
 
-#include <core/font.h>
-#include <core/maths.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/texture.h>
-#include <core/util.h>
+#include <mlk/core/font.h>
+#include <mlk/core/maths.h>
+#include <mlk/core/painter.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/texture.h>
+#include <mlk/core/util.h>
 
 #include <assets/fonts/opensans-light.h>
 #include <assets/fonts/opensans-medium.h>
--- a/src/libmlk-ui/ui/theme.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/theme.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_UI_THEME_H
 #define MLK_UI_THEME_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 struct button;
 struct checkbox;
--- a/src/libmlk-ui/ui/ui.h	Sat Oct 15 17:18:45 2022 +0200
+++ b/src/libmlk-ui/ui/ui.h	Sat Oct 15 20:23:14 2022 +0200
@@ -19,7 +19,7 @@
 #ifndef MLK_UI_UI_H
 #define MLK_UI_UI_H
 
-#include <core/core.h>
+#include <mlk/core/core.h>
 
 CORE_BEGIN_DECLS
 
--- a/tests/test-action-script.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/tests/test-action-script.c	Sat Oct 15 20:23:14 2022 +0200
@@ -16,9 +16,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <core/action.h>
-#include <core/event.h>
-#include <core/script.h>
+#include <mlk/core/action.h>
+#include <mlk/core/event.h>
+#include <mlk/core/script.h>
 
 #include <dt.h>
 
--- a/tests/test-action.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/tests/test-action.c	Sat Oct 15 20:23:14 2022 +0200
@@ -16,10 +16,10 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <core/action-stack.h>
-#include <core/action.h>
-#include <core/err.h>
-#include <core/event.h>
+#include <mlk/core/action-stack.h>
+#include <mlk/core/action.h>
+#include <mlk/core/err.h>
+#include <mlk/core/event.h>
 
 #include <dt.h>
 
--- a/tests/test-alloc.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/tests/test-alloc.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,7 +18,7 @@
 
 #include <stdlib.h>
 
-#include <core/alloc.h>
+#include <mlk/core/alloc.h>
 
 #include <dt.h>
 
--- a/tests/test-color.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/tests/test-color.c	Sat Oct 15 20:23:14 2022 +0200
@@ -16,7 +16,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <core/color.h>
+#include <mlk/core/color.h>
 
 #include <dt.h>
 
--- a/tests/test-drawable.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/tests/test-drawable.c	Sat Oct 15 20:23:14 2022 +0200
@@ -16,10 +16,10 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <core/drawable-stack.h>
-#include <core/drawable.h>
-#include <core/err.h>
-#include <core/event.h>
+#include <mlk/core/drawable-stack.h>
+#include <mlk/core/drawable.h>
+#include <mlk/core/err.h>
+#include <mlk/core/event.h>
 
 #include <dt.h>
 
--- a/tests/test-error.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/tests/test-error.c	Sat Oct 15 20:23:14 2022 +0200
@@ -16,7 +16,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <core/error.h>
+#include <mlk/core/error.h>
 
 #include <dt.h>
 
--- a/tests/test-map.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/tests/test-map.c	Sat Oct 15 20:23:14 2022 +0200
@@ -16,11 +16,11 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <core/core.h>
-#include <core/error.h>
-#include <core/panic.h>
-#include <core/sys.h>
-#include <core/window.h>
+#include <mlk/core/core.h>
+#include <mlk/core/error.h>
+#include <mlk/core/panic.h>
+#include <mlk/core/sys.h>
+#include <mlk/core/window.h>
 
 #include <rpg/map-file.h>
 #include <rpg/map.h>
--- a/tests/test-save-quest.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/tests/test-save-quest.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,7 +18,7 @@
 
 #include <stdio.h>
 
-#include <core/util.h>
+#include <mlk/core/util.h>
 
 #include <rpg/quest.h>
 #include <rpg/save.h>
--- a/tests/test-state.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/tests/test-state.c	Sat Oct 15 20:23:14 2022 +0200
@@ -18,10 +18,10 @@
 
 #include <string.h>
 
-#include <core/event.h>
-#include <core/game.h>
-#include <core/state.h>
-#include <core/util.h>
+#include <mlk/core/event.h>
+#include <mlk/core/game.h>
+#include <mlk/core/state.h>
+#include <mlk/core/util.h>
 
 #include <dt.h>
 
--- a/tests/test-tileset.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/tests/test-tileset.c	Sat Oct 15 20:23:14 2022 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <core/core.h>
-#include <core/window.h>
+#include <mlk/core/core.h>
+#include <mlk/core/window.h>
 
 #include <rpg/tileset-file.h>
 #include <rpg/tileset.h>
--- a/tests/test-util.c	Sat Oct 15 17:18:45 2022 +0200
+++ b/tests/test-util.c	Sat Oct 15 20:23:14 2022 +0200
@@ -16,7 +16,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <core/util.h>
+#include <mlk/core/util.h>
 
 #include <dt.h>