changeset 435:556c8e2ff995

misc: move tools/* in /
author David Demelier <markand@malikania.fr>
date Sun, 16 Oct 2022 08:31:01 +0200
parents 4e78f045e8c0
children df92d5b056ce
files .hgignore GNUmakefile libmlk-core/mlk/core/err.c libmlk-core/mlk/core/err.h mlk-bcc/arg.h mlk-bcc/mlk-bcc.c mlk-map/mlk-map.c mlk-tileset/mlk-tileset.c src/tools/bcc/arg.h src/tools/bcc/mlk-bcc.c src/tools/map/mlk-map.c src/tools/tileset/mlk-tileset.c
diffstat 12 files changed, 688 insertions(+), 681 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Sat Oct 15 21:24:17 2022 +0200
+++ b/.hgignore	Sun Oct 16 08:31:01 2022 +0200
@@ -67,9 +67,9 @@
 ^tests/test-vfs-zip$
 
 # Tools.
-^src/tools/bcc/mlk-bcc$
-^src/tools/map/mlk-map$
-^src/tools/tileset/mlk-tileset$
+^mlk-bcc/mlk-bcc$
+^mlk-map/mlk-map$
+^mlk-tileset/mlk-tileset$
 
 # Documentation.
 ^doc/site
--- a/GNUmakefile	Sat Oct 15 21:24:17 2022 +0200
+++ b/GNUmakefile	Sun Oct 16 08:31:01 2022 +0200
@@ -121,7 +121,7 @@
 
 # {{{ mlk-bcc
 
-MLK_BCC :=              src/tools/bcc/mlk-bcc
+MLK_BCC :=              mlk-bcc/mlk-bcc
 
 $(MLK_BCC): INCS :=
 
@@ -131,7 +131,7 @@
 
 # {{{ mlk-tileset
 
-MLK_TILESET :=          src/tools/tileset/mlk-tileset
+MLK_TILESET :=          mlk-tileset/mlk-tileset
 
 $(MLK_TILESET): INCS := $(JANSSON_INCS)
 $(MLK_TILESET): LIBS := $(JANSSON_LIBS)
@@ -142,7 +142,7 @@
 
 # {{{ mlk-map
 
-MLK_MAP :=              src/tools/map/mlk-map
+MLK_MAP :=              mlk-map/mlk-map
 
 $(MLK_MAP): INCS := -Ilibmlk-util $(JANSSON_INCS)
 $(MLK_MAP): LIBS := $(LIBMLK_UTIL) $(JANSSON_LIBS)
--- a/libmlk-core/mlk/core/err.c	Sat Oct 15 21:24:17 2022 +0200
+++ b/libmlk-core/mlk/core/err.c	Sun Oct 16 08:31:01 2022 +0200
@@ -30,6 +30,8 @@
 		return "out of memory";
 	case ERR_NO_SUPPORT:
 		return "operation not supported";
+	case ERR_FORMAT:
+		return "invalid format or corrupt file";
 	default:
 		return "no error";
 	}
--- a/libmlk-core/mlk/core/err.h	Sat Oct 15 21:24:17 2022 +0200
+++ b/libmlk-core/mlk/core/err.h	Sun Oct 16 08:31:01 2022 +0200
@@ -23,6 +23,7 @@
 #define ERR_SDL         -1
 #define ERR_NO_MEM      -2
 #define ERR_NO_SUPPORT  -3
+#define ERR_FORMAT      -4
 
 const char *
 err_string(int e);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mlk-bcc/arg.h	Sun Oct 16 08:31:01 2022 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#ifndef ARG_H__
+#define ARG_H__
+
+extern char *argv0;
+
+/* use main(int argc, char *argv[]) */
+#define ARGBEGIN	for (argv0 = *argv, argv++, argc--;\
+					argv[0] && argv[0][0] == '-'\
+					&& argv[0][1];\
+					argc--, argv++) {\
+				char argc_;\
+				char **argv_;\
+				int brk_;\
+				if (argv[0][1] == '-' && argv[0][2] == '\0') {\
+					argv++;\
+					argc--;\
+					break;\
+				}\
+				for (brk_ = 0, argv[0]++, argv_ = argv;\
+						argv[0][0] && !brk_;\
+						argv[0]++) {\
+					if (argv_ != argv)\
+						break;\
+					argc_ = argv[0][0];\
+					switch (argc_)
+
+#define ARGEND			}\
+			}
+
+#define ARGC()		argc_
+
+#define EARGF(x)	((argv[0][1] == '\0' && argv[1] == NULL)?\
+				((x), abort(), (char *)0) :\
+				(brk_ = 1, (argv[0][1] != '\0')?\
+					(&argv[0][1]) :\
+					(argc--, argv++, argv[0])))
+
+#define ARGF()		((argv[0][1] == '\0' && argv[1] == NULL)?\
+				(char *)0 :\
+				(brk_ = 1, (argv[0][1] != '\0')?\
+					(&argv[0][1]) :\
+					(argc--, argv++, argv[0])))
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mlk-bcc/mlk-bcc.c	Sun Oct 16 08:31:01 2022 +0200
@@ -0,0 +1,169 @@
+/*
+ * bcc.c -- binary to C/C++ arrays converter
+ *
+ * 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 <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(__OpenBSD__)
+#       include <unistd.h>
+#endif
+
+#include "arg.h"
+
+char *argv0;
+
+static const char *charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
+static char findentchar = '\t';
+static int findent = 1, fconst, fnull, fstatic;
+
+static void
+usage(void)
+{
+	fprintf(stderr, "usage: bcc [-0cs] [-I tab-indent] [-i space-indent] input variable\n");
+	exit(1);
+}
+
+static void
+die(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	fputs("abort: ", stderr);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	exit(1);
+}
+
+static char *
+mangle(char *variable)
+{
+	char *p;
+	size_t pos;
+
+	/* Remove extension. */
+	if ((p = strrchr(variable, '.')))
+		*p = '\0';
+
+	/* Remove disallowed characters. */
+	while ((pos = strspn(variable, charset)) != strlen(variable))
+		variable[pos] = '_';
+
+	return variable;
+}
+
+static void
+indent(void)
+{
+	for (int i = 0; i < findent; ++i)
+		putchar(findentchar);
+}
+
+static void
+put(int ch)
+{
+	printf("0x%02hhx", (unsigned char)ch);
+}
+
+static void
+process(const char *input, const char *variable)
+{
+	FILE *fp;
+	int ch, col = 0;
+
+	if (strcmp(input, "-") == 0)
+		fp = stdin;
+	else if (!(fp = fopen(input, "rb")))
+		die("%s: %s\n", input, strerror(errno));
+
+	if (fstatic)
+		printf("static ");
+	if (fconst)
+		printf("const ");
+
+	printf("unsigned char %s[] = {\n", variable);
+
+	for (ch = fgetc(fp); ch != EOF; ) {
+		if (col == 0)
+			indent();
+
+		put(ch);
+
+		if ((ch = fgetc(fp)) != EOF || fnull)
+			printf(",%s", col < 3 ? " " : "");
+
+		if (++col == 4) {
+			col = 0;
+			putchar('\n');
+		}
+
+		/* Add final '\0' if required. */
+		if (ch == EOF && fnull) {
+			if (col++ == 0)
+				indent();
+
+			put(0);
+		}
+	}
+
+	if (col != 0)
+		printf("\n");
+
+	puts("};");
+	fclose(fp);
+}
+
+int
+main(int argc, char *argv[])
+{
+#if defined(__OpenBSD__)
+	if (pledge("rpath stdio", NULL) < 0)
+		die("abort: %s\n", strerror(errno));
+#endif
+
+	ARGBEGIN {
+	case '0':
+		fnull = 1;
+		break;
+	case 'c':
+		fconst = 1;
+		break;
+	case 'I':
+		findentchar = '\t';
+		findent = atoi(EARGF(usage()));
+		break;
+	case 'i':
+		findentchar = ' ';
+		findent = atoi(EARGF(usage()));
+		break;
+	case 's':
+		fstatic = 1;
+		break;
+	default:
+		usage();
+		break;
+	} ARGEND
+
+	if (argc < 2)
+		usage();
+
+	process(argv[0], mangle(argv[1]));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mlk-map/mlk-map.c	Sun Oct 16 08:31:01 2022 +0200
@@ -0,0 +1,257 @@
+/*
+ * main.c -- convert tiled tiled JSON files into custom files
+ *
+ * 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 <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <jansson.h>
+
+#include <mlk/util/util.h>
+
+static void
+die(const char *fmt, ...)
+{
+	assert(fmt);
+
+	va_list ap;
+
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	exit(1);
+}
+
+static bool
+is_layer(const char *name)
+{
+	return strcmp(name, "background") == 0 ||
+	       strcmp(name, "foreground") == 0 ||
+	       strcmp(name, "above") == 0 ||
+	       strcmp(name, "actions") == 0;
+}
+
+static const json_t *
+find_property(const json_t *props, const char *which)
+{
+	const json_t *obj;
+	size_t index;
+
+	json_array_foreach(props, index, obj) {
+		if (!json_is_object(obj))
+			continue;
+
+		const json_t *key = json_object_get(obj, "name");
+		const json_t *value = json_object_get(obj, "value");
+
+		if (json_is_string(key) && value && strcmp(json_string_value(key), which) == 0)
+			return value;
+	}
+
+	return NULL;
+}
+
+static void
+write_title(const json_t *props)
+{
+	const json_t *prop_title = find_property(props, "title");
+
+	if (prop_title && json_is_string(prop_title))
+		printf("title|%s\n", json_string_value(prop_title));
+}
+
+static void
+write_origin(const json_t *props)
+{
+	const json_t *prop_origin_x = find_property(props, "origin-x");
+	const json_t *prop_origin_y = find_property(props, "origin-y");
+
+	if (!prop_origin_x || !json_is_integer(prop_origin_x) ||
+	    !prop_origin_y || !json_is_integer(prop_origin_y))
+		return;
+
+	printf("origin|%d|%d\n",
+	    (int)json_integer_value(prop_origin_x),
+	    (int)json_integer_value(prop_origin_y));
+}
+
+static void
+write_properties(const json_t *props)
+{
+	write_title(props);
+	write_origin(props);
+}
+
+static void
+write_dimensions(const json_t *document)
+{
+	json_t *width = json_object_get(document, "width");
+	json_t *height = json_object_get(document, "height");
+
+	if (!width || !json_is_integer(width))
+		die("missing 'width' property\n");
+	if (!height || !json_is_integer(height))
+		die("missing 'height' property\n");
+
+	printf("columns|%d\n", (int)json_integer_value(width));
+	printf("rows|%d\n", (int)json_integer_value(height));
+}
+
+static void
+write_object(const json_t *object)
+{
+	assert(json_is_object(object));
+
+	json_t *x = json_object_get(object, "x");
+	json_t *y = json_object_get(object, "y");
+	json_t *width = json_object_get(object, "width");
+	json_t *height = json_object_get(object, "height");
+	json_t *props = json_object_get(object, "properties");
+	const json_t *exec, *block;
+
+	if (!x || !json_is_number(x))
+		die("invalid 'x' property in object\n");
+	if (!y || !json_is_number(y))
+		die("invalid 'y' property in object\n");
+	if (!width || !json_is_number(width))
+		die("invalid 'width' property in object\n");
+	if (!height || !json_is_number(height))
+		die("invalid 'height' property in object\n");
+
+	/* This is optional and set to 0 if not present. */
+	block = find_property(props, "block");
+
+	/* In tiled, those properties are float but we only use ints in MA */
+	printf("%d|%d|%d|%d|%d",
+	    (int)json_integer_value(x),
+	    (int)json_integer_value(y),
+	    (int)json_integer_value(width),
+	    (int)json_integer_value(height),
+	    (int)json_is_true(block)
+	);
+
+	if ((exec = find_property(props, "exec")) && json_is_string(exec))
+		printf("|%s", json_string_value(exec));
+
+	printf("\n");
+}
+
+static void
+write_layer(const json_t *layer)
+{
+	json_t *objects = json_object_get(layer, "objects");
+	json_t *data = json_object_get(layer, "data");
+	json_t *name = json_object_get(layer, "name");
+	json_t *tile, *object;
+	size_t index;
+
+	if (!name || !json_is_string(name))
+		die("invalid 'name' property in layer");
+	if (!is_layer(json_string_value(name)))
+		die("invalid 'name' layer: %s\n", json_string_value(name));
+
+	printf("layer|%s\n", json_string_value(name));
+
+	/* Only foreground/background have 'data' property */
+	if (json_is_array(data)) {
+		json_array_foreach(data, index, tile) {
+			if (!json_is_integer(tile))
+				die("invalid 'data' property in layer\n");
+
+			printf("%d\n", (int)json_integer_value(tile));
+		}
+	}
+
+	/* Only objects has 'objects' property */
+	if (json_is_array(objects)) {
+		json_array_foreach(objects, index, object) {
+			if (!json_is_object(object))
+				die("invalid 'objects' property in layer\n");
+
+			write_object(object);
+		}
+	}
+}
+
+static void
+write_layers(const json_t *layers)
+{
+	size_t index;
+	json_t *layer;
+
+	if (!layers)
+		return;
+
+	json_array_foreach(layers, index, layer) {
+		if (!json_is_object(layer))
+			die("layer is not an object\n");
+
+		write_layer(layer);
+	}
+}
+
+static void
+write_tileset(const json_t *tilesets)
+{
+	char path[PATH_MAX];
+	char filename[FILENAME_MAX] = {0}, *ext;
+	const json_t *tileset, *source;
+
+	if (json_array_size(tilesets) != 1)
+		die("map must contain exactly one tileset");
+
+	tileset = json_array_get(tilesets, 0);
+	source = json_object_get(tileset, "source");
+
+	if (!json_is_string(source))
+		die("invalid 'source' property in tileset\n");
+
+	/* We need to replace the .json extension to .tileset. */
+	snprintf(path, sizeof (path), "%s", json_string_value(source));
+	snprintf(filename, sizeof (filename), "%s", util_basename(path));
+
+	if (!(ext = strstr(filename, ".json")))
+		die("could not determine tileset extension");
+
+	*ext = '\0';
+
+	printf("tileset|%s.tileset\n", filename);
+}
+
+int
+main(void)
+{
+	json_t *document;
+	json_error_t error;
+
+	document = json_loadf(stdin, 0, &error);
+
+	if (!document)
+		die("%d:%d: %s\n", error.line, error.column, error.text);
+
+	write_properties(json_object_get(document, "properties"));
+	write_dimensions(document);
+	write_layers(json_object_get(document, "layers"));
+	write_tileset(json_object_get(document, "tilesets"));
+
+	json_decref(document);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mlk-tileset/mlk-tileset.c	Sun Oct 16 08:31:01 2022 +0200
@@ -0,0 +1,204 @@
+/*
+ * main.c -- convert tiled tilesets JSON files into custom files
+ *
+ * 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 <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <jansson.h>
+
+static void
+die(const char *fmt, ...)
+{
+	assert(fmt);
+
+	va_list ap;
+
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	exit(1);
+}
+
+static void
+write_dimensions(const json_t *document)
+{
+	const json_t *tilewidth = json_object_get(document, "tilewidth");
+	const json_t *tileheight = json_object_get(document, "tileheight");
+
+	if (!json_is_integer(tilewidth))
+		die("invalid 'tilewidth' property\n");
+	if (!json_is_integer(tileheight))
+		die("invalid 'tileheight' property\n");
+
+	printf("tilewidth|%u\n", (unsigned int)json_integer_value(tilewidth));
+	printf("tileheight|%u\n", (unsigned int)json_integer_value(tileheight));
+}
+
+static void
+write_image(const json_t *document)
+{
+	const json_t *image = json_object_get(document, "image");
+
+	if (!json_is_string(image))
+		die("invalid 'image' property\n");
+
+	printf("image|%s\n", json_string_value(image));
+}
+
+static const json_t *
+find_property_value(const json_t *array, const char *prop)
+{
+	const json_t *obj;
+	size_t i;
+
+	json_array_foreach(array, i, obj) {
+		const json_t *name = json_object_get(obj, "name");
+
+		if (!name || !json_is_string(name))
+			die("invalid property object\n");
+
+		if (strcmp(json_string_value(name), prop) == 0)
+			return json_object_get(obj, "value");
+	}
+
+	return NULL;
+}
+
+static void
+write_animation(const json_t *tile)
+{
+	const json_t *id = json_object_get(tile, "id");
+	const json_t *properties = json_object_get(tile, "properties");
+	const json_t *file = find_property_value(properties, "animation-file");
+	const json_t *delay = find_property_value(properties, "animation-delay");
+
+	/* Animations are completely optional. */
+	if (!json_is_array(properties))
+		return;
+
+	if (!json_is_integer(id))
+		die("invalid 'id' property in tile\n");
+
+	if (json_is_string(file)) {
+		printf("%d|%s|", (int)json_integer_value(id), json_string_value(file));
+
+		if (json_is_integer(delay))
+			printf("%d\n", (int)json_integer_value(delay));
+		else
+			printf("10\n");
+	}
+}
+
+static void
+write_tiledef(const json_t *tile)
+{
+	const json_t *id = json_object_get(tile, "id");
+	const json_t *objectgroup = json_object_get(tile, "objectgroup");
+	const json_t *objects = json_object_get(objectgroup, "objects");
+	const json_t *first = json_array_get(objects, 0);
+	const json_t *x, *y, *w, *h;
+
+	/* Collisions are optional. */
+	if (!json_is_object(objectgroup))
+		return;
+
+	if (!json_is_integer(id))
+		die("invalid 'id' property in tile\n");
+	if (!json_is_array(objects))
+		die("invalid 'objects' property in tile\n");
+
+	x = json_object_get(first, "x");
+	y = json_object_get(first, "y");
+	w = json_object_get(first, "width");
+	h = json_object_get(first, "height");
+
+	if (!json_is_integer(x) || !json_is_integer(y) ||
+	    !json_is_integer(w) || !json_is_integer(h))
+		die("invalid collide object in tile description\n");
+
+	printf("%d|%d|%d|%d|%d\n",
+	    (int)json_integer_value(id),
+	    (int)json_integer_value(x),
+	    (int)json_integer_value(y),
+	    (int)json_integer_value(w),
+	    (int)json_integer_value(h));
+}
+
+static void
+write_tiledefs(const json_t *tiles)
+{
+	size_t index;
+	json_t *object;
+
+	if (!json_is_array(tiles))
+		return;
+
+	puts("tiledefs");
+
+	json_array_foreach(tiles, index, object) {
+		if (!json_is_object(object))
+			die("tile is not an object\n");
+
+		write_tiledef(object);
+	}
+}
+
+static void
+write_animations(const json_t *tiles)
+{
+	size_t index;
+	json_t *object;
+
+	if (!json_is_array(tiles))
+		return;
+
+	puts("animations");
+
+	json_array_foreach(tiles, index, object) {
+		if (!json_is_object(object))
+			die("tile is not an object\n");
+
+		write_animation(object);
+	}
+}
+
+int
+main(int argc, char *argv[])
+{
+	(void)argc;
+	(void)argv;
+
+	json_t *document;
+	json_error_t error;
+
+	document = json_loadf(stdin, 0, &error);
+
+	if (!document)
+		die("%d:%d: %s\n", error.line, error.column, error.text);
+	if (!json_is_object(document))
+		die("root value isn't an object\n");
+
+	write_dimensions(document);
+	write_image(document);
+	write_tiledefs(json_object_get(document, "tiles"));
+	write_animations(json_object_get(document, "tiles"));
+
+	json_decref(document);
+}
--- a/src/tools/bcc/arg.h	Sat Oct 15 21:24:17 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copy me if you can.
- * by 20h
- */
-
-#ifndef ARG_H__
-#define ARG_H__
-
-extern char *argv0;
-
-/* use main(int argc, char *argv[]) */
-#define ARGBEGIN	for (argv0 = *argv, argv++, argc--;\
-					argv[0] && argv[0][0] == '-'\
-					&& argv[0][1];\
-					argc--, argv++) {\
-				char argc_;\
-				char **argv_;\
-				int brk_;\
-				if (argv[0][1] == '-' && argv[0][2] == '\0') {\
-					argv++;\
-					argc--;\
-					break;\
-				}\
-				for (brk_ = 0, argv[0]++, argv_ = argv;\
-						argv[0][0] && !brk_;\
-						argv[0]++) {\
-					if (argv_ != argv)\
-						break;\
-					argc_ = argv[0][0];\
-					switch (argc_)
-
-#define ARGEND			}\
-			}
-
-#define ARGC()		argc_
-
-#define EARGF(x)	((argv[0][1] == '\0' && argv[1] == NULL)?\
-				((x), abort(), (char *)0) :\
-				(brk_ = 1, (argv[0][1] != '\0')?\
-					(&argv[0][1]) :\
-					(argc--, argv++, argv[0])))
-
-#define ARGF()		((argv[0][1] == '\0' && argv[1] == NULL)?\
-				(char *)0 :\
-				(brk_ = 1, (argv[0][1] != '\0')?\
-					(&argv[0][1]) :\
-					(argc--, argv++, argv[0])))
-
-#endif
--- a/src/tools/bcc/mlk-bcc.c	Sat Oct 15 21:24:17 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-/*
- * bcc.c -- binary to C/C++ arrays converter
- *
- * 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 <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "arg.h"
-
-char *argv0;
-
-static const char *charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
-static char findentchar = '\t';
-static int findent = 1, fconst, fnull, fstatic;
-
-static void
-usage(void)
-{
-	fprintf(stderr, "usage: bcc [-0cs] [-I tab-indent] [-i space-indent] input variable\n");
-	exit(1);
-}
-
-static void
-die(const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	fputs("abort: ", stderr);
-	vfprintf(stderr, fmt, ap);
-	va_end(ap);
-	exit(1);
-}
-
-static char *
-mangle(char *variable)
-{
-	char *p;
-	size_t pos;
-
-	/* Remove extension. */
-	if ((p = strrchr(variable, '.')))
-		*p = '\0';
-
-	/* Remove disallowed characters. */
-	while ((pos = strspn(variable, charset)) != strlen(variable))
-		variable[pos] = '_';
-
-	return variable;
-}
-
-static void
-indent(void)
-{
-	for (int i = 0; i < findent; ++i)
-		putchar(findentchar);
-}
-
-static void
-put(int ch)
-{
-	printf("0x%02hhx", (unsigned char)ch);
-}
-
-static void
-process(const char *input, const char *variable)
-{
-	FILE *fp;
-	int ch, col = 0;
-
-	if (strcmp(input, "-") == 0)
-		fp = stdin;
-	else if (!(fp = fopen(input, "rb")))
-		die("%s: %s\n", input, strerror(errno));
-
-	if (fstatic)
-		printf("static ");
-	if (fconst)
-		printf("const ");
-
-	printf("unsigned char %s[] = {\n", variable);
-
-	for (ch = fgetc(fp); ch != EOF; ) {
-		if (col == 0)
-			indent();
-
-		put(ch);
-
-		if ((ch = fgetc(fp)) != EOF || fnull)
-			printf(",%s", col < 3 ? " " : "");
-
-		if (++col == 4) {
-			col = 0;
-			putchar('\n');
-		}
-
-		/* Add final '\0' if required. */
-		if (ch == EOF && fnull) {
-			if (col++ == 0)
-				indent();
-
-			put(0);
-		}
-	}
-
-	if (col != 0)
-		printf("\n");
-
-	puts("};");
-	fclose(fp);
-}
-
-int
-main(int argc, char *argv[])
-{
-#if defined(__OpenBSD__)
-	if (pledge("rpath stdio", NULL) < 0)
-		die("abort: %s\n", strerror(errno));
-#endif
-
-	ARGBEGIN {
-	case '0':
-		fnull = 1;
-		break;
-	case 'c':
-		fconst = 1;
-		break;
-	case 'I':
-		findentchar = '\t';
-		findent = atoi(EARGF(usage()));
-		break;
-	case 'i':
-		findentchar = ' ';
-		findent = atoi(EARGF(usage()));
-		break;
-	case 's':
-		fstatic = 1;
-		break;
-	default:
-		usage();
-		break;
-	} ARGEND
-
-	if (argc < 2)
-		usage();
-
-	process(argv[0], mangle(argv[1]));
-}
--- a/src/tools/map/mlk-map.c	Sat Oct 15 21:24:17 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-/*
- * main.c -- convert tiled tiled JSON files into custom files
- *
- * 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 <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jansson.h>
-
-#include <mlk/util/util.h>
-
-static void
-die(const char *fmt, ...)
-{
-	assert(fmt);
-
-	va_list ap;
-
-	va_start(ap, fmt);
-	vfprintf(stderr, fmt, ap);
-	va_end(ap);
-	exit(1);
-}
-
-static bool
-is_layer(const char *name)
-{
-	return strcmp(name, "background") == 0 ||
-	       strcmp(name, "foreground") == 0 ||
-	       strcmp(name, "above") == 0 ||
-	       strcmp(name, "actions") == 0;
-}
-
-static const json_t *
-find_property(const json_t *props, const char *which)
-{
-	const json_t *obj;
-	size_t index;
-
-	json_array_foreach(props, index, obj) {
-		if (!json_is_object(obj))
-			continue;
-
-		const json_t *key = json_object_get(obj, "name");
-		const json_t *value = json_object_get(obj, "value");
-
-		if (json_is_string(key) && value && strcmp(json_string_value(key), which) == 0)
-			return value;
-	}
-
-	return NULL;
-}
-
-static void
-write_title(const json_t *props)
-{
-	const json_t *prop_title = find_property(props, "title");
-
-	if (prop_title && json_is_string(prop_title))
-		printf("title|%s\n", json_string_value(prop_title));
-}
-
-static void
-write_origin(const json_t *props)
-{
-	const json_t *prop_origin_x = find_property(props, "origin-x");
-	const json_t *prop_origin_y = find_property(props, "origin-y");
-
-	if (!prop_origin_x || !json_is_integer(prop_origin_x) ||
-	    !prop_origin_y || !json_is_integer(prop_origin_y))
-		return;
-
-	printf("origin|%d|%d\n",
-	    (int)json_integer_value(prop_origin_x),
-	    (int)json_integer_value(prop_origin_y));
-}
-
-static void
-write_properties(const json_t *props)
-{
-	write_title(props);
-	write_origin(props);
-}
-
-static void
-write_dimensions(const json_t *document)
-{
-	json_t *width = json_object_get(document, "width");
-	json_t *height = json_object_get(document, "height");
-
-	if (!width || !json_is_integer(width))
-		die("missing 'width' property\n");
-	if (!height || !json_is_integer(height))
-		die("missing 'height' property\n");
-
-	printf("columns|%d\n", (int)json_integer_value(width));
-	printf("rows|%d\n", (int)json_integer_value(height));
-}
-
-static void
-write_object(const json_t *object)
-{
-	assert(json_is_object(object));
-
-	json_t *x = json_object_get(object, "x");
-	json_t *y = json_object_get(object, "y");
-	json_t *width = json_object_get(object, "width");
-	json_t *height = json_object_get(object, "height");
-	json_t *props = json_object_get(object, "properties");
-	const json_t *exec, *block;
-
-	if (!x || !json_is_number(x))
-		die("invalid 'x' property in object\n");
-	if (!y || !json_is_number(y))
-		die("invalid 'y' property in object\n");
-	if (!width || !json_is_number(width))
-		die("invalid 'width' property in object\n");
-	if (!height || !json_is_number(height))
-		die("invalid 'height' property in object\n");
-
-	/* This is optional and set to 0 if not present. */
-	block = find_property(props, "block");
-
-	/* In tiled, those properties are float but we only use ints in MA */
-	printf("%d|%d|%d|%d|%d",
-	    (int)json_integer_value(x),
-	    (int)json_integer_value(y),
-	    (int)json_integer_value(width),
-	    (int)json_integer_value(height),
-	    (int)json_is_true(block)
-	);
-
-	if ((exec = find_property(props, "exec")) && json_is_string(exec))
-		printf("|%s", json_string_value(exec));
-
-	printf("\n");
-}
-
-static void
-write_layer(const json_t *layer)
-{
-	json_t *objects = json_object_get(layer, "objects");
-	json_t *data = json_object_get(layer, "data");
-	json_t *name = json_object_get(layer, "name");
-	json_t *tile, *object;
-	size_t index;
-
-	if (!name || !json_is_string(name))
-		die("invalid 'name' property in layer");
-	if (!is_layer(json_string_value(name)))
-		die("invalid 'name' layer: %s\n", json_string_value(name));
-
-	printf("layer|%s\n", json_string_value(name));
-
-	/* Only foreground/background have 'data' property */
-	if (json_is_array(data)) {
-		json_array_foreach(data, index, tile) {
-			if (!json_is_integer(tile))
-				die("invalid 'data' property in layer\n");
-
-			printf("%d\n", (int)json_integer_value(tile));
-		}
-	}
-
-	/* Only objects has 'objects' property */
-	if (json_is_array(objects)) {
-		json_array_foreach(objects, index, object) {
-			if (!json_is_object(object))
-				die("invalid 'objects' property in layer\n");
-
-			write_object(object);
-		}
-	}
-}
-
-static void
-write_layers(const json_t *layers)
-{
-	size_t index;
-	json_t *layer;
-
-	if (!layers)
-		return;
-
-	json_array_foreach(layers, index, layer) {
-		if (!json_is_object(layer))
-			die("layer is not an object\n");
-
-		write_layer(layer);
-	}
-}
-
-static void
-write_tileset(const json_t *tilesets)
-{
-	char path[PATH_MAX];
-	char filename[FILENAME_MAX] = {0}, *ext;
-	const json_t *tileset, *source;
-
-	if (json_array_size(tilesets) != 1)
-		die("map must contain exactly one tileset");
-
-	tileset = json_array_get(tilesets, 0);
-	source = json_object_get(tileset, "source");
-
-	if (!json_is_string(source))
-		die("invalid 'source' property in tileset\n");
-
-	/* We need to replace the .json extension to .tileset. */
-	snprintf(path, sizeof (path), "%s", json_string_value(source));
-	snprintf(filename, sizeof (filename), "%s", util_basename(path));
-
-	if (!(ext = strstr(filename, ".json")))
-		die("could not determine tileset extension");
-
-	*ext = '\0';
-
-	printf("tileset|%s.tileset\n", filename);
-}
-
-int
-main(void)
-{
-	json_t *document;
-	json_error_t error;
-
-	document = json_loadf(stdin, 0, &error);
-
-	if (!document)
-		die("%d:%d: %s\n", error.line, error.column, error.text);
-
-	write_properties(json_object_get(document, "properties"));
-	write_dimensions(document);
-	write_layers(json_object_get(document, "layers"));
-	write_tileset(json_object_get(document, "tilesets"));
-
-	json_decref(document);
-}
--- a/src/tools/tileset/mlk-tileset.c	Sat Oct 15 21:24:17 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,204 +0,0 @@
-/*
- * main.c -- convert tiled tilesets JSON files into custom files
- *
- * 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 <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <jansson.h>
-
-static void
-die(const char *fmt, ...)
-{
-	assert(fmt);
-
-	va_list ap;
-
-	va_start(ap, fmt);
-	vfprintf(stderr, fmt, ap);
-	va_end(ap);
-	exit(1);
-}
-
-static void
-write_dimensions(const json_t *document)
-{
-	const json_t *tilewidth = json_object_get(document, "tilewidth");
-	const json_t *tileheight = json_object_get(document, "tileheight");
-
-	if (!json_is_integer(tilewidth))
-		die("invalid 'tilewidth' property\n");
-	if (!json_is_integer(tileheight))
-		die("invalid 'tileheight' property\n");
-
-	printf("tilewidth|%u\n", (unsigned int)json_integer_value(tilewidth));
-	printf("tileheight|%u\n", (unsigned int)json_integer_value(tileheight));
-}
-
-static void
-write_image(const json_t *document)
-{
-	const json_t *image = json_object_get(document, "image");
-
-	if (!json_is_string(image))
-		die("invalid 'image' property\n");
-
-	printf("image|%s\n", json_string_value(image));
-}
-
-static const json_t *
-find_property_value(const json_t *array, const char *prop)
-{
-	const json_t *obj;
-	size_t i;
-
-	json_array_foreach(array, i, obj) {
-		const json_t *name = json_object_get(obj, "name");
-
-		if (!name || !json_is_string(name))
-			die("invalid property object\n");
-
-		if (strcmp(json_string_value(name), prop) == 0)
-			return json_object_get(obj, "value");
-	}
-
-	return NULL;
-}
-
-static void
-write_animation(const json_t *tile)
-{
-	const json_t *id = json_object_get(tile, "id");
-	const json_t *properties = json_object_get(tile, "properties");
-	const json_t *file = find_property_value(properties, "animation-file");
-	const json_t *delay = find_property_value(properties, "animation-delay");
-
-	/* Animations are completely optional. */
-	if (!json_is_array(properties))
-		return;
-
-	if (!json_is_integer(id))
-		die("invalid 'id' property in tile\n");
-
-	if (json_is_string(file)) {
-		printf("%d|%s|", (int)json_integer_value(id), json_string_value(file));
-
-		if (json_is_integer(delay))
-			printf("%d\n", (int)json_integer_value(delay));
-		else
-			printf("10\n");
-	}
-}
-
-static void
-write_tiledef(const json_t *tile)
-{
-	const json_t *id = json_object_get(tile, "id");
-	const json_t *objectgroup = json_object_get(tile, "objectgroup");
-	const json_t *objects = json_object_get(objectgroup, "objects");
-	const json_t *first = json_array_get(objects, 0);
-	const json_t *x, *y, *w, *h;
-
-	/* Collisions are optional. */
-	if (!json_is_object(objectgroup))
-		return;
-
-	if (!json_is_integer(id))
-		die("invalid 'id' property in tile\n");
-	if (!json_is_array(objects))
-		die("invalid 'objects' property in tile\n");
-
-	x = json_object_get(first, "x");
-	y = json_object_get(first, "y");
-	w = json_object_get(first, "width");
-	h = json_object_get(first, "height");
-
-	if (!json_is_integer(x) || !json_is_integer(y) ||
-	    !json_is_integer(w) || !json_is_integer(h))
-		die("invalid collide object in tile description\n");
-
-	printf("%d|%d|%d|%d|%d\n",
-	    (int)json_integer_value(id),
-	    (int)json_integer_value(x),
-	    (int)json_integer_value(y),
-	    (int)json_integer_value(w),
-	    (int)json_integer_value(h));
-}
-
-static void
-write_tiledefs(const json_t *tiles)
-{
-	size_t index;
-	json_t *object;
-
-	if (!json_is_array(tiles))
-		return;
-
-	puts("tiledefs");
-
-	json_array_foreach(tiles, index, object) {
-		if (!json_is_object(object))
-			die("tile is not an object\n");
-
-		write_tiledef(object);
-	}
-}
-
-static void
-write_animations(const json_t *tiles)
-{
-	size_t index;
-	json_t *object;
-
-	if (!json_is_array(tiles))
-		return;
-
-	puts("animations");
-
-	json_array_foreach(tiles, index, object) {
-		if (!json_is_object(object))
-			die("tile is not an object\n");
-
-		write_animation(object);
-	}
-}
-
-int
-main(int argc, char *argv[])
-{
-	(void)argc;
-	(void)argv;
-
-	json_t *document;
-	json_error_t error;
-
-	document = json_loadf(stdin, 0, &error);
-
-	if (!document)
-		die("%d:%d: %s\n", error.line, error.column, error.text);
-	if (!json_is_object(document))
-		die("root value isn't an object\n");
-
-	write_dimensions(document);
-	write_image(document);
-	write_tiledefs(json_object_get(document, "tiles"));
-	write_animations(json_object_get(document, "tiles"));
-
-	json_decref(document);
-}