summaryrefslogtreecommitdiff
path: root/tools/mzscript.c
diff options
context:
space:
mode:
authorKonAki <konaki@anokonaki.org>2026-10-14 12:16:31 +0800
committerKonAki <konaki@anokonaki.org>2026-10-14 12:16:31 +0800
commitee1aa5715693f7a8bd4886641dea0f6900a30eaa (patch)
treeac29a783fafa5a469f438d0fb1b51d01667e2bb3 /tools/mzscript.c
parent68565896993ac42769b02eb809c883a7a5726e00 (diff)
add mzscript and kons2c, converters write C directly through konscriptc
Diffstat (limited to 'tools/mzscript.c')
-rw-r--r--tools/mzscript.c129
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++) {