8#include "absl/strings/ascii.h"
9#include "absl/strings/str_format.h"
10#include "absl/strings/str_split.h"
34 uint8_t best_match = 0xFF;
35 const wchar_t target =
36 static_cast<wchar_t>(
static_cast<unsigned char>(value));
37 for (
const auto& [key, char_value] : CharEncoder) {
38 if (char_value != target) {
41 if (best_match == 0xFF || key < best_match) {
49 if (value <
DICTOFF || value == 0xFF) {
56 for (
const auto& text_element : TextCommands) {
57 if (text_element.ID == b) {
65 auto it = std::ranges::find_if(SpecialChars,
67 return text_element.
ID == value;
69 if (it != SpecialChars.end()) {
77 std::vector<TextElement> commands_and_chars = TextCommands;
78 commands_and_chars.insert(commands_and_chars.end(), SpecialChars.begin(),
80 for (
auto& text_element : commands_and_chars) {
81 match = text_element.MatchMe(str);
82 if (match.size() > 0) {
83 if (text_element.HasArgument) {
84 std::string arg = match[1].str().substr(1);
86 return ParsedElement(text_element, std::stoi(arg,
nullptr, 16));
87 }
catch (
const std::invalid_argument& e) {
88 util::logf(
"Error parsing argument for %s: %s",
89 text_element.GenericToken.c_str(), arg.c_str());
91 }
catch (
const std::out_of_range& e) {
93 text_element.GenericToken.c_str(), arg.c_str());
102 const auto dictionary_element =
105 match = dictionary_element.MatchMe(str);
106 if (match.size() > 0) {
109 std::string dict_arg = match[1].str().substr(1);
111 DICTOFF + std::stoi(dict_arg,
nullptr, 16));
112 }
catch (
const std::exception& e) {
113 util::logf(
"Error parsing dictionary token: %s", match[1].str().c_str());
121 if (CharEncoder.contains(value)) {
122 char c = CharEncoder.at(value);
123 std::string str =
"";
130 text_element != std::nullopt) {
131 return text_element->GenericToken;
136 special_element != std::nullopt) {
137 return special_element->GenericToken;
142 if (dictionary >= 0) {
144 static_cast<unsigned char>(dictionary));
151 std::vector<uint8_t> bytes;
152 std::string temp_string = std::move(str);
154 while (pos < temp_string.size()) {
156 if (temp_string[pos] ==
'[') {
157 int next = temp_string.find(
']', pos);
165 const auto dictionary_element =
168 if (!parsedElement.
Active) {
169 util::logf(
"Error parsing message: %s", temp_string);
171 }
else if (parsedElement.
Parent == dictionary_element) {
172 bytes.push_back(parsedElement.
Value);
174 bytes.push_back(parsedElement.
Parent.
ID);
177 bytes.push_back(parsedElement.
Value);
197 std::string temp_string(str);
199 bool warned_newline =
false;
201 while (pos < temp_string.size()) {
202 char current = temp_string[pos];
203 if (current ==
'\r' || current ==
'\n') {
204 if (!warned_newline) {
206 "Literal newlines are ignored; use [1], [2], [3], [V], or [K] "
207 "tokens for line breaks.");
208 warned_newline =
true;
214 if (current ==
'[') {
215 size_t close = temp_string.find(
']', pos);
216 if (close == std::string::npos) {
218 absl::StrFormat(
"Unclosed token starting at position %zu", pos));
222 std::string token = temp_string.substr(pos, close - pos + 1);
224 const auto dictionary_element =
227 if (!parsed_element.
Active) {
228 result.
errors.push_back(absl::StrFormat(
"Unknown token: %s", token));
235 result.
errors.push_back(absl::StrFormat(
"Unknown token: %s", token));
241 if (parsed_element.
Parent == dictionary_element) {
256 result.
errors.push_back(absl::StrFormat(
257 "Unsupported character '%c' at position %zu", current, pos));
262 result.
bytes.push_back(bb);
280 const std::string lowered = absl::AsciiStrToLower(std::string(value));
281 if (lowered ==
"vanilla") {
284 if (lowered ==
"expanded") {
287 return absl::InvalidArgumentError(
288 absl::StrFormat(
"Unknown message bank: %s", std::string(value)));
292 std::vector<DictionaryEntry> AllDictionaries;
294 std::vector<uint8_t> bytes;
295 std::stringstream stringBuilder;
301 int temppush_backress =
306 while (address < temppush_backress) {
307 uint8_t uint8_tDictionary = rom->
data()[address++];
308 bytes.push_back(uint8_tDictionary);
312 AllDictionaries.push_back(
DictionaryEntry{(uint8_t)i, stringBuilder.str()});
315 std::ranges::sort(AllDictionaries,
320 return AllDictionaries;
324 std::string str,
const std::vector<DictionaryEntry>& dictionary) {
325 std::string temp = std::move(str);
326 for (
const auto& entry : dictionary) {
327 if (entry.ContainedInString(temp)) {
328 temp = entry.ReplaceInstancesOfIn(temp);
335 uint8_t value,
const std::vector<DictionaryEntry>& dictionary) {
336 for (
const auto& entry : dictionary) {
337 if (entry.ID +
DICTOFF == value) {
345 const std::vector<uint8_t>& rom_data,
int* current_pos) {
346 if (current_pos ==
nullptr) {
347 return absl::InvalidArgumentError(
"current_pos is null");
349 if (*current_pos < 0 ||
350 static_cast<size_t>(*current_pos) >= rom_data.size()) {
351 return absl::OutOfRangeError(
"current_pos is out of range");
355 int pos = *current_pos;
356 uint8_t current_byte;
357 std::vector<uint8_t> temp_bytes_raw;
358 std::vector<uint8_t> temp_bytes_parsed;
359 std::string current_message_raw;
360 std::string current_message_parsed;
363 while (pos <
static_cast<int>(rom_data.size())) {
364 current_byte = rom_data[pos++];
367 message_data.
ID = message_data.
ID + 1;
369 message_data.
RawString = current_message_raw;
370 message_data.
Data = temp_bytes_raw;
374 temp_bytes_raw.clear();
375 temp_bytes_parsed.clear();
376 current_message_raw.clear();
377 current_message_parsed.clear();
381 }
else if (current_byte == 0xFF) {
382 return absl::InvalidArgumentError(
"message terminator not found");
385 temp_bytes_raw.push_back(current_byte);
389 if (text_element != std::nullopt) {
390 temp_bytes_parsed.push_back(current_byte);
391 if (text_element->HasArgument) {
392 if (pos >=
static_cast<int>(rom_data.size())) {
393 return absl::OutOfRangeError(
"message command argument out of range");
395 uint8_t arg_byte = rom_data[pos++];
396 temp_bytes_raw.push_back(arg_byte);
397 temp_bytes_parsed.push_back(arg_byte);
398 current_message_raw.append(text_element->GetParamToken(arg_byte));
399 current_message_parsed.append(text_element->GetParamToken(arg_byte));
401 current_message_raw.append(text_element->GetParamToken());
402 current_message_parsed.append(text_element->GetParamToken());
409 special_element != std::nullopt) {
410 current_message_raw.append(special_element->GetParamToken());
411 current_message_parsed.append(special_element->GetParamToken());
412 temp_bytes_parsed.push_back(current_byte);
418 if (dictionary >= 0) {
419 std::string token = absl::StrFormat(
421 current_message_raw.append(token);
422 current_message_parsed.append(token);
423 temp_bytes_parsed.push_back(current_byte);
428 if (CharEncoder.contains(current_byte)) {
429 std::string str =
"";
430 str.push_back(CharEncoder.at(current_byte));
431 current_message_raw.append(str);
432 current_message_parsed.append(str);
433 temp_bytes_parsed.push_back(current_byte);
438 return absl::InvalidArgumentError(
"message terminator not found");
442 std::vector<MessageData>& message_data,
443 const std::vector<DictionaryEntry>& dictionary_entries) {
444 std::vector<std::string> parsed_messages;
446 for (
auto& message : message_data) {
447 std::string parsed_message =
"";
449 for (
size_t pos = 0; pos < message.Data.size(); ++pos) {
450 uint8_t
byte = message.Data[pos];
454 if (text_element != std::nullopt) {
457 text_element->ID ==
kLine3) {
458 parsed_message.append(
"\n");
461 if (text_element->HasArgument && pos + 1 < message.Data.size()) {
462 uint8_t arg_byte = message.Data[pos + 1];
463 parsed_message.append(text_element->GetParamToken(arg_byte));
466 parsed_message.append(text_element->GetParamToken());
473 if (special_element != std::nullopt) {
474 parsed_message.append(special_element->GetParamToken());
481 for (
const auto& entry : dictionary_entries) {
482 if (entry.ID ==
byte -
DICTOFF) {
487 parsed_message.append(dic_entry.
Contents);
492 if (CharEncoder.contains(
byte)) {
493 parsed_message.push_back(CharEncoder.at(
byte));
496 parsed_messages.push_back(parsed_message);
499 return parsed_messages;
503 std::vector<MessageData> list_of_texts;
507 return list_of_texts;
509 if (max_pos > 0 && (pos < 0 || pos >= max_pos)) {
510 return list_of_texts;
513 std::vector<uint8_t> raw_message;
514 std::vector<uint8_t> parsed_message;
515 std::string current_raw_message;
516 std::string current_parsed_message;
518 bool did_bank_switch =
false;
519 uint8_t current_byte = 0;
520 while (current_byte != 0xFF) {
521 if (max_pos > 0 && (pos < 0 || pos >= max_pos))
523 current_byte = rom[pos++];
525 list_of_texts.push_back(
526 MessageData(message_id++, pos, current_raw_message, raw_message,
527 current_parsed_message, parsed_message));
529 parsed_message.clear();
530 current_raw_message.clear();
531 current_parsed_message.clear();
533 }
else if (current_byte == 0xFF) {
537 raw_message.push_back(current_byte);
540 if (text_element != std::nullopt) {
541 parsed_message.push_back(current_byte);
542 if (text_element->HasArgument) {
543 if (max_pos > 0 && (pos < 0 || pos >= max_pos))
545 current_byte = rom[pos++];
546 raw_message.push_back(current_byte);
547 parsed_message.push_back(current_byte);
550 current_raw_message.append(text_element->GetParamToken(current_byte));
551 current_parsed_message.append(text_element->GetParamToken(current_byte));
553 if (text_element->Token ==
kBankToken && !did_bank_switch) {
554 did_bank_switch =
true;
563 if (special_element != std::nullopt) {
564 current_raw_message.append(special_element->GetParamToken());
565 current_parsed_message.append(special_element->GetParamToken());
566 parsed_message.push_back(current_byte);
572 if (dictionary >= 0) {
573 current_raw_message.append(absl::StrFormat(
583 if (ptr_a < 0 || ptr_a + 1 >= max_pos || ptr_b < 0 ||
584 ptr_b + 1 >= max_pos) {
591 uint32_t address_end =
595 const uint32_t max_u =
static_cast<uint32_t
>(max_pos);
596 if (address >= max_u || address_end > max_u || address_end < address) {
601 for (uint32_t i = address; i < address_end; i++) {
602 if (max_pos > 0 && i >=
static_cast<uint32_t
>(max_pos))
604 parsed_message.push_back(rom[i]);
612 if (CharEncoder.contains(current_byte)) {
613 std::string str =
"";
614 str.push_back(CharEncoder.at(current_byte));
615 current_raw_message.append(str);
616 current_parsed_message.append(str);
617 parsed_message.push_back(current_byte);
621 return list_of_texts;
625 std::vector<std::string>& parsed_messages,
626 std::vector<MessageData>& expanded_messages,
627 std::vector<DictionaryEntry>& dictionary) {
628 static Rom expanded_message_rom;
629 if (!expanded_message_rom.
LoadFromFile(expanded_message_path).ok()) {
630 return absl::InternalError(
"Failed to load expanded message ROM");
633 auto parsed_expanded_messages =
636 for (
const auto& expanded_message : expanded_messages) {
637 parsed_messages.push_back(parsed_expanded_messages[expanded_message.ID]);
639 return absl::OkStatus();
643 const std::vector<MessageData>& messages) {
644 nlohmann::json j = nlohmann::json::array();
645 for (
const auto& msg : messages) {
646 j.push_back({{
"id", msg.ID},
647 {
"address", msg.Address},
648 {
"raw_string", msg.RawString},
649 {
"parsed_string", msg.ContentsParsed}});
655 const std::vector<MessageData>& messages) {
658 std::ofstream file(path);
659 if (!file.is_open()) {
660 return absl::InternalError(
661 absl::StrFormat(
"Failed to open file for writing: %s", path));
664 return absl::OkStatus();
665 }
catch (
const std::exception& e) {
666 return absl::InternalError(
667 absl::StrFormat(
"JSON export failed: %s", e.what()));
672 const std::vector<MessageData>& vanilla,
673 const std::vector<MessageData>& expanded) {
675 j[
"format"] =
"yaze-message-bundle";
677 j[
"counts"] = {{
"vanilla", vanilla.size()}, {
"expanded", expanded.size()}};
678 j[
"messages"] = nlohmann::json::array();
680 auto append_messages = [&j](
const std::vector<MessageData>& messages,
682 for (
const auto& msg : messages) {
683 nlohmann::json entry;
684 entry[
"id"] = msg.ID;
686 entry[
"address"] = msg.Address;
687 entry[
"raw"] = msg.RawString;
688 entry[
"parsed"] = msg.ContentsParsed;
690 !msg.RawString.empty() ? msg.RawString : msg.ContentsParsed;
691 entry[
"length"] = msg.Data.size();
692 const std::string validation_text =
693 !msg.RawString.empty() ? msg.RawString : msg.ContentsParsed;
695 if (!warnings.empty()) {
696 entry[
"line_width_warnings"] = warnings;
698 j[
"messages"].push_back(entry);
709 const std::string& path,
const std::vector<MessageData>& vanilla,
710 const std::vector<MessageData>& expanded) {
713 std::ofstream file(path);
714 if (!file.is_open()) {
715 return absl::InternalError(
716 absl::StrFormat(
"Failed to open file for writing: %s", path));
719 return absl::OkStatus();
720 }
catch (
const std::exception& e) {
721 return absl::InternalError(
722 absl::StrFormat(
"Message bundle export failed: %s", e.what()));
728 const nlohmann::json& entry,
MessageBank default_bank) {
729 if (!entry.is_object()) {
730 return absl::InvalidArgumentError(
"Message entry must be an object");
734 result.
id = entry.value(
"id", -1);
736 return absl::InvalidArgumentError(
"Message entry missing valid id");
739 if (entry.contains(
"bank")) {
740 if (!entry[
"bank"].is_string()) {
741 return absl::InvalidArgumentError(
"Message entry bank must be string");
745 return bank_or.status();
747 result.
bank = bank_or.value();
749 result.
bank = default_bank;
752 if (entry.contains(
"raw") && entry[
"raw"].is_string()) {
753 result.
raw = entry[
"raw"].get<std::string>();
754 }
else if (entry.contains(
"raw_string") && entry[
"raw_string"].is_string()) {
755 result.
raw = entry[
"raw_string"].get<std::string>();
758 if (entry.contains(
"parsed") && entry[
"parsed"].is_string()) {
759 result.
parsed = entry[
"parsed"].get<std::string>();
760 }
else if (entry.contains(
"parsed_string") &&
761 entry[
"parsed_string"].is_string()) {
762 result.
parsed = entry[
"parsed_string"].get<std::string>();
765 if (entry.contains(
"text") && entry[
"text"].is_string()) {
766 result.
text = entry[
"text"].get<std::string>();
769 if (result.
text.empty()) {
770 if (!result.
raw.empty()) {
772 }
else if (!result.
parsed.empty()) {
777 if (result.
text.empty()) {
778 return absl::InvalidArgumentError(
779 absl::StrFormat(
"Message entry %d missing text content", result.
id));
787 const nlohmann::json& json) {
788 std::vector<MessageBundleEntry> entries;
790 if (json.is_array()) {
791 for (
const auto& entry : json) {
793 if (!parsed_or.ok()) {
794 return parsed_or.status();
796 entries.push_back(parsed_or.value());
801 if (!json.is_object()) {
802 return absl::InvalidArgumentError(
"Message bundle JSON must be object");
805 if (json.contains(
"version") && json[
"version"].is_number_integer()) {
806 int version = json[
"version"].get<
int>();
808 return absl::InvalidArgumentError(
809 absl::StrFormat(
"Unsupported message bundle version: %d", version));
813 if (!json.contains(
"messages") || !json[
"messages"].is_array()) {
814 return absl::InvalidArgumentError(
"Message bundle missing messages array");
817 for (
const auto& entry : json[
"messages"]) {
819 if (!parsed_or.ok()) {
820 return parsed_or.status();
822 entries.push_back(parsed_or.value());
829 const std::string& path) {
830 std::ifstream file(path);
831 if (!file.is_open()) {
832 return absl::NotFoundError(
833 absl::StrFormat(
"Cannot open message bundle: %s", path));
839 }
catch (
const std::exception& e) {
840 return absl::InvalidArgumentError(
841 absl::StrFormat(
"Failed to parse JSON: %s", e.what()));
852 std::vector<std::string> warnings;
857 int visible_chars = 0;
858 bool all_spaces_this_line =
true;
861 while (pos < message.size()) {
862 if (message[pos] ==
'[') {
864 size_t close = message.find(
']', pos);
865 if (close == std::string::npos)
868 std::string token = message.substr(pos, close - pos + 1);
873 if (token ==
"[1]" || token ==
"[2]" || token ==
"[3]" ||
874 token ==
"[V]" || token ==
"[K]") {
877 if (visible_chars >
kMaxLineWidth && !all_spaces_this_line) {
879 absl::StrFormat(
"Line %d: %d visible characters (max %d)",
884 all_spaces_this_line =
true;
895 if (message[pos] !=
' ')
896 all_spaces_this_line =
false;
902 if (visible_chars >
kMaxLineWidth && !all_spaces_this_line) {
904 absl::StrFormat(
"Line %d: %d visible characters (max %d)", line_num,
916 const std::string& line) {
919 if (line.size() < 6 || line[0] !=
'*' || line[1] !=
'*' || line[2] !=
' ') {
924 size_t sep = line.find(
" - ", 3);
925 if (sep == std::string::npos) {
930 std::string hex_id = line.substr(3, sep - 3);
933 message_id = std::stoi(hex_id,
nullptr, 16);
934 }
catch (
const std::exception&) {
939 std::string label = line.substr(sep + 3);
941 return std::make_pair(message_id, label);
945 const std::string& content) {
946 std::vector<std::pair<int, std::string>> messages;
947 std::istringstream stream(content);
951 std::string current_body;
953 while (std::getline(stream, line)) {
956 if (header.has_value()) {
958 if (current_id >= 0) {
960 while (!current_body.empty() && current_body.back() ==
'\n') {
961 current_body.pop_back();
963 messages.push_back({current_id, current_body});
966 current_id = header->first;
967 current_body.clear();
972 if (!line.empty() && line[0] ==
'*' &&
973 (line.size() < 2 || line[1] !=
'*')) {
978 if (current_id >= 0) {
979 if (!current_body.empty()) {
980 current_body +=
"\n";
982 current_body += line;
987 if (current_id >= 0) {
988 while (!current_body.empty() && current_body.back() ==
'\n') {
989 current_body.pop_back();
991 messages.push_back({current_id, current_body});
998 const std::vector<std::pair<int, std::string>>& messages,
999 const std::vector<std::string>& labels) {
1001 output +=
"* Oracle of Secrets English Dialogue\n";
1003 for (
size_t i = 0; i < messages.size(); ++i) {
1004 const auto& [msg_id, body] = messages[i];
1005 std::string label = (i < labels.size())
1007 : absl::StrFormat(
"Message %02X", msg_id);
1009 output += absl::StrFormat(
"** %02X - %s\n", msg_id, label);
1027 const std::vector<std::string>& messages) {
1028 if (rom ==
nullptr || !rom->
is_loaded()) {
1029 return absl::InvalidArgumentError(
"ROM not loaded");
1031 if (start < 0 || end < start) {
1032 return absl::InvalidArgumentError(
"Invalid expanded message region");
1035 const int capacity = end - start + 1;
1036 if (capacity <= 0) {
1037 return absl::InvalidArgumentError(
1038 "Expanded message region has no capacity");
1041 const auto& data = rom->
vector();
1042 if (end >=
static_cast<int>(data.size())) {
1043 return absl::OutOfRangeError(
"Expanded message region out of ROM range");
1048 std::vector<uint8_t> blob;
1049 blob.reserve(
static_cast<size_t>(capacity));
1052 for (
size_t i = 0; i < messages.size(); ++i) {
1054 const int needed =
static_cast<int>(bytes.size()) + 1;
1057 if (used + needed + 1 > capacity) {
1058 return absl::ResourceExhaustedError(absl::StrFormat(
1059 "Expanded message data exceeds bank boundary "
1060 "(at message %d, used=%d, needed=%d, capacity=%d, end=0x%06X)",
1061 static_cast<int>(i), used, needed, capacity, end));
1064 blob.insert(blob.end(), bytes.begin(), bytes.end());
1069 if (used + 1 > capacity) {
1070 return absl::ResourceExhaustedError(
1071 "No space for end-of-region marker (0xFF)");
1073 blob.push_back(0xFF);
1078 const uint32_t fence_start =
static_cast<uint32_t
>(start);
1079 const uint32_t fence_end =
1080 static_cast<uint32_t
>(
static_cast<uint64_t
>(end) + 1ULL);
1088 const std::vector<std::string>& messages) {
1090 int capacity = end - start + 1;
1092 for (
size_t i = 0; i < messages.size(); ++i) {
1096 int needed =
static_cast<int>(bytes.size()) + 1;
1097 if (i == messages.size() - 1) {
1101 if (pos + needed - start > capacity) {
1102 return absl::ResourceExhaustedError(
1103 absl::StrFormat(
"Expanded message data exceeds bank boundary "
1104 "(at message %d, pos 0x%06X, end 0x%06X)",
1105 static_cast<int>(i), pos, end));
1109 for (uint8_t
byte : bytes) {
1117 if (pos - start >= capacity) {
1118 return absl::ResourceExhaustedError(
1119 "No space for end-of-region marker (0xFF)");
1123 return absl::OkStatus();
1127 const std::vector<MessageData>& messages) {
1128 if (rom ==
nullptr || !rom->
is_loaded()) {
1129 return absl::InvalidArgumentError(
"ROM not loaded");
1133 bool in_second_bank =
false;
1135 for (
const auto& message : messages) {
1136 for (uint8_t value : message.Data) {
1141 return absl::ResourceExhaustedError(absl::StrFormat(
1142 "Text data exceeds first bank (pos 0x%06X)", pos));
1145 in_second_bank =
true;
1155 return absl::ResourceExhaustedError(
1156 absl::StrFormat(
"Text data exceeds first bank (pos 0x%06X)", pos));
1160 return absl::ResourceExhaustedError(
1161 absl::StrFormat(
"Text data exceeds second bank (pos 0x%06X)", pos));
1165 return absl::OkStatus();
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
absl::Status LoadFromFile(const std::string &filename, const LoadOptions &options=LoadOptions::Defaults())
absl::Status WriteByte(int addr, uint8_t value)
const auto & vector() const
absl::Status WriteVector(int addr, std::vector< uint8_t > data)
static RomSettings & Get()
uint32_t GetAddressOr(const std::string &key, uint32_t default_value) const
absl::Status Allow(uint32_t start, uint32_t end, std::string_view label)
constexpr char kExpandedMessageEnd[]
constexpr char kExpandedMessageStart[]
absl::StatusOr< MessageBundleEntry > ParseMessageBundleEntry(const nlohmann::json &entry, MessageBank default_bank)
uint8_t FindMatchingCharacter(char value)
const std::string kBankToken
nlohmann::json SerializeMessagesToJson(const std::vector< MessageData > &messages)
absl::StatusOr< MessageBank > MessageBankFromString(std::string_view value)
DictionaryEntry FindRealDictionaryEntry(uint8_t value, const std::vector< DictionaryEntry > &dictionary)
constexpr int kMaxLineWidth
int GetExpandedTextDataStart()
constexpr int kMessageBundleVersion
const std::string DICTIONARYTOKEN
constexpr uint8_t kScrollVertical
std::string ParseTextDataByte(uint8_t value)
absl::Status WriteAllTextData(Rom *rom, const std::vector< MessageData > &messages)
absl::Status LoadExpandedMessages(std::string &expanded_message_path, std::vector< std::string > &parsed_messages, std::vector< MessageData > &expanded_messages, std::vector< DictionaryEntry > &dictionary)
std::optional< std::pair< int, std::string > > ParseOrgHeader(const std::string &line)
std::string MessageBankToString(MessageBank bank)
constexpr int kExpandedTextDataEndDefault
std::string ReplaceAllDictionaryWords(std::string str, const std::vector< DictionaryEntry > &dictionary)
absl::Status WriteExpandedTextData(Rom *rom, int start, int end, const std::vector< std::string > &messages)
nlohmann::json SerializeMessageBundle(const std::vector< MessageData > &vanilla, const std::vector< MessageData > &expanded)
constexpr int kPointersDictionaries
absl::StatusOr< std::vector< MessageBundleEntry > > LoadMessageBundleFromJson(const std::string &path)
constexpr int kNumDictionaryEntries
absl::StatusOr< MessageData > ParseSingleMessage(const std::vector< uint8_t > &rom_data, int *current_pos)
absl::StatusOr< std::vector< MessageBundleEntry > > ParseMessageBundleJson(const nlohmann::json &json)
std::vector< std::string > ParseMessageData(std::vector< MessageData > &message_data, const std::vector< DictionaryEntry > &dictionary_entries)
std::optional< TextElement > FindMatchingSpecial(uint8_t value)
constexpr uint8_t kMessageTerminator
std::vector< MessageData > ReadAllTextData(uint8_t *rom, int pos, int max_pos)
constexpr int kTextData2End
std::vector< DictionaryEntry > BuildDictionaryEntries(Rom *rom)
constexpr uint8_t kBankSwitchCommand
std::vector< uint8_t > ParseMessageToData(std::string str)
absl::Status ExportMessagesToJson(const std::string &path, const std::vector< MessageData > &messages)
absl::Status ExportMessageBundleToJson(const std::string &path, const std::vector< MessageData > &vanilla, const std::vector< MessageData > &expanded)
constexpr uint8_t DICTOFF
std::string ExportToOrgFormat(const std::vector< std::pair< int, std::string > > &messages, const std::vector< std::string > &labels)
std::vector< MessageData > ReadExpandedTextData(uint8_t *rom, int pos)
std::optional< TextElement > FindMatchingCommand(uint8_t b)
MessageParseResult ParseMessageToDataWithDiagnostics(std::string_view str)
int GetExpandedTextDataEnd()
ParsedElement FindMatchingElement(const std::string &str)
std::vector< std::string > ValidateMessageLineWidths(const std::string &message)
std::vector< std::pair< int, std::string > > ParseOrgContent(const std::string &content)
constexpr int kExpandedTextDataDefault
int8_t FindDictionaryEntry(uint8_t value)
constexpr int kTextDataEnd
std::string HexByte(uint8_t byte, HexStringParams params)
void logf(const absl::FormatSpec< Args... > &format, Args &&... args)
uint32_t Get24LocalFromPC(uint8_t *data, int addr, bool pc=true)
uint32_t SnesToPc(uint32_t addr) noexcept
#define RETURN_IF_ERROR(expr)
std::vector< uint8_t > Data
std::vector< uint8_t > DataParsed
std::string ContentsParsed
std::vector< uint8_t > bytes
std::vector< std::string > errors
std::vector< std::string > warnings
std::string GetParamToken(uint8_t value=0) const