yaze 0.2.0
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
message_data.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_MESSAGE_MESSAGE_DATA_H
2#define YAZE_APP_EDITOR_MESSAGE_MESSAGE_DATA_H
3
4#include <regex>
5#include <string>
6#include <vector>
7
8#include "absl/strings/str_cat.h"
9#include "absl/strings/str_format.h"
10#include "absl/strings/str_replace.h"
11#include "app/rom.h"
12
13namespace yaze {
14namespace app {
15namespace editor {
16
17const uint8_t kMessageTerminator = 0x7F;
18const std::string BANKToken = "BANK";
19const std::string DICTIONARYTOKEN = "D";
20constexpr uint8_t DICTOFF = 0x88;
21
22static const std::unordered_map<uint8_t, wchar_t> CharEncoder = {
23 {0x00, 'A'}, {0x01, 'B'}, {0x02, 'C'}, {0x03, 'D'}, {0x04, 'E'},
24 {0x05, 'F'}, {0x06, 'G'}, {0x07, 'H'}, {0x08, 'I'}, {0x09, 'J'},
25 {0x0A, 'K'}, {0x0B, 'L'}, {0x0C, 'M'}, {0x0D, 'N'}, {0x0E, 'O'},
26 {0x0F, 'P'}, {0x10, 'Q'}, {0x11, 'R'}, {0x12, 'S'}, {0x13, 'T'},
27 {0x14, 'U'}, {0x15, 'V'}, {0x16, 'W'}, {0x17, 'X'}, {0x18, 'Y'},
28 {0x19, 'Z'}, {0x1A, 'a'}, {0x1B, 'b'}, {0x1C, 'c'}, {0x1D, 'd'},
29 {0x1E, 'e'}, {0x1F, 'f'}, {0x20, 'g'}, {0x21, 'h'}, {0x22, 'i'},
30 {0x23, 'j'}, {0x24, 'k'}, {0x25, 'l'}, {0x26, 'm'}, {0x27, 'n'},
31 {0x28, 'o'}, {0x29, 'p'}, {0x2A, 'q'}, {0x2B, 'r'}, {0x2C, 's'},
32 {0x2D, 't'}, {0x2E, 'u'}, {0x2F, 'v'}, {0x30, 'w'}, {0x31, 'x'},
33 {0x32, 'y'}, {0x33, 'z'}, {0x34, '0'}, {0x35, '1'}, {0x36, '2'},
34 {0x37, '3'}, {0x38, '4'}, {0x39, '5'}, {0x3A, '6'}, {0x3B, '7'},
35 {0x3C, '8'}, {0x3D, '9'}, {0x3E, '!'}, {0x3F, '?'}, {0x40, '-'},
36 {0x41, '.'}, {0x42, ','}, {0x44, '>'}, {0x45, '('}, {0x46, ')'},
37 {0x4C, '"'}, {0x51, '\''}, {0x59, ' '}, {0x5A, '<'}, {0x5F, L'¡'},
38 {0x60, L'¡'}, {0x61, L'¡'}, {0x62, L' '}, {0x63, L' '}, {0x64, L' '},
39 {0x65, ' '}, {0x66, '_'},
40};
41
42uint8_t FindMatchingCharacter(char value);
43uint8_t FindDictionaryEntry(uint8_t value);
44
45std::vector<uint8_t> ParseMessageToData(std::string str);
46
48 uint8_t ID;
49 std::string Contents;
50 std::vector<uint8_t> Data;
51 int Length;
52 std::string Token;
53
54 DictionaryEntry() = default;
55 DictionaryEntry(uint8_t i, std::string s)
56 : Contents(s), ID(i), Length(s.length()) {
57 Token = absl::StrFormat("[%s:%00X]", DICTIONARYTOKEN, ID);
59 }
60
61 bool ContainedInString(std::string s) {
62 return s.find(Contents) != std::string::npos;
63 }
64
65 std::string ReplaceInstancesOfIn(std::string s) {
66 std::string replacedString = s;
67 size_t pos = replacedString.find(Contents);
68 while (pos != std::string::npos) {
69 replacedString.replace(pos, Contents.length(), Token);
70 pos = replacedString.find(Contents, pos + Token.length());
71 }
72 return replacedString;
73 }
74};
75
76constexpr int kTextData = 0xE0000;
77constexpr int kTextDataEnd = 0xE7FFF;
78constexpr int kNumDictionaryEntries = 97;
79constexpr int kPointersDictionaries = 0x74703;
80
81std::vector<DictionaryEntry> BuildDictionaryEntries(app::Rom* rom);
82
83std::string ReplaceAllDictionaryWords(std::string str,
84 std::vector<DictionaryEntry> dictionary);
85
86// Inserted into commands to protect them from dictionary replacements.
87const std::string CHEESE = "\uBEBE";
88
90 int ID;
92 std::string RawString;
93 std::string ContentsParsed;
94 std::vector<uint8_t> Data;
95 std::vector<uint8_t> DataParsed;
96
97 MessageData() = default;
98 MessageData(int id, int address, const std::string& rawString,
99 const std::vector<uint8_t>& rawData,
100 const std::string& parsedString,
101 const std::vector<uint8_t>& parsedData)
102 : ID(id),
103 Address(address),
104 RawString(rawString),
105 Data(rawData),
106 DataParsed(parsedData),
107 ContentsParsed(parsedString) {}
108
109 // Copy constructor
110 MessageData(const MessageData& other) {
111 ID = other.ID;
112 Address = other.Address;
113 RawString = other.RawString;
114 Data = other.Data;
115 DataParsed = other.DataParsed;
117 }
118
119 std::string ToString() {
120 return absl::StrFormat("%0X - %s", ID, ContentsParsed);
121 }
122
124 std::string messageString,
125 const std::vector<DictionaryEntry>& dictionary) {
126 std::stringstream protons;
127 bool command = false;
128 for (const auto& c : messageString) {
129 if (c == '[') {
130 command = true;
131 } else if (c == ']') {
132 command = false;
133 }
134
135 protons << c;
136 if (command) {
137 protons << CHEESE;
138 }
139 }
140
141 std::string protonsString = protons.str();
142 std::string replacedString =
143 ReplaceAllDictionaryWords(protonsString, dictionary);
144 std::string finalString =
145 absl::StrReplaceAll(replacedString, {{CHEESE, ""}});
146
147 return finalString;
148 }
149
150 void SetMessage(const std::string& message,
151 const std::vector<DictionaryEntry>& dictionary) {
152 RawString = message;
153 ContentsParsed = OptimizeMessageForDictionary(message, dictionary);
154 }
155};
156
158 uint8_t ID;
159 std::string Token;
160 std::string GenericToken;
161 std::string Pattern;
162 std::string StrictPattern;
163 std::string Description;
165
166 TextElement() = default;
167 TextElement(uint8_t id, std::string token, bool arg,
168 std::string description) {
169 ID = id;
170 Token = token;
171 if (arg) {
172 GenericToken = absl::StrFormat("[%s:##]", Token);
173 } else {
174 GenericToken = absl::StrFormat("[%s]", Token);
175 }
176 HasArgument = arg;
177 Description = description;
178 Pattern =
179 arg ? "\\[" + Token + ":?([0-9A-F]{1,2})\\]" : "\\[" + Token + "\\]";
180 Pattern = absl::StrReplaceAll(Pattern, {{"[", "\\["}, {"]", "\\]"}});
181 StrictPattern = absl::StrCat("^", Pattern, "$");
182 StrictPattern = "^" + Pattern + "$";
183 }
184
185 std::string GetParameterizedToken(uint8_t value = 0) {
186 if (HasArgument) {
187 return absl::StrFormat("[%s:%02X]", Token, value);
188 } else {
189 return absl::StrFormat("[%s]", Token);
190 }
191 }
192
193 std::string ToString() {
194 return absl::StrFormat("%s %s", GenericToken, Description);
195 }
196
197 std::smatch MatchMe(std::string dfrag) const {
198 std::regex pattern(StrictPattern);
199 std::smatch match;
200 std::regex_match(dfrag, match, pattern);
201 return match;
202 }
203
204 bool Empty() { return ID == 0; }
205
206 // Comparison operator
207 bool operator==(const TextElement& other) const { return ID == other.ID; }
208};
209
210static const std::vector<TextElement> TextCommands = {
211 TextElement(0x6B, "W", true, "Window border"),
212 TextElement(0x6D, "P", true, "Window position"),
213 TextElement(0x6E, "SPD", true, "Scroll speed"),
214 TextElement(0x7A, "S", true, "Text draw speed"),
215 TextElement(0x77, "C", true, "Text color"),
216 TextElement(0x6A, "L", false, "Player name"),
217 TextElement(0x74, "1", false, "Line 1"),
218 TextElement(0x75, "2", false, "Line 2"),
219 TextElement(0x76, "3", false, "Line 3"),
220 TextElement(0x7E, "K", false, "Wait for key"),
221 TextElement(0x73, "V", false, "Scroll text"),
222 TextElement(0x78, "WT", true, "Delay X"),
223 TextElement(0x6C, "N", true, "BCD number"),
224 TextElement(0x79, "SFX", true, "Sound effect"),
225 TextElement(0x71, "CH3", false, "Choose 3"),
226 TextElement(0x72, "CH2", false, "Choose 2 high"),
227 TextElement(0x6F, "CH2L", false, "Choose 2 low"),
228 TextElement(0x68, "CH2I", false, "Choose 2 indented"),
229 TextElement(0x69, "CHI", false, "Choose item"),
230 TextElement(0x67, "IMG", false, "Next attract image"),
231 TextElement(0x80, BANKToken, false, "Bank marker (automatic)"),
232 TextElement(0x70, "NONO", false, "Crash"),
233};
234
235TextElement FindMatchingCommand(uint8_t b);
236
237static const std::vector<TextElement> SpecialChars = {
238 TextElement(0x43, "...", false, "Ellipsis …"),
239 TextElement(0x4D, "UP", false, "Arrow ↑"),
240 TextElement(0x4E, "DOWN", false, "Arrow ↓"),
241 TextElement(0x4F, "LEFT", false, "Arrow ←"),
242 TextElement(0x50, "RIGHT", false, "Arrow →"),
243 TextElement(0x5B, "A", false, "Button Ⓐ"),
244 TextElement(0x5C, "B", false, "Button Ⓑ"),
245 TextElement(0x5D, "X", false, "Button ⓧ"),
246 TextElement(0x5E, "Y", false, "Button ⓨ"),
247 TextElement(0x52, "HP1L", false, "1 HP left"),
248 TextElement(0x53, "HP1R", false, "1 HP right"),
249 TextElement(0x54, "HP2L", false, "2 HP left"),
250 TextElement(0x55, "HP3L", false, "3 HP left"),
251 TextElement(0x56, "HP3R", false, "3 HP right"),
252 TextElement(0x57, "HP4L", false, "4 HP left"),
253 TextElement(0x58, "HP4R", false, "4 HP right"),
254 TextElement(0x47, "HY0", false, "Hieroglyph ☥"),
255 TextElement(0x48, "HY1", false, "Hieroglyph 𓈗"),
256 TextElement(0x49, "HY2", false, "Hieroglyph Ƨ"),
257 TextElement(0x4A, "LFL", false, "Link face left"),
258 TextElement(0x4B, "LFR", false, "Link face right"),
259};
260
261TextElement FindMatchingSpecial(uint8_t b);
262
265 uint8_t Value;
266 bool Active = false;
267
268 ParsedElement() = default;
269 ParsedElement(TextElement textElement, uint8_t value) {
270 Parent = textElement;
271 Value = value;
272 Active = true;
273 }
274};
275
276ParsedElement FindMatchingElement(const std::string& str);
277
278std::string ParseTextDataByte(uint8_t value);
279
280} // namespace editor
281} // namespace app
282} // namespace yaze
283
284#endif // YAZE_APP_EDITOR_MESSAGE_MESSAGE_DATA_H
The Rom class is used to load, save, and modify Rom data.
Definition rom.h:145
const std::string DICTIONARYTOKEN
uint8_t FindDictionaryEntry(uint8_t value)
ParsedElement FindMatchingElement(const std::string &str)
constexpr uint8_t DICTOFF
constexpr int kPointersDictionaries
constexpr int kTextDataEnd
constexpr int kTextData
std::vector< DictionaryEntry > BuildDictionaryEntries(app::Rom *rom)
const uint8_t kMessageTerminator
const std::string BANKToken
uint8_t FindMatchingCharacter(char value)
TextElement FindMatchingSpecial(uint8_t value)
const std::string CHEESE
TextElement FindMatchingCommand(uint8_t b)
std::vector< uint8_t > ParseMessageToData(std::string str)
constexpr int kNumDictionaryEntries
std::string ParseTextDataByte(uint8_t value)
std::string ReplaceAllDictionaryWords(std::string str, std::vector< DictionaryEntry > dictionary)
Definition common.cc:21
std::string ReplaceInstancesOfIn(std::string s)
std::vector< uint8_t > Data
bool ContainedInString(std::string s)
DictionaryEntry(uint8_t i, std::string s)
std::vector< uint8_t > DataParsed
std::vector< uint8_t > Data
MessageData(const MessageData &other)
void SetMessage(const std::string &message, const std::vector< DictionaryEntry > &dictionary)
std::string OptimizeMessageForDictionary(std::string messageString, 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)
ParsedElement(TextElement textElement, uint8_t value)
TextElement(uint8_t id, std::string token, bool arg, std::string description)
std::smatch MatchMe(std::string dfrag) const
std::string GetParameterizedToken(uint8_t value=0)
bool operator==(const TextElement &other) const