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 uint32_t hook_address; // $0ED436
96 uint32_t data_start; // $2F8000
97 uint32_t data_end; // $2FFFFF
98 uint16_t first_expanded_id; // $18D
99 uint16_t last_expanded_id; // $1D1
101 int vanilla_count; // 397
102};
103
108 std::string dev_rom;
109 std::string patched_rom;
110 std::string assembler;
111 std::string entry_point;
112 std::string build_script;
113};
114
118enum class DungeonStreamType : uint8_t {
119 kObjects,
120 kSprites,
121 kPotItems,
122};
123
127enum class DungeonPointerEncoding : uint8_t {
128 kLong24,
129 kBank16,
130};
131
135enum class DungeonWriteStrategy : uint8_t {
138};
139
144 uint32_t start = 0;
145 uint32_t end = 0;
146};
147
165
170 uint32_t address;
172 std::string module; // From protected region, if applicable
173};
174
175// ─── Project Registry (Dungeon + Overworld data) ─────────────────────────
176
181 int id;
182 std::string name;
183 std::string floor; // "F1", "B1", etc. Optional project-map label.
185 bool has_grid_position = false;
186 std::string type; // "entrance", "boss", "mini_boss", "connector", "normal"
188 uint8_t tag1, tag2;
189};
190
196 std::string label;
197 std::string direction; // For doors: "north"/"south"/"east"/"west"
198};
199
204 std::string id; // "D4"
205 std::string name; // "Zora Temple"
206 std::string vanilla_name; // "Thieves' Town"
207 std::vector<DungeonRoom> rooms;
208 std::vector<DungeonConnection> stairs;
209 std::vector<DungeonConnection> holewarps;
210 std::vector<DungeonConnection> doors;
211};
212
218 std::string name;
219 std::string world; // "LW", "DW", "SW"
221};
222
230 std::vector<DungeonEntry> dungeons;
231 std::vector<OverworldArea> overworld_areas;
233
234 // Universal resource labels: type -> {id_str -> label}
235 //
236 // Notes:
237 // - Keys are normalized to decimal strings for project::YazeProject::resource_labels.
238 // - Input JSON may use either decimal ("57") or hex ("0x39") IDs.
239 //
240 // Types: "room", "sprite", "item", "entrance", "overworld_map", "music".
241 // Oracle `dungeons.json` room names are mirrored into "room" labels so the
242 // opened project file can serialize the current registry names.
243 std::unordered_map<std::string, std::unordered_map<std::string, std::string>>
245
246 // Backward-compat accessor for room labels only
247 const std::unordered_map<std::string, std::string>& room_labels() const {
248 static const std::unordered_map<std::string, std::string> empty;
249 auto it = all_resource_labels.find("room");
250 return it != all_resource_labels.end() ? it->second : empty;
251 }
252};
253
278 public:
279 HackManifest() = default;
280
284 absl::Status LoadFromFile(const std::string& filepath);
285
289 absl::Status LoadFromString(const std::string& json_content);
290
294 [[nodiscard]] bool loaded() const { return loaded_; }
295
302 void Clear() { Reset(); }
303
304 // ─── Address Classification ───────────────────────────────
305
315 [[nodiscard]] AddressOwnership ClassifyAddress(uint32_t address) const;
316
323 [[nodiscard]] bool IsWriteOverwritten(uint32_t address) const;
324
328 [[nodiscard]] bool IsProtected(uint32_t address) const;
329
337 [[nodiscard]] bool IsEditorManaged(uint32_t address) const;
338
342 [[nodiscard]] std::optional<AddressOwnership> GetBankOwnership(
343 uint8_t bank) const;
344
345 // ─── Room Tags ────────────────────────────────────────────
346
350 [[nodiscard]] std::string GetRoomTagLabel(uint8_t tag_id) const;
351
355 [[nodiscard]] std::optional<RoomTagEntry> GetRoomTag(uint8_t tag_id) const;
356
360 [[nodiscard]] const std::vector<RoomTagEntry>& room_tags() const {
361 return room_tags_;
362 }
363
364 // ─── Feature Flags ────────────────────────────────────────
365
366 [[nodiscard]] bool IsFeatureEnabled(const std::string& flag_name) const;
367
368 [[nodiscard]] const std::vector<FeatureFlag>& feature_flags() const {
369 return feature_flags_;
370 }
371
372 // ─── SRAM ─────────────────────────────────────────────────
373
374 [[nodiscard]] std::string GetSramVariableName(uint32_t address) const;
375
376 [[nodiscard]] const std::vector<SramVariable>& sram_variables() const {
377 return sram_variables_;
378 }
379
380 // ─── Messages ─────────────────────────────────────────────
381
382 [[nodiscard]] const MessageLayout& message_layout() const {
383 return message_layout_;
384 }
385
386 [[nodiscard]] bool IsExpandedMessage(uint16_t message_id) const;
387
388 // ─── Dungeon Stream Allocation Layouts ────────────────────────────
389
396 [[nodiscard]] const DungeonStreamLayout* GetDungeonStreamLayout(
397 DungeonStreamType stream) const;
398
399 [[nodiscard]] bool HasDungeonStreamLayouts() const {
400 return !dungeon_stream_layouts_.empty();
401 }
402
403 // ─── Protected Regions ──────────────────────────────────
404
405 [[nodiscard]] const std::vector<ProtectedRegion>& protected_regions() const {
406 return protected_regions_;
407 }
408
409 [[nodiscard]] const std::vector<SnesAddressRange>& editor_managed_regions()
410 const {
412 }
413
414 [[nodiscard]] const std::unordered_map<uint8_t, OwnedBank>& owned_banks()
415 const {
416 return owned_banks_;
417 }
418
419 // ─── Write Conflict Analysis ─────────────────────────────
420
428 [[nodiscard]] std::vector<WriteConflict> AnalyzeWriteRanges(
429 const std::vector<std::pair<uint32_t, uint32_t>>& ranges) const;
430
440 [[nodiscard]] std::vector<WriteConflict> AnalyzePcWriteRanges(
441 const std::vector<std::pair<uint32_t, uint32_t>>& pc_ranges) const;
442
443 // ─── Project Registry ────────────────────────────────────
444
451 absl::Status LoadProjectRegistry(const std::string& code_folder);
452
453 [[nodiscard]] const ProjectRegistry& project_registry() const {
454 return project_registry_;
455 }
456
457 [[nodiscard]] bool HasProjectRegistry() const {
458 return !project_registry_.dungeons.empty() ||
461 }
462
463 // ─── Oracle Progression (SRAM) ─────────────────────────────
464
465 // Updates story event completion coloring based on progression state parsed
466 // from an emulator SRAM file (.srm).
468
469 // Clears any loaded progression state and resets story graph status to
470 // default (no progress).
472
473 [[nodiscard]] std::optional<OracleProgressionState> oracle_progression_state()
474 const {
476 }
477
478 // ─── Build Pipeline ───────────────────────────────────────
479
480 [[nodiscard]] const BuildPipeline& build_pipeline() const {
481 return build_pipeline_;
482 }
483
484 // ─── Metadata ─────────────────────────────────────────────
485
486 [[nodiscard]] const std::string& hack_name() const { return hack_name_; }
487 [[nodiscard]] int manifest_version() const { return manifest_version_; }
488 [[nodiscard]] int total_hooks() const { return total_hooks_; }
489
490 private:
491 void Reset();
492 [[nodiscard]] const ProtectedRegion* FindProtectedRegion(
493 uint32_t address) const;
494
495 bool loaded_ = false;
497 std::string hack_name_;
499
500 // Protected regions (vanilla bank hooks) — sorted by start address
501 std::vector<ProtectedRegion> protected_regions_;
502
503 // Exact manifest-v3 regions that remain yaze-owned inside otherwise owned
504 // banks. Sorted, disjoint, and stored as canonical LoROM addresses.
505 std::vector<SnesAddressRange> editor_managed_regions_;
506
507 // Bank ownership lookup
508 std::unordered_map<uint8_t, OwnedBank> owned_banks_;
509
510 // Room tag lookup by tag ID
511 std::unordered_map<uint8_t, RoomTagEntry> room_tag_map_;
512 std::vector<RoomTagEntry> room_tags_;
513
514 // Feature flags by name
515 std::unordered_map<std::string, FeatureFlag> feature_flag_map_;
516 std::vector<FeatureFlag> feature_flags_;
517
518 // SRAM variable lookup by address
519 std::unordered_map<uint32_t, SramVariable> sram_map_;
520 std::vector<SramVariable> sram_variables_;
521
522 // Message layout
524
525 // Explicit dungeon stream layouts, indexed by stream kind.
526 std::unordered_map<DungeonStreamType, DungeonStreamLayout>
528
529 // Build pipeline
531
532 // Project registry (loaded from code_folder JSON files)
534
535 // Optional: live progression state derived from SRAM/.srm. This is used to
536 // color story event nodes and can be updated at runtime by editor panels.
537 std::optional<OracleProgressionState> oracle_progression_state_;
538};
539
540} // namespace yaze::core
541
542#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.
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