10#include "absl/strings/str_format.h"
11#include "absl/strings/str_split.h"
12#include "absl/strings/strip.h"
42 return "overworld_map";
58 if (type_str ==
"sprite")
60 if (type_str ==
"room")
62 if (type_str ==
"entrance")
64 if (type_str ==
"item")
66 if (type_str ==
"overlord")
68 if (type_str ==
"overworld_map")
70 if (type_str ==
"music")
72 if (type_str ==
"graphics")
74 if (type_str ==
"room_effect")
76 if (type_str ==
"room_tag")
78 if (type_str ==
"tile_type")
88 auto lookup = [&](
const std::string& key) -> std::string {
89 auto it = labels.find(key);
90 if (it != labels.end() && !it->second.empty()) {
97 if (std::string decimal = lookup(std::to_string(
id)); !decimal.empty()) {
102 const std::string hex_upper = absl::StrFormat(
"%X",
id);
103 const std::string hex_lower = absl::StrFormat(
"%x",
id);
104 const std::array<std::string, 8> keys = {
105 absl::StrFormat(
"0x%s", hex_lower), absl::StrFormat(
"0x%s", hex_upper),
106 absl::StrFormat(
"0X%s", hex_upper), absl::StrFormat(
"$%s", hex_upper),
107 absl::StrFormat(
"0x%02X",
id), absl::StrFormat(
"0x%03X",
id),
108 absl::StrFormat(
"0x%04X",
id), absl::StrFormat(
"$%02X",
id),
111 for (
const auto& key : keys) {
112 if (std::string label = lookup(key); !label.empty()) {
122 if (project_labels) {
123 const auto it = project_labels->find(
"item_receipt");
124 if (it != project_labels->end()) {
142 for (
const auto& room : dungeon.rooms) {
143 if (room.id ==
id && !room.name.empty()) {
177 if (std::string override_label = LookupProjectLabel(it->second,
id);
178 !override_label.empty()) {
179 return override_label;
183 if (std::string registry_label =
185 !registry_label.empty()) {
186 return registry_label;
196 if (std::string project_label = LookupProjectLabel(type_it->second,
id);
197 !project_label.empty()) {
198 return project_label;
207 if (!manifest_label.empty()) {
208 return manifest_label;
222 if (!hmagic.empty()) {
255 const std::string& label) {
260 (*project_labels_)[type_str][std::to_string(
id)] = label;
270 type_it->second.erase(std::to_string(
id));
283 return !LookupProjectLabel(type_it->second,
id).empty();
291 if (
id >= 0 &&
static_cast<size_t>(
id) < names.size()) {
294 return absl::StrFormat(
"Sprite %02X",
id);
298 if (
id >= 0 &&
static_cast<size_t>(
id) < names.size()) {
301 return absl::StrFormat(
"Room %03X",
id);
305 if (
id >= 0 &&
static_cast<size_t>(
id) < names.size()) {
308 return absl::StrFormat(
"Entrance %02X",
id);
312 if (
id >= 0 &&
static_cast<size_t>(
id) < names.size()) {
315 return absl::StrFormat(
"Item %02X",
id);
319 if (
id >= 0 &&
static_cast<size_t>(
id) < names.size()) {
322 return absl::StrFormat(
"Overlord %02X",
id);
326 if (
id >= 0 &&
static_cast<size_t>(
id) < names.size()) {
329 return absl::StrFormat(
"Map %02X",
id);
333 if (
id >= 0 &&
static_cast<size_t>(
id) < names.size()) {
336 return absl::StrFormat(
"Music %02X",
id);
340 if (
id >= 0 &&
static_cast<size_t>(
id) < names.size()) {
343 return absl::StrFormat(
"GFX %02X",
id);
347 if (
id >= 0 &&
static_cast<size_t>(
id) < names.size()) {
350 return absl::StrFormat(
"Effect %02X",
id);
354 if (
id >= 0 &&
static_cast<size_t>(
id) < names.size()) {
357 return absl::StrFormat(
"Tag %02X",
id);
361 if (
id >= 0 &&
static_cast<size_t>(
id) < names.size()) {
364 return absl::StrFormat(
"Tile %02X",
id);
367 return absl::StrFormat(
"Unknown %02X",
id);
436 const std::string& content) {
438 return absl::FailedPreconditionError(
439 "Project labels not initialized. Open a project first.");
442 std::istringstream stream(content);
444 std::string current_section;
448 while (std::getline(stream, line)) {
452 std::string trimmed = std::string(absl::StripAsciiWhitespace(line));
455 if (trimmed.empty() || trimmed.substr(0, 2) ==
"//") {
460 if (trimmed.front() ==
'[' && trimmed.back() ==
']') {
461 current_section = trimmed.substr(1, trimmed.length() - 2);
467 if (!current_section.empty()) {
472 return absl::OkStatus();
476 const std::string& section,
483 std::string resource_type;
484 bool has_hex_prefix =
false;
486 if (section ==
"Sprites Names") {
487 resource_type =
"sprite";
488 has_hex_prefix =
true;
489 }
else if (section ==
"Rooms Names") {
490 resource_type =
"room";
491 has_hex_prefix =
false;
492 }
else if (section ==
"Chests Items") {
493 resource_type =
"item_receipt";
494 has_hex_prefix =
true;
495 }
else if (section ==
"Tags Names") {
496 resource_type =
"room_tag";
497 has_hex_prefix =
false;
506 if (has_hex_prefix) {
508 size_t space_pos = line.find(
' ');
509 if (space_pos == std::string::npos || space_pos < 2) {
514 std::string hex_str = line.substr(0, space_pos);
515 label = line.substr(space_pos + 1);
519 int id = std::stoi(hex_str,
nullptr, 16);
520 id_str = std::to_string(
id);
526 id_str = std::to_string(line_index);
532 label = std::string(absl::StripAsciiWhitespace(label));
535 if (!label.empty()) {
536 (*project_labels_)[resource_type][id_str] = label;
543 std::ostringstream output;
545 output <<
"//Do not use brackets [] in naming\n";
548 output <<
"[Sprites Names]\n";
549 for (
int i = 0; i < 256; ++i) {
551 output << absl::StrFormat(
"%02X %s\n", i, label);
555 output <<
"\n[Rooms Names]\n";
556 for (
int i = 0; i < 297; ++i) {
558 output << label <<
"\n";
562 output <<
"\n[Chests Items]\n";
563 for (
int i = 0; i <= 0xFF; ++i) {
564 const auto id =
static_cast<uint8_t
>(i);
569 output << absl::StrFormat(
"%02X %s\n", i,
574 output <<
"\n[Tags Names]\n";
576 for (
int i = 0; i < tag_count; ++i) {
578 output << label <<
"\n";
589 const std::string& csv_content) {
596 std::istringstream stream(csv_content);
599 int imported_count = 0;
601 while (std::getline(stream, line)) {
605 std::string trimmed = std::string(absl::StripAsciiWhitespace(line));
608 if (trimmed.empty() || line_number == 1) {
613 std::vector<std::string> fields = absl::StrSplit(trimmed,
',');
614 if (fields.size() < 2) {
618 std::string
name = std::string(absl::StripAsciiWhitespace(fields[0]));
619 std::string id_str = std::string(absl::StripAsciiWhitespace(fields[1]));
623 if (id_str.empty()) {
628 if (id_str[0] ==
'$') {
629 id_str = id_str.substr(1);
632 if (id_str.size() >= 2 && id_str[0] ==
'0' &&
633 (id_str[1] ==
'x' || id_str[1] ==
'X')) {
634 id_str = id_str.substr(2);
638 sprite_id = std::stoi(id_str,
nullptr, 16);
643 if (sprite_id < 0 || sprite_id > 255) {
648 (*project_labels_)[
"sprite"][std::to_string(sprite_id)] =
name;
652 if (imported_count == 0) {
653 return absl::InvalidArgumentError(
654 "No valid sprite entries found in registry CSV");
657 return absl::OkStatus();
662 if (
const auto label = LookupProjectReceiptLabel(
id, project_labels);
667 if (
id < names.size())
669 return absl::StrFormat(
"Unknown item %02X",
id);
674 if (!LookupProjectReceiptLabel(
id, project_labels).empty())
Loads and queries the hack manifest JSON for yaze-ASM integration.
const ProjectRegistry & project_registry() const
bool HasProjectRegistry() const
std::string GetRoomTagLabel(uint8_t tag_id) const
Get the human-readable label for a room tag ID.
bool loaded() const
Check if the manifest has been loaded.
Unified interface for accessing resource labels with project overrides.
std::string ExportToZScreamFormat() const
Export project labels to ZScream DefaultNames.txt format.
void SetProjectLabel(ResourceType type, int id, const std::string &label)
Set a project-specific label override.
bool HasProjectLabel(ResourceType type, int id) const
Check if a project-specific label exists.
void ClearAllProjectLabels()
Clear all project labels.
int GetResourceCount(ResourceType type) const
Get the count of resources for a given type.
std::unordered_map< std::string, std::string > LabelMap
const core::HackManifest * hack_manifest_
ProjectLabels * project_labels_
std::string GetDefaultLabel(ResourceType type, int id) const
Get the label without project overrides (steps 4-5 above)
ResolvedLabel ResolveLabel(ResourceType type, int id) const
Get the label and the default name it replaces.
std::string GetLabel(ResourceType type, int id) const
Get a label for a resource by type and ID.
bool ParseZScreamLine(const std::string &line, const std::string §ion, int &line_index)
std::unordered_map< std::string, LabelMap > ProjectLabels
absl::Status ImportFromZScreamFormat(const std::string &content)
Import labels from ZScream DefaultNames.txt format.
std::string GetVanillaLabel(ResourceType type, int id) const
Get the vanilla (default) label for a resource.
const LabelMap * GetProjectLabelsForType(ResourceType type) const
Get all project labels for a given type.
std::string GetHMagicLabel(ResourceType type, int id) const
Get the Hyrule Magic label for a resource (sprites only)
void ClearProjectLabel(ResourceType type, int id)
Clear a project-specific label (revert to default)
absl::Status ImportOracleSpriteRegistry(const std::string &csv_content)
Import sprite labels from Oracle of Secrets registry.csv format.
std::string LookupProjectRegistryRoomLabel(const core::HackManifest *manifest, int id)
std::string LookupProjectReceiptLabel(uint8_t id, const ResourceLabelProvider::ProjectLabels *project_labels)
std::string LookupProjectLabel(const ResourceLabelProvider::LabelMap &labels, int id)
Zelda 3 specific classes and functions.
ResourceType
Enumeration of all supported resource types for labeling.
const char * GetItemReceiptLabelSource(uint8_t id, const ResourceLabelProvider::ProjectLabels *project_labels)
const size_t kSpriteNameCount
const char *const kSpriteNames[]
std::string GetItemReceiptLabel(uint8_t id, const ResourceLabelProvider::ProjectLabels *project_labels)
std::string ResourceTypeToString(ResourceType type)
Convert ResourceType enum to string key for storage.
ResourceType StringToResourceType(const std::string &type_str)
Convert string key to ResourceType enum.
ResourceLabelProvider & GetResourceLabels()
Get the global ResourceLabelProvider instance.
std::vector< DungeonEntry > dungeons
A label plus the name it replaces.
std::string Display() const
static const std::vector< std::string > & GetRoomNames()
static const std::vector< std::string > & GetItemNames()
static const std::vector< std::string > & GetEntranceNames()
static const std::vector< std::string > & GetGraphicsSheetNames()
static const std::vector< std::string > & GetMusicTrackNames()
static const std::vector< std::string > & GetItemReceiptNames()
static const std::vector< std::string > & GetTileTypeNames()
static const std::vector< std::string > & GetOverlordNames()
static const std::vector< std::string > & GetSpriteNames()
static const std::vector< std::string > & GetOverworldMapNames()
static const std::vector< std::string > & GetRoomEffectNames()
static const std::vector< std::string > & GetRoomTagNames()