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 struct Source {
117 std::string format;
118 int version = 0;
119 std::string path;
120
121 bool operator==(const Source&) const = default;
122 };
123
124 std::optional<Source> source;
125};
126
131 std::string dev_rom;
132 std::string patched_rom;
133 std::string assembler;
134 std::string entry_point;
135 std::string build_script;
136};
137
141enum class DungeonStreamType : uint8_t {
142 kObjects,
143 kSprites,
144 kPotItems,
145};
146
150enum class DungeonPointerEncoding : uint8_t {
151 kLong24,
152 kBank16,
153};
154
158enum class DungeonWriteStrategy : uint8_t {
161};
162
167 uint32_t start = 0;
168 uint32_t end = 0;
169};
170
188
199 std::vector<SnesAddressRange> allocation_regions;
200 std::vector<uint16_t> reserved_sheets;
201};
202
207 uint32_t address;
209 std::string module; // From protected region, if applicable
210};
211
212// ─── Project Registry (Dungeon + Overworld data) ─────────────────────────
213
218 int id;
219 std::string name;
220 std::string floor; // "F1", "B1", etc. Optional project-map label.
222 bool has_grid_position = false;
223 std::string type; // "entrance", "boss", "mini_boss", "connector", "normal"
225 uint8_t tag1, tag2;
226};
227
233 std::string label;
234 std::string direction; // For doors: "north"/"south"/"east"/"west"
235};
236
241 std::string id; // "D4"
242 std::string name; // "Zora Temple"
243 std::string vanilla_name; // "Thieves' Town"
244 std::vector<DungeonRoom> rooms;
245 std::vector<DungeonConnection> stairs;
246 std::vector<DungeonConnection> holewarps;
247 std::vector<DungeonConnection> doors;
248};
249
255 std::string name;
256 std::string world; // "LW", "DW", "SW"
258};
259
267 std::vector<DungeonEntry> dungeons;
268 std::vector<OverworldArea> overworld_areas;
270
271 // Universal resource labels: type -> {id_str -> label}
272 //
273 // Notes:
274 // - Keys are normalized to decimal strings for project::YazeProject::resource_labels.
275 // - Input JSON may use either decimal ("57") or hex ("0x39") IDs.
276 //
277 // Types: "room", "sprite", "item", "entrance", "overworld_map", "music".
278 // Oracle `dungeons.json` room names are mirrored into "room" labels so the
279 // opened project file can serialize the current registry names.
280 std::unordered_map<std::string, std::unordered_map<std::string, std::string>>
282
283 // Backward-compat accessor for room labels only
284 const std::unordered_map<std::string, std::string>& room_labels() const {
285 static const std::unordered_map<std::string, std::string> empty;
286 auto it = all_resource_labels.find("room");
287 return it != all_resource_labels.end() ? it->second : empty;
288 }
289};
290
315 public:
316 HackManifest() = default;
317
321 absl::Status LoadFromFile(const std::string& filepath);
322
326 absl::Status LoadFromString(const std::string& json_content);
327
331 [[nodiscard]] bool loaded() const { return loaded_; }
332
339 void Clear() { Reset(); }
340
341 // ─── Address Classification ───────────────────────────────
342
352 [[nodiscard]] AddressOwnership ClassifyAddress(uint32_t address) const;
353
360 [[nodiscard]] bool IsWriteOverwritten(uint32_t address) const;
361
365 [[nodiscard]] bool IsProtected(uint32_t address) const;
366
374 [[nodiscard]] bool IsEditorManaged(uint32_t address) const;
375
379 [[nodiscard]] std::optional<AddressOwnership> GetBankOwnership(
380 uint8_t bank) const;
381
382 // ─── Room Tags ────────────────────────────────────────────
383
387 [[nodiscard]] std::string GetRoomTagLabel(uint8_t tag_id) const;
388
392 [[nodiscard]] std::optional<RoomTagEntry> GetRoomTag(uint8_t tag_id) const;
393
397 [[nodiscard]] const std::vector<RoomTagEntry>& room_tags() const {
398 return room_tags_;
399 }
400
401 // ─── Feature Flags ────────────────────────────────────────
402
403 [[nodiscard]] bool IsFeatureEnabled(const std::string& flag_name) const;
404
405 [[nodiscard]] const std::vector<FeatureFlag>& feature_flags() const {
406 return feature_flags_;
407 }
408
409 // ─── SRAM ─────────────────────────────────────────────────
410
411 [[nodiscard]] std::string GetSramVariableName(uint32_t address) const;
412
413 [[nodiscard]] const std::vector<SramVariable>& sram_variables() const {
414 return sram_variables_;
415 }
416
417 // ─── Messages ─────────────────────────────────────────────
418
419 [[nodiscard]] const MessageLayout& message_layout() const {
420 return message_layout_;
421 }
422
423 [[nodiscard]] bool IsExpandedMessage(uint16_t message_id) const;
424
425 // ─── Minecart Tracks ──────────────────────────────────────
426
427 [[nodiscard]] const MinecartTrackLayout& minecart_track_layout() const {
429 }
430
431 // ─── Dungeon Stream Allocation Layouts ────────────────────────────
432
439 [[nodiscard]] const DungeonStreamLayout* GetDungeonStreamLayout(
440 DungeonStreamType stream) const;
441
442 [[nodiscard]] bool HasDungeonStreamLayouts() const {
443 return !dungeon_stream_layouts_.empty();
444 }
445
446 // ─── Graphics Sheet Layout ────────────────────────────────
447
452 [[nodiscard]] const GraphicsSheetLayout& graphics_sheet_layout() const {
454 }
455
456 // ─── Protected Regions ──────────────────────────────────
457
458 [[nodiscard]] const std::vector<ProtectedRegion>& protected_regions() const {
459 return protected_regions_;
460 }
461
462 [[nodiscard]] const std::vector<SnesAddressRange>& editor_managed_regions()
463 const {
465 }
466
467 [[nodiscard]] const std::unordered_map<uint8_t, OwnedBank>& owned_banks()
468 const {
469 return owned_banks_;
470 }
471
472 // ─── Write Conflict Analysis ─────────────────────────────
473
481 [[nodiscard]] std::vector<WriteConflict> AnalyzeWriteRanges(
482 const std::vector<std::pair<uint32_t, uint32_t>>& ranges) const;
483
493 [[nodiscard]] std::vector<WriteConflict> AnalyzePcWriteRanges(
494 const std::vector<std::pair<uint32_t, uint32_t>>& pc_ranges) const;
495
496 // ─── Project Registry ────────────────────────────────────
497
504 absl::Status LoadProjectRegistry(const std::string& code_folder);
505
506 [[nodiscard]] const ProjectRegistry& project_registry() const {
507 return project_registry_;
508 }
509
510 [[nodiscard]] bool HasProjectRegistry() const {
511 return !project_registry_.dungeons.empty() ||
514 }
515
516 // ─── Oracle Progression (SRAM) ─────────────────────────────
517
518 // Updates story event completion coloring based on progression state parsed
519 // from an emulator SRAM file (.srm).
521
522 // Clears any loaded progression state and resets story graph status to
523 // default (no progress).
525
526 [[nodiscard]] std::optional<OracleProgressionState> oracle_progression_state()
527 const {
529 }
530
531 // ─── Build Pipeline ───────────────────────────────────────
532
533 [[nodiscard]] const BuildPipeline& build_pipeline() const {
534 return build_pipeline_;
535 }
536
537 // ─── Metadata ─────────────────────────────────────────────
538
539 [[nodiscard]] const std::string& hack_name() const { return hack_name_; }
540 [[nodiscard]] int manifest_version() const { return manifest_version_; }
541 [[nodiscard]] int total_hooks() const { return total_hooks_; }
542
543 private:
544 void Reset();
545 [[nodiscard]] const ProtectedRegion* FindProtectedRegion(
546 uint32_t address) const;
547
548 bool loaded_ = false;
550 std::string hack_name_;
552
553 // Protected regions (vanilla bank hooks) — sorted by start address
554 std::vector<ProtectedRegion> protected_regions_;
555
556 // Exact manifest-v3 regions that remain yaze-owned inside otherwise owned
557 // banks. Sorted, disjoint, and stored as canonical LoROM addresses.
558 std::vector<SnesAddressRange> editor_managed_regions_;
559
560 // Bank ownership lookup
561 std::unordered_map<uint8_t, OwnedBank> owned_banks_;
562
563 // Room tag lookup by tag ID
564 std::unordered_map<uint8_t, RoomTagEntry> room_tag_map_;
565 std::vector<RoomTagEntry> room_tags_;
566
567 // Feature flags by name
568 std::unordered_map<std::string, FeatureFlag> feature_flag_map_;
569 std::vector<FeatureFlag> feature_flags_;
570
571 // SRAM variable lookup by address
572 std::unordered_map<uint32_t, SramVariable> sram_map_;
573 std::vector<SramVariable> sram_variables_;
574
575 // Message layout
577
578 // Optional canonical source contract for the minecart track table.
580
581 // Explicit dungeon stream layouts, indexed by stream kind.
582 std::unordered_map<DungeonStreamType, DungeonStreamLayout>
584
585 // Optional graphics-sheet free space and reserved sheets.
587
588 // Build pipeline
590
591 // Project registry (loaded from code_folder JSON files)
593
594 // Optional: live progression state derived from SRAM/.srm. This is used to
595 // color story event nodes and can be updated at runtime by editor panels.
596 std::optional<OracleProgressionState> oracle_progression_state_;
597};
598
599} // namespace yaze::core
600
601#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.
const MinecartTrackLayout & minecart_track_layout() const
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_
const GraphicsSheetLayout & graphics_sheet_layout() const
Graphics-sheet free space and reserved sheets. Empty when the optional graphics_sheet_regions section...
std::optional< AddressOwnership > GetBankOwnership(uint8_t bank) const
Get the bank ownership for a given bank number.
std::optional< OracleProgressionState > oracle_progression_state_
GraphicsSheetLayout graphics_sheet_layout_
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
MinecartTrackLayout minecart_track_layout_
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.
Graphics-sheet storage rules declared by the hack (graphics_sheet_regions).
std::vector< uint16_t > reserved_sheets
std::vector< SnesAddressRange > allocation_regions
Message range information for the expanded message system.
std::optional< Source > source
bool operator==(const Source &) const =default
Canonical source metadata for the ASM-owned minecart track table.
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