Mercurial > molko
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); -}