yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
atlas_annotations.h
Go to the documentation of this file.
1#ifndef YAZE_ZELDA3_ATLAS_ATLAS_ANNOTATIONS_H_
2#define YAZE_ZELDA3_ATLAS_ATLAS_ANNOTATIONS_H_
3
4// Atlas annotations: what a project adds to the ROM facts behind the Atlas
5// map views (names, colors, hand areas, plans, links that only exist in ASM).
6//
7// Accepted files (detected from content):
8// - yaze.atlas/1: {"schema": "yaze.atlas/1", ...}. Schema:
9// assets/atlas/atlas-annotations-1.schema.json; guide:
10// docs/public/guides/atlas-annotations.md.
11// - Oracle of Secrets room file (Scripts/Maps/room_annotations.json):
12// dungeon_codes, areas, room_names, runtime_pits, plans.
13// - Oracle of Secrets overworld file (Scripts/Maps/overworld_annotations.json):
14// regions, names, gate_notes, special_edge_block, sw_isolated_maps, links.
15//
16// Loading is strict: an unknown key, a bad ID, a room or map out of range or
17// a bad color is an error that names the file and the JSON pointer. Keys that
18// start with '_' (for example "_about") are comments and are ignored.
19//
20// Merge order: built-in vanilla defaults (unless disabled), then files in the
21// order given. Scalars: last writer wins. dungeons, areas, plans, links (with
22// an id), overworld regions and gates merge by key; other lists concatenate.
23
24#include <cstdint>
25#include <map>
26#include <optional>
27#include <string>
28#include <vector>
29
30#include "absl/status/status.h"
31#include "absl/status/statusor.h"
32
33namespace yaze::zelda3::atlas {
34
35inline constexpr int kAtlasRoomCount = 0x128; // Rooms $000-$127.
36inline constexpr int kAtlasMapCount = 0xA0; // Overworld maps $00-$9F.
37
38struct AtlasColor {
39 uint8_t r = 0;
40 uint8_t g = 0;
41 uint8_t b = 0;
42 std::string Hex() const; // "#RRGGBB"
43 bool operator==(const AtlasColor& other) const {
44 return r == other.r && g == other.g && b == other.b;
45 }
46};
47
48// Where a fact came from. JSON and tooltips print ToString():
49// "rom", "registry", "annotation:<file>", "symbol:<label>", "default".
50enum class Provenance : uint8_t {
51 kRom,
54 kSymbol,
56};
57
58struct Origin {
60 std::string ref; // File name (annotation) or label (symbol).
61 std::string ToString() const;
62 static Origin Rom() { return {Provenance::kRom, ""}; }
63 static Origin Registry() { return {Provenance::kRegistry, ""}; }
64 static Origin Default() { return {Provenance::kDefault, ""}; }
65 static Origin Annotation(std::string file) {
66 return {Provenance::kAnnotation, std::move(file)};
67 }
68 static Origin Symbol(std::string label) {
69 return {Provenance::kSymbol, std::move(label)};
70 }
71};
72
73// Display data for a census owner: a project registry dungeon (`owner`) or an
74// entrance dungeon ID (`dungeon_id`, for owners derived from entrances).
76 std::string owner; // Registry dungeon ID ("D1", "FOS"), or empty.
77 int dungeon_id = -1; // Entrance dungeon ID byte, or -1.
78 std::string code; // Legend code, <= 4 characters.
79 std::string name;
80 std::optional<AtlasColor> color;
81 Origin origin; // Last writer of code/name.
82 Origin color_origin; // Writer of `color`.
83};
84
85// Hand-assigned owner for rooms the ROM cannot place.
87 std::string key;
88 std::string code;
89 std::string name;
90 std::optional<AtlasColor> color;
91 std::vector<int> rooms;
92 std::string note; // "source" in the file.
94};
95
97 std::string name;
98 bool reserved = false; // status: "reserved"
99 std::string note;
101};
102
103enum class AtlasView : uint8_t { kDungeon, kOverworld };
104
105// A link the ROM does not show (ASM warps, scripted triggers). `to` < 0 is a
106// label-only pill.
108 std::string id; // Merge key, optional.
110 std::string kind; // pit, warp, stair, pad, whirlpool, special, dream, warn
111 int from = -1;
112 int to = -1;
113 std::string label;
114 std::string note; // "source" in the file.
116};
117
118// Room list read from the ROM at a symbol (for example Oracle's dream warps).
120 std::string symbol;
121 int count = 0;
122 int width = 1; // Bytes per entry: 1 or 2.
123 std::string kind;
124 std::string label; // "{n}" = 1-based index; empty: "<KIND> {n}".
126};
127
129 std::string key;
130 std::string label;
131 std::string name;
132 std::string status; // "decided" or "provisional" (empty = unspecified)
133 std::optional<AtlasColor> color;
134 std::vector<int> rooms;
135 std::string note;
137};
138
139// Item IDs that decide chest and pot badges (vanilla by default).
141 int small_key = 0x24;
142 int compass = 0x25;
143 int big_key = 0x32;
144 int map = 0x33;
145 int pot_small_key = 0x08;
146};
147
148// Overworld annotations. Parsed and validated in P1; used by the overworld
149// Atlas (P2).
151 std::string title;
152 std::string subtitle;
153 std::vector<int> maps;
154 double origin_col = 0.0;
155 double origin_row = 0.0;
157};
158
160 std::string name;
161 std::string code;
162 std::string world; // "LW", "DW", "SW"
163 std::optional<AtlasColor> color;
164 std::vector<int> maps;
166};
167
169 std::string name;
170 std::string note;
172};
173
175 int map = 0;
176 std::string gate; // Glove, Mitt, Hammer, Boots
177 std::string note;
178 std::string role; // ROUTE, POCKET, DECOR or empty (automatic)
179 bool suppress = false;
181};
182
184 int a = 0;
185 int b = 0;
186 std::string status; // open, swim, blocked, special
187 std::string note;
189};
190
192 std::vector<OverworldSectionAnnotation> sections;
193 std::vector<OverworldRegionAnnotation> regions;
194 std::map<int, OverworldMapAnnotation> maps;
195 std::vector<OverworldGateAnnotation> gates;
196 std::vector<OverworldEdgeAnnotation> edges;
197 std::vector<int> closed_border_maps;
198 std::vector<int> isolated_maps;
199 std::map<std::string, std::vector<int>> tile_classes;
200 std::optional<int> gate_role_big;
201 std::optional<int> gate_role_small;
202 std::string warp_tile_rule; // "toggle_world", "none", empty = default
203};
204
206 std::string title;
208 std::vector<DungeonAnnotation> dungeons;
209 std::vector<AreaAnnotation> areas;
210 std::map<int, RoomAnnotation> rooms;
211 std::vector<LinkAnnotation> links;
212 std::vector<SymbolLinkAnnotation> symbol_links;
213 std::vector<PlanAnnotation> plans;
214 std::vector<std::string> legend_notes_dungeon;
215 std::vector<std::string> legend_notes_overworld;
218 bool vanilla_defaults = false; // The built-in set was applied.
219 std::vector<std::string> files; // Merged files (names), in order.
220};
221
222enum class AnnotationFormat : uint8_t {
223 kAtlasV1, // "schema": "yaze.atlas/1"
224 kOracleRoomV0, // Oracle Scripts/Maps/room_annotations.json
225 kOracleOverworldV0 // Oracle Scripts/Maps/overworld_annotations.json
226};
227const char* AnnotationFormatName(AnnotationFormat format);
228
229// Parses one annotation document and merges it into `out`. `file_label`
230// names the file in provenance ("annotation:<file_label>") and errors.
231absl::Status MergeAtlasAnnotationText(const std::string& text,
232 const std::string& file_label,
233 AtlasAnnotations* out,
234 AnnotationFormat* format = nullptr);
235
236// Reads `path` and merges it; the label is the file name.
237absl::Status MergeAtlasAnnotationFile(const std::string& path,
238 AtlasAnnotations* out,
239 AnnotationFormat* format = nullptr);
240
241// Built-in vanilla set (dungeon codes, names and colors keyed by entrance
242// dungeon ID), origin "default".
243void ApplyVanillaAtlasDefaults(AtlasAnnotations* out);
244
245// `defaults`: "vanilla" or "none" (the [atlas] defaults key); anything else
246// is an error. Then every file in order.
247absl::StatusOr<AtlasAnnotations> LoadAtlasAnnotations(
248 const std::vector<std::string>& files, const std::string& defaults);
249
250// "0x81", "0x11D", "81" (hex) or a JSON integer, as text. Exposed for tests.
251std::optional<int> ParseAtlasId(const std::string& text);
252
253} // namespace yaze::zelda3::atlas
254
255#endif // YAZE_ZELDA3_ATLAS_ATLAS_ANNOTATIONS_H_
constexpr int kAtlasMapCount
absl::Status MergeAtlasAnnotationFile(const std::string &path, AtlasAnnotations *out, AnnotationFormat *format)
void ApplyVanillaAtlasDefaults(AtlasAnnotations *out)
absl::Status MergeAtlasAnnotationText(const std::string &text, const std::string &file_label, AtlasAnnotations *out, AnnotationFormat *format)
constexpr int kAtlasRoomCount
absl::StatusOr< AtlasAnnotations > LoadAtlasAnnotations(const std::vector< std::string > &files, const std::string &defaults)
std::optional< int > ParseAtlasId(const std::string &text)
const char * AnnotationFormatName(AnnotationFormat format)
std::optional< AtlasColor > color
std::vector< std::string > legend_notes_dungeon
std::vector< LinkAnnotation > links
std::vector< SymbolLinkAnnotation > symbol_links
std::vector< PlanAnnotation > plans
std::vector< DungeonAnnotation > dungeons
std::vector< AreaAnnotation > areas
std::vector< std::string > legend_notes_overworld
std::map< int, RoomAnnotation > rooms
bool operator==(const AtlasColor &other) const
static Origin Symbol(std::string label)
static Origin Annotation(std::string file)
std::vector< OverworldGateAnnotation > gates
std::vector< OverworldSectionAnnotation > sections
std::map< std::string, std::vector< int > > tile_classes
std::vector< OverworldEdgeAnnotation > edges
std::vector< OverworldRegionAnnotation > regions
std::map< int, OverworldMapAnnotation > maps
std::optional< AtlasColor > color