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);
218 uint8_t value,
const std::vector<DictionaryEntry>& dictionary);
239 const std::vector<uint8_t>& rawData,
240 const std::string& parsedString,
241 const std::vector<uint8_t>& parsedData)
264 std::string_view message_string,
265 const std::vector<DictionaryEntry>& dictionary) {
266 std::stringstream protons;
267 bool command =
false;
269 for (
const auto& c : message_string) {
272 }
else if (c ==
']') {
282 std::string protons_string = protons.str();
283 std::string replaced_string =
285 std::string final_string =
286 absl::StrReplaceAll(replaced_string, {{
CHEESE,
""}});
294 const std::vector<DictionaryEntry>& dictionary) {
325 const std::string& description) {
337 "\\[%s(:[0-9A-F]{1,2})?\\]",
338 absl::StrReplaceAll(
Token, {{
"[",
"\\["}, {
"]",
"\\]"}}));
341 "\\[%s\\]", absl::StrReplaceAll(
Token, {{
"[",
"\\["}, {
"]",
"\\]"}}));
348 return absl::StrFormat(
"[%s:%02X]",
Token, value);
350 return absl::StrFormat(
"[%s]",
Token);
354 std::smatch
MatchMe(
const std::string& dfrag)
const {
357 std::regex_match(dfrag, match, pattern);
367const static std::string kWindowBorder =
"Window border";
368const static std::string kWindowPosition =
"Window position";
369const static std::string kScrollSpeed =
"Scroll speed";
370const static std::string kTextDrawSpeed =
"Text draw speed";
371const static std::string kTextColor =
"Text color";
372const static std::string kPlayerName =
"Player name";
373const static std::string kLine1Str =
"Line 1";
374const static std::string kLine2Str =
"Line 2";
375const static std::string kLine3Str =
"Line 3";
376const static std::string kWaitForKey =
"Wait for key";
377const static std::string kScrollText =
"Scroll text";
378const static std::string kDelayX =
"Delay X";
379const static std::string kBCDNumber =
"BCD number";
380const static std::string kSoundEffect =
"Sound effect";
381const static std::string kChoose3 =
"Choose 3";
382const static std::string kChoose2High =
"Choose 2 high";
383const static std::string kChoose2Low =
"Choose 2 low";
384const static std::string kChoose2Indented =
"Choose 2 indented";
385const static std::string kChooseItem =
"Choose item";
386const static std::string kNextAttractImage =
"Next attract image";
387const static std::string kBankMarker =
"Bank marker (automatic)";
388const static std::string kCrash =
"Crash";
390static const std::vector<TextElement> TextCommands = {
391 TextElement(0x6B,
"W",
true, kWindowBorder),
392 TextElement(0x6D,
"P",
true, kWindowPosition),
393 TextElement(0x6E,
"SPD",
true, kScrollSpeed),
394 TextElement(0x7A,
"S",
true, kTextDrawSpeed),
395 TextElement(0x77,
"C",
true, kTextColor),
396 TextElement(0x6A,
"L",
false, kPlayerName),
397 TextElement(0x74,
"1",
false, kLine1Str),
398 TextElement(0x75,
"2",
false, kLine2Str),
399 TextElement(0x76,
"3",
false, kLine3Str),
400 TextElement(0x7E,
"K",
false, kWaitForKey),
401 TextElement(0x73,
"V",
false, kScrollText),
402 TextElement(0x78,
"WT",
true, kDelayX),
403 TextElement(0x6C,
"N",
true, kBCDNumber),
404 TextElement(0x79,
"SFX",
true, kSoundEffect),
405 TextElement(0x71,
"CH3",
false, kChoose3),
406 TextElement(0x72,
"CH2",
false, kChoose2High),
407 TextElement(0x6F,
"CH2L",
false, kChoose2Low),
408 TextElement(0x68,
"CH2I",
false, kChoose2Indented),
409 TextElement(0x69,
"CHI",
false, kChooseItem),
410 TextElement(0x67,
"IMG",
false, kNextAttractImage),
411 TextElement(0x80,
kBankToken,
false, kBankMarker),
412 TextElement(0x70,
"NONO",
false, kCrash),
421static const std::vector<TextElement> SpecialChars = {
422 TextElement(0x43,
"...",
false,
"Ellipsis …"),
423 TextElement(0x4D,
"UP",
false,
"Arrow ↑"),
424 TextElement(0x4E,
"DOWN",
false,
"Arrow ↓"),
425 TextElement(0x4F,
"LEFT",
false,
"Arrow ←"),
426 TextElement(0x50,
"RIGHT",
false,
"Arrow →"),
427 TextElement(0x5B,
"A",
false,
"Button Ⓐ"),
428 TextElement(0x5C,
"B",
false,
"Button Ⓑ"),
429 TextElement(0x5D,
"X",
false,
"Button ⓧ"),
430 TextElement(0x5E,
"Y",
false,
"Button ⓨ"),
431 TextElement(0x52,
"HP1L",
false,
"1 HP left"),
432 TextElement(0x53,
"HP1R",
false,
"1 HP right"),
433 TextElement(0x54,
"HP2L",
false,
"2 HP left"),
434 TextElement(0x55,
"HP3L",
false,
"3 HP left"),
435 TextElement(0x56,
"HP3R",
false,
"3 HP right"),
436 TextElement(0x57,
"HP4L",
false,
"4 HP left"),
437 TextElement(0x58,
"HP4R",
false,
"4 HP right"),
438 TextElement(0x47,
"HY0",
false,
"Hieroglyph ☥"),
439 TextElement(0x48,
"HY1",
false,
"Hieroglyph 𓈗"),
440 TextElement(0x49,
"HY2",
false,
"Hieroglyph Ƨ"),
441 TextElement(0x4A,
"LFL",
false,
"Link face left"),
442 TextElement(0x4B,
"LFR",
false,
"Link face right"),
473 const std::vector<uint8_t>& rom_data,
int* current_pos);
479 std::vector<MessageData>& message_data,
480 const std::vector<DictionaryEntry>& dictionary_entries);
492 std::vector<std::string>& parsed_messages,
493 std::vector<MessageData>& expanded_messages,
494 std::vector<DictionaryEntry>& dictionary);
501 const std::vector<MessageData>& messages);
505 const std::vector<MessageData>& expanded);
509 const std::string& path,
const std::vector<MessageData>& vanilla,
510 const std::vector<MessageData>& expanded);
514 const nlohmann::json& json);
518 const std::string& path);
539 const std::string& line);
544 const std::string& content);
550 const std::vector<std::pair<int, std::string>>& messages,
551 const std::vector<std::string>& labels);
579 const std::vector<std::string>& messages);
584 const std::vector<std::string>& messages);
588 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
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