1#ifndef YAZE_APP_EDITOR_MESSAGE_MESSAGE_DATA_H
2#define YAZE_APP_EDITOR_MESSAGE_MESSAGE_DATA_H
85#include <unordered_map>
88#include <nlohmann/json.hpp>
89#include "absl/status/status.h"
90#include "absl/status/statusor.h"
91#include "absl/strings/match.h"
92#include "absl/strings/str_format.h"
93#include "absl/strings/str_replace.h"
108static const std::unordered_map<uint8_t, wchar_t> CharEncoder = {
109 {0x00,
'A'}, {0x01,
'B'}, {0x02,
'C'}, {0x03,
'D'}, {0x04,
'E'},
110 {0x05,
'F'}, {0x06,
'G'}, {0x07,
'H'}, {0x08,
'I'}, {0x09,
'J'},
111 {0x0A,
'K'}, {0x0B,
'L'}, {0x0C,
'M'}, {0x0D,
'N'}, {0x0E,
'O'},
112 {0x0F,
'P'}, {0x10,
'Q'}, {0x11,
'R'}, {0x12,
'S'}, {0x13,
'T'},
113 {0x14,
'U'}, {0x15,
'V'}, {0x16,
'W'}, {0x17,
'X'}, {0x18,
'Y'},
114 {0x19,
'Z'}, {0x1A,
'a'}, {0x1B,
'b'}, {0x1C,
'c'}, {0x1D,
'd'},
115 {0x1E,
'e'}, {0x1F,
'f'}, {0x20,
'g'}, {0x21,
'h'}, {0x22,
'i'},
116 {0x23,
'j'}, {0x24,
'k'}, {0x25,
'l'}, {0x26,
'm'}, {0x27,
'n'},
117 {0x28,
'o'}, {0x29,
'p'}, {0x2A,
'q'}, {0x2B,
'r'}, {0x2C,
's'},
118 {0x2D,
't'}, {0x2E,
'u'}, {0x2F,
'v'}, {0x30,
'w'}, {0x31,
'x'},
119 {0x32,
'y'}, {0x33,
'z'}, {0x34,
'0'}, {0x35,
'1'}, {0x36,
'2'},
120 {0x37,
'3'}, {0x38,
'4'}, {0x39,
'5'}, {0x3A,
'6'}, {0x3B,
'7'},
121 {0x3C,
'8'}, {0x3D,
'9'}, {0x3E,
'!'}, {0x3F,
'?'}, {0x40,
'-'},
122 {0x41,
'.'}, {0x42,
','}, {0x44,
'>'}, {0x45,
'('}, {0x46,
')'},
123 {0x4C,
'"'}, {0x51,
'\''}, {0x59,
' '}, {0x5A,
'<'}, {0x5F, L
'¡'},
124 {0x60, L
'¡'}, {0x61, L
'¡'}, {0x62, L
' '}, {0x63, L
' '}, {0x64, L
' '},
125 {0x65,
' '}, {0x66,
'_'},
183 return absl::StrContains(std::string(s),
Contents);
189 auto replaced_string = std::string(s);
190 size_t pos = replaced_string.find(
Contents);
191 while (pos != std::string::npos) {
195 return replaced_string;
214 std::string str,
const std::vector<DictionaryEntry>& dictionary);
219 std::string_view query,
size_t start_pos,
220 bool case_sensitive,
bool match_whole_word);
226 std::string_view replacement,
size_t start_pos,
227 bool replace_all,
bool case_sensitive,
228 bool match_whole_word,
229 size_t* first_replaced_pos =
nullptr);
233 uint8_t value,
const std::vector<DictionaryEntry>& dictionary);
254 const std::vector<uint8_t>& rawData,
255 const std::string& parsedString,
256 const std::vector<uint8_t>& parsedData)
279 std::string_view message_string,
280 const std::vector<DictionaryEntry>& dictionary) {
281 std::stringstream protons;
282 bool command =
false;
284 for (
const auto& c : message_string) {
287 }
else if (c ==
']') {
297 std::string protons_string = protons.str();
298 std::string replaced_string =
300 std::string final_string =
301 absl::StrReplaceAll(replaced_string, {{
CHEESE,
""}});
309 const std::vector<DictionaryEntry>& dictionary) {
340 const std::string& description) {
352 "\\[%s(:[0-9A-F]{1,2})?\\]",
353 absl::StrReplaceAll(
Token, {{
"[",
"\\["}, {
"]",
"\\]"}}));
356 "\\[%s\\]", absl::StrReplaceAll(
Token, {{
"[",
"\\["}, {
"]",
"\\]"}}));
363 return absl::StrFormat(
"[%s:%02X]",
Token, value);
365 return absl::StrFormat(
"[%s]",
Token);
369 std::smatch
MatchMe(
const std::string& dfrag)
const {
372 std::regex_match(dfrag, match, pattern);
382const static std::string kWindowBorder =
"Window border";
383const static std::string kWindowPosition =
"Window position";
384const static std::string kScrollSpeed =
"Scroll speed";
385const static std::string kTextDrawSpeed =
"Text draw speed";
386const static std::string kTextColor =
"Text color";
387const static std::string kPlayerName =
"Player name";
388const static std::string kLine1Str =
"Line 1";
389const static std::string kLine2Str =
"Line 2";
390const static std::string kLine3Str =
"Line 3";
391const static std::string kWaitForKey =
"Wait for key";
392const static std::string kScrollText =
"Scroll text";
393const static std::string kDelayX =
"Delay X";
394const static std::string kBCDNumber =
"BCD number";
395const static std::string kSoundEffect =
"Sound effect";
396const static std::string kChoose3 =
"Choose 3";
397const static std::string kChoose2High =
"Choose 2 high";
398const static std::string kChoose2Low =
"Choose 2 low";
399const static std::string kChoose2Indented =
"Choose 2 indented";
400const static std::string kChooseItem =
"Choose item";
401const static std::string kNextAttractImage =
"Next attract image";
402const static std::string kBankMarker =
"Bank marker (automatic)";
403const static std::string kCrash =
"Crash";
405static const std::vector<TextElement> TextCommands = {
406 TextElement(0x6B,
"W",
true, kWindowBorder),
407 TextElement(0x6D,
"P",
true, kWindowPosition),
408 TextElement(0x6E,
"SPD",
true, kScrollSpeed),
409 TextElement(0x7A,
"S",
true, kTextDrawSpeed),
410 TextElement(0x77,
"C",
true, kTextColor),
411 TextElement(0x6A,
"L",
false, kPlayerName),
412 TextElement(0x74,
"1",
false, kLine1Str),
413 TextElement(0x75,
"2",
false, kLine2Str),
414 TextElement(0x76,
"3",
false, kLine3Str),
415 TextElement(0x7E,
"K",
false, kWaitForKey),
416 TextElement(0x73,
"V",
false, kScrollText),
417 TextElement(0x78,
"WT",
true, kDelayX),
418 TextElement(0x6C,
"N",
true, kBCDNumber),
419 TextElement(0x79,
"SFX",
true, kSoundEffect),
420 TextElement(0x71,
"CH3",
false, kChoose3),
421 TextElement(0x72,
"CH2",
false, kChoose2High),
422 TextElement(0x6F,
"CH2L",
false, kChoose2Low),
423 TextElement(0x68,
"CH2I",
false, kChoose2Indented),
424 TextElement(0x69,
"CHI",
false, kChooseItem),
425 TextElement(0x67,
"IMG",
false, kNextAttractImage),
426 TextElement(0x80,
kBankToken,
false, kBankMarker),
427 TextElement(0x70,
"NONO",
false, kCrash),
436static const std::vector<TextElement> SpecialChars = {
437 TextElement(0x43,
"...",
false,
"Ellipsis …"),
438 TextElement(0x4D,
"UP",
false,
"Arrow ↑"),
439 TextElement(0x4E,
"DOWN",
false,
"Arrow ↓"),
440 TextElement(0x4F,
"LEFT",
false,
"Arrow ←"),
441 TextElement(0x50,
"RIGHT",
false,
"Arrow →"),
442 TextElement(0x5B,
"A",
false,
"Button Ⓐ"),
443 TextElement(0x5C,
"B",
false,
"Button Ⓑ"),
444 TextElement(0x5D,
"X",
false,
"Button ⓧ"),
445 TextElement(0x5E,
"Y",
false,
"Button ⓨ"),
446 TextElement(0x52,
"HP1L",
false,
"1 HP left"),
447 TextElement(0x53,
"HP1R",
false,
"1 HP right"),
448 TextElement(0x54,
"HP2L",
false,
"2 HP left"),
449 TextElement(0x55,
"HP3L",
false,
"3 HP left"),
450 TextElement(0x56,
"HP3R",
false,
"3 HP right"),
451 TextElement(0x57,
"HP4L",
false,
"4 HP left"),
452 TextElement(0x58,
"HP4R",
false,
"4 HP right"),
453 TextElement(0x47,
"HY0",
false,
"Hieroglyph ☥"),
454 TextElement(0x48,
"HY1",
false,
"Hieroglyph 𓈗"),
455 TextElement(0x49,
"HY2",
false,
"Hieroglyph Ƨ"),
456 TextElement(0x4A,
"LFL",
false,
"Link face left"),
457 TextElement(0x4B,
"LFR",
false,
"Link face right"),
488 const std::vector<uint8_t>& rom_data,
int* current_pos);
494 std::vector<MessageData>& message_data,
495 const std::vector<DictionaryEntry>& dictionary_entries);
505 bool allow_bank_switch =
true);
509 std::vector<std::string>& parsed_messages,
510 std::vector<MessageData>& expanded_messages,
511 std::vector<DictionaryEntry>& dictionary);
515 const std::vector<MessageData>& messages);
519 const std::vector<MessageData>& messages);
523 const std::vector<MessageData>& expanded);
527 const std::string& path,
const std::vector<MessageData>& vanilla,
528 const std::vector<MessageData>& expanded);
532 const nlohmann::json& json);
536 const std::string& path);
557 const std::string& line);
562 const std::string& content);
568 const std::vector<std::pair<int, std::string>>& messages,
569 const std::vector<std::string>& labels);
601 const std::vector<std::string>& messages);
606 const std::vector<std::string>& messages);
610 const std::vector<MessageData>& messages);
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
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< MessageData > ReadAllTextData(uint8_t *rom, int pos, int max_pos, bool allow_bank_switch)
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
constexpr int kTextData2End
std::vector< DictionaryEntry > BuildDictionaryEntries(Rom *rom)
constexpr uint8_t kBankSwitchCommand
int ReplaceTextMatches(std::string *text, std::string_view query, std::string_view replacement, size_t start_pos, bool replace_all, bool case_sensitive, bool match_whole_word, size_t *first_replaced_pos)
std::optional< size_t > FindTextMatch(std::string_view text, std::string_view query, size_t start_pos, bool case_sensitive, bool match_whole_word)
std::vector< uint8_t > ParseMessageToData(std::string str)
absl::Status ExportMessagesToJson(const std::string &path, const std::vector< MessageData > &messages)
constexpr uint8_t kWidthArraySize
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
bool ContainedInString(std::string_view s) const
std::string ReplaceInstancesOfIn(std::string_view s) const
DictionaryEntry(uint8_t i, std::string_view s)
std::vector< uint8_t > Data
DictionaryEntry()=default
MessageData(const MessageData &other)
std::vector< uint8_t > Data
std::vector< uint8_t > DataParsed
std::string ContentsParsed
std::string OptimizeMessageForDictionary(std::string_view message_string, const std::vector< DictionaryEntry > &dictionary)
void SetMessage(const std::string &message, const std::vector< DictionaryEntry > &dictionary)
MessageData(int id, int address, const std::string &rawString, const std::vector< uint8_t > &rawData, const std::string &parsedString, const std::vector< uint8_t > &parsedData)
std::vector< uint8_t > bytes
std::vector< std::string > errors
std::vector< std::string > warnings
ParsedElement(const TextElement &textElement, uint8_t value)
std::smatch MatchMe(const std::string &dfrag) const
std::string StrictPattern
TextElement(uint8_t id, const std::string &token, bool arg, const std::string &description)
bool operator==(const TextElement &other) const
std::string GetParamToken(uint8_t value=0) const