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,
221 bool match_whole_word);
227 std::string_view replacement,
size_t start_pos,
228 bool replace_all,
bool case_sensitive,
229 bool match_whole_word,
230 size_t* first_replaced_pos =
nullptr);
234 uint8_t value,
const std::vector<DictionaryEntry>& dictionary);
255 const std::vector<uint8_t>& rawData,
256 const std::string& parsedString,
257 const std::vector<uint8_t>& parsedData)
280 std::string_view message_string,
281 const std::vector<DictionaryEntry>& dictionary) {
282 std::stringstream protons;
283 bool command =
false;
285 for (
const auto& c : message_string) {
288 }
else if (c ==
']') {
298 std::string protons_string = protons.str();
299 std::string replaced_string =
301 std::string final_string =
302 absl::StrReplaceAll(replaced_string, {{
CHEESE,
""}});
310 const std::vector<DictionaryEntry>& dictionary) {
341 const std::string& description) {
353 "\\[%s(:[0-9A-F]{1,2})?\\]",
354 absl::StrReplaceAll(
Token, {{
"[",
"\\["}, {
"]",
"\\]"}}));
357 "\\[%s\\]", absl::StrReplaceAll(
Token, {{
"[",
"\\["}, {
"]",
"\\]"}}));
364 return absl::StrFormat(
"[%s:%02X]",
Token, value);
366 return absl::StrFormat(
"[%s]",
Token);
370 std::smatch
MatchMe(
const std::string& dfrag)
const {
373 std::regex_match(dfrag, match, pattern);
383const static std::string kWindowBorder =
"Window border";
384const static std::string kWindowPosition =
"Window position";
385const static std::string kScrollSpeed =
"Scroll speed";
386const static std::string kTextDrawSpeed =
"Text draw speed";
387const static std::string kTextColor =
"Text color";
388const static std::string kPlayerName =
"Player name";
389const static std::string kLine1Str =
"Line 1";
390const static std::string kLine2Str =
"Line 2";
391const static std::string kLine3Str =
"Line 3";
392const static std::string kWaitForKey =
"Wait for key";
393const static std::string kScrollText =
"Scroll text";
394const static std::string kDelayX =
"Delay X";
395const static std::string kBCDNumber =
"BCD number";
396const static std::string kSoundEffect =
"Sound effect";
397const static std::string kChoose3 =
"Choose 3";
398const static std::string kChoose2High =
"Choose 2 high";
399const static std::string kChoose2Low =
"Choose 2 low";
400const static std::string kChoose2Indented =
"Choose 2 indented";
401const static std::string kChooseItem =
"Choose item";
402const static std::string kNextAttractImage =
"Next attract image";
403const static std::string kBankMarker =
"Bank marker (automatic)";
404const static std::string kCrash =
"Crash";
406static const std::vector<TextElement> TextCommands = {
407 TextElement(0x6B,
"W",
true, kWindowBorder),
408 TextElement(0x6D,
"P",
true, kWindowPosition),
409 TextElement(0x6E,
"SPD",
true, kScrollSpeed),
410 TextElement(0x7A,
"S",
true, kTextDrawSpeed),
411 TextElement(0x77,
"C",
true, kTextColor),
412 TextElement(0x6A,
"L",
false, kPlayerName),
413 TextElement(0x74,
"1",
false, kLine1Str),
414 TextElement(0x75,
"2",
false, kLine2Str),
415 TextElement(0x76,
"3",
false, kLine3Str),
416 TextElement(0x7E,
"K",
false, kWaitForKey),
417 TextElement(0x73,
"V",
false, kScrollText),
418 TextElement(0x78,
"WT",
true, kDelayX),
419 TextElement(0x6C,
"N",
true, kBCDNumber),
420 TextElement(0x79,
"SFX",
true, kSoundEffect),
421 TextElement(0x71,
"CH3",
false, kChoose3),
422 TextElement(0x72,
"CH2",
false, kChoose2High),
423 TextElement(0x6F,
"CH2L",
false, kChoose2Low),
424 TextElement(0x68,
"CH2I",
false, kChoose2Indented),
425 TextElement(0x69,
"CHI",
false, kChooseItem),
426 TextElement(0x67,
"IMG",
false, kNextAttractImage),
427 TextElement(0x80,
kBankToken,
false, kBankMarker),
428 TextElement(0x70,
"NONO",
false, kCrash),
437static const std::vector<TextElement> SpecialChars = {
438 TextElement(0x43,
"...",
false,
"Ellipsis …"),
439 TextElement(0x4D,
"UP",
false,
"Arrow ↑"),
440 TextElement(0x4E,
"DOWN",
false,
"Arrow ↓"),
441 TextElement(0x4F,
"LEFT",
false,
"Arrow ←"),
442 TextElement(0x50,
"RIGHT",
false,
"Arrow →"),
443 TextElement(0x5B,
"A",
false,
"Button Ⓐ"),
444 TextElement(0x5C,
"B",
false,
"Button Ⓑ"),
445 TextElement(0x5D,
"X",
false,
"Button ⓧ"),
446 TextElement(0x5E,
"Y",
false,
"Button ⓨ"),
447 TextElement(0x52,
"HP1L",
false,
"1 HP left"),
448 TextElement(0x53,
"HP1R",
false,
"1 HP right"),
449 TextElement(0x54,
"HP2L",
false,
"2 HP left"),
450 TextElement(0x55,
"HP3L",
false,
"3 HP left"),
451 TextElement(0x56,
"HP3R",
false,
"3 HP right"),
452 TextElement(0x57,
"HP4L",
false,
"4 HP left"),
453 TextElement(0x58,
"HP4R",
false,
"4 HP right"),
454 TextElement(0x47,
"HY0",
false,
"Hieroglyph ☥"),
455 TextElement(0x48,
"HY1",
false,
"Hieroglyph 𓈗"),
456 TextElement(0x49,
"HY2",
false,
"Hieroglyph Ƨ"),
457 TextElement(0x4A,
"LFL",
false,
"Link face left"),
458 TextElement(0x4B,
"LFR",
false,
"Link face right"),
489 const std::vector<uint8_t>& rom_data,
int* current_pos);
495 std::vector<MessageData>& message_data,
496 const std::vector<DictionaryEntry>& dictionary_entries);
508 std::vector<std::string>& parsed_messages,
509 std::vector<MessageData>& expanded_messages,
510 std::vector<DictionaryEntry>& dictionary);
517 const std::vector<MessageData>& messages);
521 const std::vector<MessageData>& expanded);
525 const std::string& path,
const std::vector<MessageData>& vanilla,
526 const std::vector<MessageData>& expanded);
530 const nlohmann::json& json);
534 const std::string& path);
555 const std::string& line);
560 const std::string& content);
566 const std::vector<std::pair<int, std::string>>& messages,
567 const std::vector<std::string>& labels);
595 const std::vector<std::string>& messages);
600 const std::vector<std::string>& messages);
604 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< 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
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