summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonAki <konaki@anokonaki.org>2026-10-15 05:40:52 +0800
committerKonAki <konaki@anokonaki.org>2026-10-15 05:40:52 +0800
commit4cc59a3d028629fbfffeddf89ab9af20c3b878d2 (patch)
tree4e056e6325beeef95581bdd3a0e6d657b6282439
parent79957363275663e82900160b5a08aa56fc21086c (diff)
add rmmap module: const data shapes for RPG Maker maps
-rw-r--r--kon/konrmmap.c65
-rw-r--r--kon/konrmmap.h150
2 files changed, 215 insertions, 0 deletions
diff --git a/kon/konrmmap.c b/kon/konrmmap.c
new file mode 100644
index 0000000..0487d84
--- /dev/null
+++ b/kon/konrmmap.c
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * konrmmap.c
+ *
+ * Copyright (c) 2026 KonAki
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "konrmmap.h"
+
+#include <stddef.h>
+
+/*** pages ***/
+
+static int pageActive(const kon_rmPage_t *page, int mapId, int eventId, const kon_rmState_t *state)
+{
+ if (page->hasSwitch1 && !(state && state->switchOn && state->switchOn(page->switch1, state->user))) return 0;
+ if (page->hasSwitch2 && !(state && state->switchOn && state->switchOn(page->switch2, state->user))) return 0;
+ if (page->hasVariable) {
+ int value = state && state->variable ? state->variable(page->variable, state->user) : 0;
+
+ if (value < page->variableValue) return 0;
+ }
+ if (page->hasSelfSwitch && !(state && state->selfSwitch && state->selfSwitch(mapId, eventId, page->selfSwitch, state->user))) return 0;
+ if (page->hasItem && !(state && state->hasItem && state->hasItem(page->item, state->user))) return 0;
+ if (page->hasActor && !(state && state->hasActor && state->hasActor(page->actor, state->user))) return 0;
+ return 1;
+}
+
+int kon_rmEventPage(const kon_rmEvent_t *event, int mapId, const kon_rmState_t *state)
+{
+ int i;
+
+ if (!event || !event->pages) return -1;
+ for (i = event->pageCount - 1; i >= 0; i--) {
+ if (pageActive(&event->pages[i], mapId, event->id, state)) return i;
+ }
+ return -1;
+}
+
+/*** tiles ***/
+
+int kon_rmTile(const kon_rmMap_t *map, int layer, int x, int y)
+{
+ if (!map || !map->tiles || layer < 0 || layer >= KON_RM_LAYERS) return 0;
+ if (x < 0 || y < 0 || x >= map->width || y >= map->height) return 0;
+ return map->tiles[((size_t)layer * (size_t)map->height + (size_t)y) * (size_t)map->width + (size_t)x];
+}
diff --git a/kon/konrmmap.h b/kon/konrmmap.h
new file mode 100644
index 0000000..6274822
--- /dev/null
+++ b/kon/konrmmap.h
@@ -0,0 +1,150 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * konrmmap.h
+ *
+ * Copyright (c) 2026 KonAki
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef KONRMMAP_H
+#define KONRMMAP_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*** definition ***/
+
+/* what mzmap writes for a map of an RPG Maker MV or MZ game: all of it const data, so it can sit in the program as it is.
+ the structs are only ever read. the event scripts are not in here, a page names the label of its script in the konscript
+ the converter wrote next to it ("m3e12p1" is map 3, event 12, page 1) */
+
+#define KON_RM_LAYERS 6 /* four tile layers, then shadows, then regions */
+
+typedef struct kon_rmPage {
+ /* conditions, each used only when its flag is 1 */
+ uint8_t hasSwitch1, hasSwitch2, hasVariable, hasSelfSwitch, hasItem, hasActor;
+ char selfSwitch; /* 'A' to 'D' */
+ int switch1, switch2, variable, variableValue, item, actor;
+
+ /* a character sheet, or a tile of the map's tileset when tileId is not 0 */
+ const char *characterName;
+ int characterIndex, direction, pattern, tileId;
+
+ uint8_t moveType; /* 0 fixed, 1 random, 2 approach, 3 custom */
+ uint8_t moveSpeed, moveFrequency;
+ uint8_t priority; /* 0 under the characters, 1 same as them, 2 over them */
+ uint8_t trigger; /* 0 action button, 1 player touch, 2 event touch, 3 autorun, 4 parallel */
+ uint8_t walkAnime, stepAnime, directionFix, through;
+ uint8_t routeRepeat, routeSkippable, routeWait;
+
+ const char *script;
+
+ /* the custom move route, a command and its numbers after each other: code, count, count numbers. a count of 0
+ for a command that had text, which is not kept. empty for none */
+ const int32_t *route;
+ int routeSize;
+} kon_rmPage_t;
+
+typedef struct kon_rmEvent {
+ int id;
+ const char *name;
+ int x, y;
+ const kon_rmPage_t *pages;
+ int pageCount;
+} kon_rmEvent_t;
+
+typedef struct kon_rmEncounter {
+ int troopId;
+ int weight;
+ const int *regions; /* where it can happen, none means everywhere */
+ int regionCount;
+} kon_rmEncounter_t;
+
+typedef struct kon_rmAudio {
+ const char *name; /* "" for none */
+ int volume, pitch, pan;
+} kon_rmAudio_t;
+
+typedef struct kon_rmMap {
+ int id;
+ int width, height;
+ int tilesetId;
+ const uint16_t *tiles; /* the layers one after the other, each width * height, row by row */
+ const char *displayName;
+ const char *note;
+ int scrollType; /* 0 none, 1 loops up and down, 2 loops left and right, 3 both */
+ int disableDashing;
+ int autoplayBgm, autoplayBgs;
+ kon_rmAudio_t bgm, bgs;
+ const char *parallaxName;
+ int parallaxLoopX, parallaxLoopY, parallaxSx, parallaxSy, parallaxShow;
+ int encounterStep;
+ const kon_rmEncounter_t *encounters;
+ int encounterCount;
+ const kon_rmEvent_t *events;
+ int eventCount;
+} kon_rmMap_t;
+
+typedef struct kon_rmTileset {
+ int id;
+ int mode; /* 0 for the world map, 1 for the others */
+ const char *names[9]; /* A1 to A5, then B to E, "" when there is none */
+ const uint16_t *flags;
+ int flagCount;
+} kon_rmTileset_t;
+
+typedef struct kon_rmSystem {
+ const char *title;
+ int startMapId, startX, startY;
+ const int *party;
+ int partyCount;
+ int switchCount, variableCount;
+ int optFollowers, optTransparent;
+ int windowTone[3];
+} kon_rmSystem_t;
+
+/*** pages ***/
+
+/* what a page needs to know about the game to be switched on. any of them can be NULL, which reads as off, 0 and no */
+typedef struct kon_rmState {
+ int (*switchOn)(int id, void *user);
+ int (*variable)(int id, void *user);
+ int (*selfSwitch)(int mapId, int eventId, char letter, void *user);
+ int (*hasItem)(int id, void *user);
+ int (*hasActor)(int id, void *user);
+ void *user;
+} kon_rmState_t;
+
+/* the page an event is showing, like RPG Maker picks it: the last one that has all its conditions, counted from the end.
+ returns -1 when none of them do, then the event is not on the map at all */
+int kon_rmEventPage(const kon_rmEvent_t *event, int mapId, const kon_rmState_t *state);
+
+/*** tiles ***/
+
+/* layer is 0 to 5, the four tile layers, the shadows and the regions. 0 outside of the map or for a layer that is not there */
+int kon_rmTile(const kon_rmMap_t *map, int layer, int x, int y);
+
+#ifdef __cplusplus
+}
+#endif
+#endif