diff options
| author | KonAki <konaki@anokonaki.org> | 2026-10-14 12:16:31 +0800 |
|---|---|---|
| committer | KonAki <konaki@anokonaki.org> | 2026-10-14 12:16:31 +0800 |
| commit | ee1aa5715693f7a8bd4886641dea0f6900a30eaa (patch) | |
| tree | ac29a783fafa5a469f438d0fb1b51d01667e2bb3 /tools/mzscript.c | |
| parent | 68565896993ac42769b02eb809c883a7a5726e00 (diff) | |
add mzscript and kons2c, converters write C directly through konscriptc
Diffstat (limited to 'tools/mzscript.c')
| -rw-r--r-- | tools/mzscript.c | 129 |
1 files changed, 95 insertions, 34 deletions
diff --git a/tools/mzscript.c b/tools/mzscript.c index f9371f6..077efb2 100644 --- a/tools/mzscript.c +++ b/tools/mzscript.c @@ -24,21 +24,26 @@ */ /* - * usage: mzscript <data folder> <output folder> - * turns the events of an exported RPG Maker MV or MZ game into konscript text. + * usage: mzscript [-n name] [-split rows] [-text] <data folder> <output folder> + * turns the events of an exported RPG Maker MV or MZ game into C, ready to build with the engine. * - * script.kons every common event (label common_N), troop page (tN pM) and map event page (mN eN pN) as one script - * speakers.tsv what the numbers after say mean: number, face file, face index, name, window background, window position + * name.h, name.c every common event (label common_N), troop page (tN pM) and map event page (mN eN pN) as one list of + * kon_cmd_t, see konscriptc.h for how it is written and checked. with -split the list is also name_0.inc and so on + * name_speakers.c what the numbers after say mean: face file, face index, name, window background, window position, + * and the scratch switch and variable the host answers conditions and battle results in + * name.kons only with -text, the same script as konscript text for reading * * what konscript has itself becomes konscript. everything else becomes host commands, where the host number is the * RPG Maker command code and the parameters are b, c, d (the first three numbers) and a text with all of them split by - * tabs, in the order RPG Maker keeps them. a choice, loop or battle result is turned into labels and jumps. - * conditions and battle results that konscript can't test are answered by the host in scratch switch and scratch variable + * tabs, in the order RPG Maker keeps them. a choice, loop or battle result is turned into labels and jumps */ #define KONJSON_IMPLEMENTATION #include "konjson.h" +#define KONSCRIPTC_IMPLEMENTATION +#include "konscriptc.h" +#include <ctype.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -731,31 +736,88 @@ static kon_json_t *load(const char *folder, const char *name) return j; } +static int writeSpeakers(const char *prefix, const char *name, int scratchSwitch, int scratchVar) +{ + char path[1100]; + const char *base = strrchr(prefix, '/'); + char upper[64]; + FILE *f; + int k; + + base = base ? base + 1 : prefix; + for (k = 0; name[k] && k < 63; k++) upper[k] = (char)toupper((unsigned char)name[k]); + upper[k] = '\0'; + snprintf(path, sizeof path, "%s_speakers.h", prefix); + f = fopen(path, "wb"); + if (!f) { + fprintf(stderr, "cannot write %s\n", path); + return 1; + } + fprintf(f, "/* made by mzscript, don't edit */\n\n#ifndef %s_SPEAKERS_H\n#define %s_SPEAKERS_H\n\n", upper, upper); + fprintf(f, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"); + fprintf(f, "/* the host answers conditions and battle results in this switch and variable */\n"); + fprintf(f, "#define %s_SCRATCH_SWITCH %d\n#define %s_SCRATCH_VARIABLE %d\n\n", upper, scratchSwitch, upper, scratchVar); + fprintf(f, "typedef struct %s_speaker {\n\tconst char *face;\n\tint faceIndex;\n\tconst char *name;\n\tint background, position;\n} %s_speaker_t;\n\n", name, name); + fprintf(f, "extern const int %s_speakerCount;\nextern const %s_speaker_t %s_speakers[%d];\n\n", name, name, name, speakerCount > 0 ? speakerCount : 1); + fprintf(f, "#ifdef __cplusplus\n}\n#endif\n#endif\n"); + if (fclose(f) != 0) return 1; + + snprintf(path, sizeof path, "%s_speakers.c", prefix); + f = fopen(path, "wb"); + if (!f) { + fprintf(stderr, "cannot write %s\n", path); + return 1; + } + fprintf(f, "/* made by mzscript, don't edit */\n\n#include \"%s_speakers.h\"\n\n", base); + fprintf(f, "const int %s_speakerCount = %d;\n\n", name, speakerCount); + fprintf(f, "const %s_speaker_t %s_speakers[%d] = {\n", name, name, speakerCount > 0 ? speakerCount : 1); + for (k = 0; k < speakerCount; k++) { + fputs("\t{", f); + konsc_string(f, speakers[k].face); + fprintf(f, ", %d, ", speakers[k].index); + konsc_string(f, speakers[k].name); + fprintf(f, ", %d, %d},\n", speakers[k].background, speakers[k].position); + } + if (!speakerCount) fputs("\t{\"\", 0, \"\", 0, 0}\n", f); + fputs("};\n", f); + return fclose(f) != 0; +} + int main(int argc, char **argv) { buf_t out; context_t c; kon_json_t *system, *json; - char path[1024], scope[40]; - int id, k, p, maxCommon = 0, entries = 0; - FILE *f; - - if (argc < 3) { - fprintf(stderr, "usage: mzscript <data folder> <output folder>\n"); + char scope[40], name[64] = "game", prefix[1024], error[200]; + const char *folder = NULL, *outFolder = NULL; + int id, k, p, a, maxCommon = 0, entries = 0, split = 0, text = 0; + konsc_result_t result; + + for (a = 1; a < argc; a++) { + if (!strcmp(argv[a], "-n") && a + 1 < argc) snprintf(name, sizeof name, "%s", argv[++a]); + else if (!strcmp(argv[a], "-split") && a + 1 < argc) split = atoi(argv[++a]); + else if (!strcmp(argv[a], "-text")) text = 1; + else if (!folder) folder = argv[a]; + else if (!outFolder) outFolder = argv[a]; + } + if (!folder || !outFolder) { + fprintf(stderr, "usage: mzscript [-n name] [-split rows] [-text] <data folder> <output folder>\n"); return 2; } + snprintf(prefix, sizeof prefix, "%s/%s", outFolder, name); + memset(&out, 0, sizeof out); memset(&c, 0, sizeof c); c.out = &out; - system = load(argv[1], "System.json"); + system = load(folder, "System.json"); if (!system) return 1; c.scratchSwitch = kon_jsonCount(kon_jsonGet(system, "switches")) + 1; c.scratchVar = kon_jsonCount(kon_jsonGet(system, "variables")) + 1; kon_jsonFree(system); put(&out, "# scratch switch s%d and scratch variable v%d are the host's\n\n", c.scratchSwitch, c.scratchVar); - json = load(argv[1], "CommonEvents.json"); + json = load(folder, "CommonEvents.json"); if (json) { maxCommon = kon_jsonCount(json) - 1; c.maxCommon = maxCommon; @@ -773,7 +835,7 @@ int main(int argc, char **argv) kon_jsonFree(json); } - json = load(argv[1], "Troops.json"); + json = load(folder, "Troops.json"); if (json) { for (id = 1; id < kon_jsonCount(json); id++) { const kon_json_t *pages = kon_jsonGet(kon_jsonAt(json, id), "pages"); @@ -792,11 +854,11 @@ int main(int argc, char **argv) } for (id = 1; id < 2000; id++) { - char name[32]; + char file[32]; const kon_json_t *events; - snprintf(name, sizeof name, "Map%03d.json", id); - json = load(argv[1], name); + snprintf(file, sizeof file, "Map%03d.json", id); + json = load(folder, file); if (!json) continue; events = kon_jsonGet(json, "events"); for (k = 1; k < kon_jsonCount(events); k++) { @@ -816,26 +878,25 @@ int main(int argc, char **argv) kon_jsonFree(json); } - snprintf(path, sizeof path, "%s/script.kons", argv[2]); - f = fopen(path, "wb"); - if (!f) { - fprintf(stderr, "cannot write %s\n", path); - return 1; - } - fwrite(out.p, 1, out.n, f); - fclose(f); - free(out.p); + if (text) { + char path[1100]; + FILE *f; - snprintf(path, sizeof path, "%s/speakers.tsv", argv[2]); - f = fopen(path, "wb"); - if (!f) { - fprintf(stderr, "cannot write %s\n", path); + snprintf(path, sizeof path, "%s.kons", prefix); + f = fopen(path, "wb"); + if (!f || fwrite(out.p, 1, out.n, f) != out.n || fclose(f) != 0) { + fprintf(stderr, "cannot write %s\n", path); + return 1; + } + } + if (konsc_write(out.p, out.n, prefix, name, split, &result, error, sizeof error) != 0) { + fprintf(stderr, "the script could not be written: %s (use -text to see it)\n", error); return 1; } - for (k = 0; k < speakerCount; k++) fprintf(f, "%d\t%s\t%d\t%s\t%d\t%d\n", k, speakers[k].face, speakers[k].index, speakers[k].name, speakers[k].background, speakers[k].position); - fclose(f); + free(out.p); + if (writeSpeakers(prefix, name, c.scratchSwitch, c.scratchVar)) return 1; - printf("%d scripts, %d speakers\n", entries, speakerCount); + printf("%d scripts, %d commands, %d labels, %d speakers\n", entries, result.commands, result.labels, speakerCount); printf("%d commands became konscript, %d became host commands", structured, hostLines); printf(" (%d kinds)\n", hostKinds); for (k = 0; k < hostKinds; k++) { |
