yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
hack_manifest.h
Go to the documentation of this file.
1#ifndef YAZE_CORE_HACK_MANIFEST_H
2#define YAZE_CORE_HACK_MANIFEST_H
3
4#include <cstdint>
5#include <optional>
6#include <string>
7#include <unordered_map>
8#include <utility>
9#include <vector>
10
11#include "absl/status/status.h"
14
15namespace yaze::core {
16
26enum class AddressOwnership : uint8_t {
27 kVanillaSafe, // Yaze can edit; asar doesn't touch
28 kHookPatched, // Asar patches this; yaze edits are overwritten on build
29 kAsmOwned, // Entire bank owned by ASM hack
30 kShared, // Both yaze and ASM write (e.g., ZSCustomOverworld)
31 kAsmExpansion, // ROM expansion bank — only exists in patched ROM
32 kRam, // WRAM definition (not ROM data)
33 kMirror, // HiROM mirror of vanilla bank
34};
35
36std::string AddressOwnershipToString(AddressOwnership ownership);
37
42 uint32_t start;
43 uint32_t end;
45 std::string module;
46};
47
51struct OwnedBank {
52 uint8_t bank;
53 uint32_t bank_start;
54 uint32_t bank_end;
56 std::string ownership_note;
57};
58
63 uint8_t tag_id;
64 uint32_t address;
65 std::string name;
66 std::string purpose;
67 std::string source;
68 std::string feature_flag; // Empty if always enabled
69 bool enabled = true;
70};
71
76 std::string name;
77 int value;
78 bool enabled;
79 std::string source;
80};
81
86 std::string name;
87 uint32_t address;
88 std::string purpose;
89};
90
95 struct Source {
96 std::string format;
97 int version = 0;
100 };
101
102 uint32_t hook_address; // $0ED436
103 uint32_t data_start; // $2F8000
104 uint32_t data_end; // $2FFFFF
105 uint16_t first_expanded_id; // $18D
106 uint16_t last_expanded_id; // $1D1
108 int vanilla_count; // 397
109 std::optional<Source> source;
110};
111
116 std::string dev_rom;
117 std::string patched_rom;
118 std::string assembler;
119 std::string entry_point;
120 std::string build_script;
121};
122
126enum class DungeonStreamType : uint8_t {
127 kObjects,
128 kSprites,
129 kPotItems,
130};
131
135enum class DungeonPointerEncoding : uint8_t {
136 kLong24,
137 kBank16,
138};
139
143enum class DungeonWriteStrategy : uint8_t {
146};
147
152 uint32_t start = 0;
153 uint32_t end = 0;
154};
155
173
178 uint32_t address;
180 std::string module; // From protected region, if applicable
181};
182
183// ─── Project Registry (Dungeon + Overworld data) ─────────────────────────
184
189 int id;
190 std::string name;
191 std::string floor; // "F1", "B1", etc. Optional project-map label.
193 bool has_grid_position = false;
194 std::string type; // "entrance", "boss", "mini_boss", "connector", "normal"
196 uint8_t tag1, tag2;
197};
198
204 std::string label;
205 std::string direction; // For doors: "north"/"south"/"east"/"west"
206};
207
212 std::string id; // "D4"
213 std::string name; // "Zora Temple"
214 std::string vanilla_name; // "Thieves' Town"
215 std::vector<DungeonRoom> rooms;
216 std::vector<DungeonConnection> stairs;
217 std::vector<DungeonConnection> holewarps;
218 std::vector<DungeonConnection> doors;
219};
220
226 std::string name;
227 std::string world; // "LW", "DW", "SW"
229};
230
238 std::vector<DungeonEntry> dungeons;
239 std::vector<OverworldArea> overworld_areas;
241
242 // Universal resource labels: type -> {id_str -> label}
243 //
244 // Notes:
245 // - Keys are normalized to decimal strings for project::YazeProject::resource_labels.
246 // - Input JSON may use either decimal ("57") or hex ("0x39") IDs.
247 //
248 // Types: "room", "sprite", "item", "entrance", "overworld_map", "music".
249 // Oracle `dungeons.json` room names are mirrored into "room" labels so the
250 // opened project file can serialize the current registry names.
251 std::unordered_map<std::string, std::unordered_map<std::string, std::string>>
253
254 // Backward-compat accessor for room labels only
255 const std::unordered_map<std::string, std::string>& room_labels() const {
256 static const std::unordered_map<std::string, std::string> empty;
257 auto it = all_resource_labels.find("room");
258 return it != all_resource_labels.end() ? it->second : empty;
259 }
260};
261
286 public:
287 HackManifest() = default;
288
292 absl::Status LoadFromFile(const std::string& filepath);
293
297 absl::Status LoadFromString(const std::string& json_content);
298
302 [[nodiscard]] bool loaded() const { return loaded_; }
303
310 void Clear() { Reset(); }
311
312 // ─── Address Classification ───────────────────────────────
313
323 [[nodiscard]] AddressOwnership ClassifyAddress(uint32_t address) const;
324
331 [[nodiscard]] bool IsWriteOverwritten(uint32_t address) const;
332
336 [[nodiscard]] bool IsProtected(uint32_t address) const;
337
345 [[nodiscard]] bool IsEditorManaged(uint32_t address) const;
346
350 [[nodiscard]] std::optional<AddressOwnership> GetBankOwnership(
351 uint8_t bank) const;
352
353 // ─── Room Tags ────────────────────────────────────────────
354
358 [[nodiscard]] std::string GetRoomTagLabel(uint8_t tag_id) const;
359
363 [[nodiscard]] std::optional<RoomTagEntry> GetRoomTag(uint8_t tag_id) const;
364
368 [[nodiscard]] const std::vector<RoomTagEntry>& room_tags() const {
369 return room_tags_;
370 }
371
372 // ─── Feature Flags ────────────────────────────────────────
373
374 [[nodiscard]] bool IsFeatureEnabled(const std::string& flag_name) const;
375
376 [[nodiscard]] const std::vector<FeatureFlag>& feature_flags() const {
377 return feature_flags_;
378 }
379
380 // ─── SRAM ─────────────────────────────────────────────────
381
382 [[nodiscard]] std::string GetSramVariableName(uint32_t address) const;
383
384 [[nodiscard]] const std::vector<SramVariable>& sram_variables() const {
385 return sram_variables_;
386 }
387
388 // ─── Messages ─────────────────────────────────────────────
389
390 [[nodiscard]] const MessageLayout& message_layout() const {
391 return message_layout_;
392 }
393
394 [[nodiscard]] bool IsExpandedMessage(uint16_t message_id) const;
395
396 // ─── Dungeon Stream Allocation Layouts ────────────────────────────
397
404 [[nodiscard]] const DungeonStreamLayout* GetDungeonStreamLayout(
405 DungeonStreamType stream) const;
406
407 [[nodiscard]] bool HasDungeonStreamLayouts() const {
408 return !dungeon_stream_layouts_.empty();
409 }
410
411 // ─── Protected Regions ──────────────────────────────────
412
413 [[nodiscard]] const std::vector<ProtectedRegion>& protected_regions() const {
414 return protected_regions_;
415 }
416
417 [[nodiscard]] const std::vector<SnesAddressRange>& editor_managed_regions()
418 const {
420 }
421
422 [[nodiscard]] const std::unordered_map<uint8_t, OwnedBank>& owned_banks()
423 const {
424 return owned_banks_;
425 }
426
427 // ─── Write Conflict Analysis ─────────────────────────────
428
436 [[nodiscard]] std::vector<WriteConflict> AnalyzeWriteRanges(
437 const std::vector<std::pair<uint32_t, uint32_t>>& ranges) const;
438
448 [[nodiscard]] std::vector<WriteConflict> AnalyzePcWriteRanges(
449 const std::vector<std::pair<uint32_t, uint32_t>>& pc_ranges) const;
450
451 // ─── Project Registry ────────────────────────────────────
452
459 absl::Status LoadProjectRegistry(const std::string& code_folder);
460
461 [[nodiscard]] const ProjectRegistry& project_registry() const {
462 return project_registry_;
463 }
464
465 [[nodiscard]] bool HasProjectRegistry() const {
466 return !project_registry_.dungeons.empty() ||
469 }
470
471 // ─── Oracle Progression (SRAM) ─────────────────────────────
472
473 // Updates story event completion coloring based on progression state parsed
474 // from an emulator SRAM file (.srm).
476
477 // Clears any loaded progression state and resets story graph status to
478 // default (no progress).
480
481 [[nodiscard]] std::optional<OracleProgressionState> oracle_progression_state()
482 const {
484 }
485
486 // ─── Build Pipeline ───────────────────────────────────────
487
488 [[nodiscard]] const BuildPipeline& build_pipeline() const {
489 return build_pipeline_;
490 }
491
492 // ─── Metadata ─────────────────────────────────────────────
493
494 [[nodiscard]] const std::string& hack_name() const { return hack_name_; }
495 [[nodiscard]] int manifest_version() const { return manifest_version_; }
496 [[nodiscard]] int total_hooks() const { return total_hooks_; }
497
498 private:
499 void Reset();
500 [[nodiscard]] const ProtectedRegion* FindProtectedRegion(
501 uint32_t address) const;
502
503 bool loaded_ = false;
505 std::string hack_name_;
507
508 // Protected regions (vanilla bank hooks) — sorted by start address
509 std::vector<ProtectedRegion> protected_regions_;
510
511 // Exact manifest-v3 regions that remain yaze-owned inside otherwise owned
512 // banks. Sorted, disjoint, and stored as canonical LoROM addresses.
513 std::vector<SnesAddressRange> editor_managed_regions_;
514
515 // Bank ownership lookup
516 std::unordered_map<uint8_t, OwnedBank> owned_banks_;
517
518 // Room tag lookup by tag ID
519 std::unordered_map<uint8_t, RoomTagEntry> room_tag_map_;
520 std::vector<RoomTagEntry> room_tags_;
521
522 // Feature flags by name
523 std::unordered_map<std::string, FeatureFlag> feature_flag_map_;
524 std::vector<FeatureFlag> feature_flags_;
525
526 // SRAM variable lookup by address
527 std::unordered_map<uint32_t, SramVariable> sram_map_;
528 std::vector<SramVariable> sram_variables_;
529
530 // Message layout
532
533 // Explicit dungeon stream layouts, indexed by stream kind.
534 std::unordered_map<DungeonStreamType, DungeonStreamLayout>
536
537 // Build pipeline
539
540 // Project registry (loaded from code_folder JSON files)
542
543 // Optional: live progression state derived from SRAM/.srm. This is used to
544 // color story event nodes and can be updated at runtime by editor panels.
545 std::optional<OracleProgressionState> oracle_progression_state_;
546};
547
548} // namespace yaze::core
549
550#endif // YAZE_CORE_HACK_MANIFEST_H
Loads and queries the hack manifest JSON for yaze-ASM integration.
bool HasDungeonStreamLayouts() const
std::vector< WriteConflict > AnalyzeWriteRanges(const std::vector< std::pair< uint32_t, uint32_t > > &ranges) const
Analyze a set of address ranges for write conflicts.
std::unordered_map< std::string, FeatureFlag > feature_flag_map_
std::optional< RoomTagEntry > GetRoomTag(uint8_t tag_id) const
Get the full room tag entry for a tag ID.
const std::vector< FeatureFlag > & feature_flags() const
std::unordered_map< uint8_t, OwnedBank > owned_banks_
AddressOwnership ClassifyAddress(uint32_t address) const
Classify a ROM address by ownership.
bool IsFeatureEnabled(const std::string &flag_name) const
const MessageLayout & message_layout() const
std::vector< SramVariable > sram_variables_
std::vector< ProtectedRegion > protected_regions_
bool IsWriteOverwritten(uint32_t address) const
Check if a ROM write at this address would be overwritten by asar.
const std::vector< SramVariable > & sram_variables() const
const std::vector< RoomTagEntry > & room_tags() const
Get all room tags.
const std::unordered_map< uint8_t, OwnedBank > & owned_banks() const
void Clear()
Clear any loaded manifest state.
ProjectRegistry project_registry_
bool IsExpandedMessage(uint16_t message_id) const
const std::string & hack_name() const
bool IsEditorManaged(uint32_t address) const
Check if an address is explicitly managed by yaze.
const ProjectRegistry & project_registry() const
BuildPipeline build_pipeline_
std::optional< AddressOwnership > GetBankOwnership(uint8_t bank) const
Get the bank ownership for a given bank number.
std::optional< OracleProgressionState > oracle_progression_state_
bool HasProjectRegistry() const
std::unordered_map< uint32_t, SramVariable > sram_map_
std::string GetSramVariableName(uint32_t address) const
std::unordered_map< uint8_t, RoomTagEntry > room_tag_map_
std::vector< SnesAddressRange > editor_managed_regions_
std::unordered_map< DungeonStreamType, DungeonStreamLayout > dungeon_stream_layouts_
const std::vector< ProtectedRegion > & protected_regions() const
absl::Status LoadProjectRegistry(const std::string &code_folder)
Load project registry data from the code folder.
const DungeonStreamLayout * GetDungeonStreamLayout(DungeonStreamType stream) const
Get an explicitly declared dungeon stream layout.
bool IsProtected(uint32_t address) const
Check if an address is in a protected region.
std::optional< OracleProgressionState > oracle_progression_state() const
absl::Status LoadFromFile(const std::string &filepath)
Load manifest from a JSON file path.
absl::Status LoadFromString(const std::string &json_content)
Load manifest from a JSON string.
MessageLayout message_layout_
std::string GetRoomTagLabel(uint8_t tag_id) const
Get the human-readable label for a room tag ID.
std::vector< WriteConflict > AnalyzePcWriteRanges(const std::vector< std::pair< uint32_t, uint32_t > > &pc_ranges) const
Analyze a set of PC-offset ranges for write conflicts.
bool loaded() const
Check if the manifest has been loaded.
void SetOracleProgressionState(const OracleProgressionState &state)
const ProtectedRegion * FindProtectedRegion(uint32_t address) const
const std::vector< SnesAddressRange > & editor_managed_regions() const
const BuildPipeline & build_pipeline() const
std::vector< RoomTagEntry > room_tags_
std::vector< FeatureFlag > feature_flags_
The complete Oracle narrative progression graph.
bool loaded() const
Check if the graph has been loaded.
DungeonWriteStrategy
Save strategy allowed for a dungeon stream layout.
std::string AddressOwnershipToString(AddressOwnership ownership)
DungeonStreamType
Dungeon stream kinds with allocator layouts in the hack manifest.
AddressOwnership
Ownership classification for ROM addresses and banks.
DungeonPointerEncoding
Encoding used by entries in a dungeon stream pointer table.
Build pipeline information.
A connection between two rooms (stair, holewarp, or door).
A complete dungeon entry with rooms and connections.
std::vector< DungeonConnection > doors
std::vector< DungeonConnection > holewarps
std::vector< DungeonRoom > rooms
std::vector< DungeonConnection > stairs
A room within a dungeon, with spatial and metadata info.
Explicit pointer and storage layout for one dungeon stream.
DungeonWriteStrategy strategy
std::vector< SnesAddressRange > allocation_regions
std::optional< uint8_t > pointer_bank
std::vector< SnesAddressRange > data_regions
DungeonPointerEncoding pointer_encoding
A compile-time feature flag.
Message range information for the expanded message system.
std::optional< Source > source
Oracle of Secrets game progression state parsed from SRAM.
An overworld area from the overworld registry.
An expanded bank with ownership classification.
AddressOwnership ownership
std::string ownership_note
Project-level registry data loaded from the Oracle planning outputs.
std::vector< DungeonEntry > dungeons
std::vector< OverworldArea > overworld_areas
const std::unordered_map< std::string, std::string > & room_labels() const
std::unordered_map< std::string, std::unordered_map< std::string, std::string > > all_resource_labels
A contiguous protected ROM region owned by the ASM hack.
A room tag entry from the dispatch table.
A half-open [start, end) range of canonical LoROM SNES addresses.
A custom SRAM variable definition.
A conflict detected when yaze wants to write to an ASM-owned address.
AddressOwnership ownership