yaze 0.2.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
message_data.cc
Go to the documentation of this file.
1#include "message_data.h"
2
3#include <string>
4
5#include "util/hex.h"
6#include "util/log.h"
7
8namespace yaze {
9namespace editor {
10
11uint8_t FindMatchingCharacter(char value) {
12 for (const auto [key, char_value] : CharEncoder) {
13 if (value == char_value) {
14 return key;
15 }
16 }
17 return 0xFF;
18}
19
20uint8_t FindDictionaryEntry(uint8_t value) {
21 if (value < DICTOFF || value == 0xFF) {
22 return -1;
23 }
24 return value - DICTOFF;
25}
26
28 TextElement empty_element;
29 for (const auto &text_element : TextCommands) {
30 if (text_element.ID == b) {
31 return text_element;
32 }
33 }
34 return empty_element;
35}
36
38 auto it = std::find_if(SpecialChars.begin(), SpecialChars.end(),
39 [value](const TextElement &text_element) {
40 return text_element.ID == value;
41 });
42 if (it != SpecialChars.end()) {
43 return *it;
44 }
45
46 return TextElement();
47}
48
49ParsedElement FindMatchingElement(const std::string &str) {
50 std::smatch match;
51 for (auto &text_element : TextCommands) {
52 match = text_element.MatchMe(str);
53 if (match.size() > 0) {
54 if (text_element.HasArgument) {
55 return ParsedElement(text_element,
56 std::stoi(match[1].str(), nullptr, 16));
57 } else {
58 return ParsedElement(text_element, 0);
59 }
60 }
61 }
62
63 const auto dictionary_element =
64 TextElement(0x80, DICTIONARYTOKEN, true, "Dictionary");
65
66 match = dictionary_element.MatchMe(str);
67 if (match.size() > 0) {
68 return ParsedElement(dictionary_element,
69 DICTOFF + std::stoi(match[1].str(), nullptr, 16));
70 }
71 return ParsedElement();
72}
73
74std::string ParseTextDataByte(uint8_t value) {
75 if (CharEncoder.contains(value)) {
76 char c = CharEncoder.at(value);
77 std::string str = "";
78 str.push_back(c);
79 return str;
80 }
81
82 // Check for command.
83 TextElement text_element = FindMatchingCommand(value);
84 if (!text_element.Empty()) {
85 return text_element.GenericToken;
86 }
87
88 // Check for special characters.
89 text_element = FindMatchingSpecial(value);
90 if (!text_element.Empty()) {
91 return text_element.GenericToken;
92 }
93
94 // Check for dictionary.
95 int dictionary = FindDictionaryEntry(value);
96 if (dictionary >= 0) {
97 return absl::StrFormat("[%s:%X]", DICTIONARYTOKEN, dictionary);
98 }
99
100 return "";
101}
102
103std::vector<uint8_t> ParseMessageToData(std::string str) {
104 std::vector<uint8_t> bytes;
105 std::string temp_string = str;
106 int pos = 0;
107
108 while (pos < temp_string.size()) {
109 // Get next text fragment.
110 if (temp_string[pos] == '[') {
111 int next = temp_string.find(']', pos);
112 if (next == -1) {
113 break;
114 }
115
116 ParsedElement parsedElement =
117 FindMatchingElement(temp_string.substr(pos, next - pos + 1));
118
119 const auto dictionary_element =
120 TextElement(0x80, DICTIONARYTOKEN, true, "Dictionary");
121
122 if (!parsedElement.Active) {
123 util::logf("Error parsing message: %s", temp_string);
124 break;
125 } else if (parsedElement.Parent == dictionary_element) {
126 bytes.push_back(parsedElement.Value);
127 } else {
128 bytes.push_back(parsedElement.Parent.ID);
129
130 if (parsedElement.Parent.HasArgument) {
131 bytes.push_back(parsedElement.Value);
132 }
133 }
134
135 pos = next + 1;
136 continue;
137 } else {
138 uint8_t bb = FindMatchingCharacter(temp_string[pos++]);
139
140 if (bb != 0xFF) {
141 util::logf("Error parsing message: %s", temp_string);
142 bytes.push_back(bb);
143 }
144 }
145 }
146
147 return bytes;
148}
149
150std::vector<DictionaryEntry> BuildDictionaryEntries(Rom *rom) {
151 std::vector<DictionaryEntry> AllDictionaries;
152 for (int i = 0; i < kNumDictionaryEntries; i++) {
153 std::vector<uint8_t> bytes;
154 std::stringstream stringBuilder;
155
156 int address = SnesToPc(
157 kTextData + (rom->data()[kPointersDictionaries + (i * 2) + 1] << 8) +
158 rom->data()[kPointersDictionaries + (i * 2)]);
159
160 int temppush_backress =
162 (rom->data()[kPointersDictionaries + ((i + 1) * 2) + 1] << 8) +
163 rom->data()[kPointersDictionaries + ((i + 1) * 2)]);
164
165 while (address < temppush_backress) {
166 uint8_t uint8_tDictionary = rom->data()[address++];
167 bytes.push_back(uint8_tDictionary);
168 stringBuilder << ParseTextDataByte(uint8_tDictionary);
169 }
170
171 AllDictionaries.push_back(DictionaryEntry{(uint8_t)i, stringBuilder.str()});
172 }
173
174 std::sort(AllDictionaries.begin(), AllDictionaries.end(),
175 [](const DictionaryEntry &a, const DictionaryEntry &b) {
176 return a.Contents.size() > b.Contents.size();
177 });
178
179 return AllDictionaries;
180}
181
182absl::StatusOr<MessageData> ParseSingleMessage(
183 const std::vector<uint8_t> &rom_data, int *current_pos) {
184 MessageData message_data;
185 int pos = *current_pos;
186 uint8_t current_byte;
187 std::vector<uint8_t> temp_bytes_raw;
188 std::vector<uint8_t> temp_bytes_parsed;
189 std::string current_message_raw;
190 std::string current_message_parsed;
191
192 // Read the message data
193 while (true) {
194 current_byte = rom_data[pos++];
195
196 if (current_byte == kMessageTerminator) {
197 message_data.ID = message_data.ID + 1;
198 message_data.Address = pos;
199 message_data.RawString = current_message_raw;
200 message_data.Data = temp_bytes_raw;
201 message_data.DataParsed = temp_bytes_parsed;
202 message_data.ContentsParsed = current_message_parsed;
203
204 temp_bytes_raw.clear();
205 temp_bytes_parsed.clear();
206 current_message_raw.clear();
207 current_message_parsed.clear();
208
209 break;
210 } else if (current_byte == 0xFF) {
211 break;
212 }
213
214 temp_bytes_raw.push_back(current_byte);
215
216 // Check for command.
217 TextElement text_element = FindMatchingCommand(current_byte);
218 if (!text_element.Empty()) {
219 current_message_raw.append(text_element.GetParamToken());
220 current_message_parsed.append(text_element.GetParamToken());
221 temp_bytes_parsed.push_back(current_byte);
222 continue;
223 }
224
225 // Check for dictionary.
226 int dictionary = FindDictionaryEntry(current_byte);
227 if (dictionary >= 0) {
228 current_message_raw.append("[");
229 current_message_raw.append(DICTIONARYTOKEN);
230 current_message_raw.append(":");
231 current_message_raw.append(util::HexWord(dictionary));
232 current_message_raw.append("]");
233
234 auto mutable_rom_data = const_cast<uint8_t *>(rom_data.data());
235 uint32_t address = Get24LocalFromPC(
236 mutable_rom_data, kPointersDictionaries + (dictionary * 2));
237 uint32_t address_end = Get24LocalFromPC(
238 mutable_rom_data, kPointersDictionaries + ((dictionary + 1) * 2));
239
240 for (uint32_t i = address; i < address_end; i++) {
241 temp_bytes_parsed.push_back(rom_data[i]);
242 current_message_parsed.append(ParseTextDataByte(rom_data[i]));
243 }
244
245 continue;
246 }
247
248 // Everything else.
249 if (CharEncoder.contains(current_byte)) {
250 std::string str = "";
251 str.push_back(CharEncoder.at(current_byte));
252 current_message_raw.append(str);
253 current_message_parsed.append(str);
254 temp_bytes_parsed.push_back(current_byte);
255 }
256 }
257
258 *current_pos = pos;
259 return message_data;
260}
261
262std::vector<std::string> ParseMessageData(
263 std::vector<MessageData> &message_data,
264 const std::vector<DictionaryEntry> &dictionary_entries) {
265 std::vector<std::string> parsed_messages;
266
267 for (auto &message : message_data) {
268 std::cout << "Message #" << message.ID << " at address "
269 << util::HexLong(message.Address) << std::endl;
270 std::cout << " " << message.RawString << std::endl;
271
272 std::string parsed_message = "";
273 for (const uint8_t &byte : message.Data) {
274 if (CharEncoder.contains(byte)) {
275 parsed_message.push_back(CharEncoder.at(byte));
276 } else {
277 if (byte >= DICTOFF && byte < (DICTOFF + 97)) {
278 if (byte > 0 && byte <= dictionary_entries.size()) {
279 auto dic_entry = dictionary_entries[byte];
280 parsed_message.append(dic_entry.Contents);
281 } else {
282 parsed_message.append(dictionary_entries[0].Contents);
283 }
284 } else {
285 auto text_element = FindMatchingCommand(byte);
286 if (!text_element.Empty()) {
287 if (text_element.ID == kScrollVertical ||
288 text_element.ID == kLine2 || text_element.ID == kLine3) {
289 parsed_message.append("\n");
290 }
291 parsed_message.append(text_element.GenericToken);
292 }
293 }
294 }
295 }
296 parsed_messages.push_back(parsed_message);
297 }
298
299 return parsed_messages;
300}
301
302std::vector<std::string> ImportMessageData(std::string_view filename) {
303 std::vector<std::string> messages;
304 std::ifstream file(filename.data());
305 if (!file.is_open()) {
306 util::logf("Error opening file: %s", filename);
307 return messages;
308 }
309
310 // Parse a file with dialogue IDs and convert
311 std::string line;
312 while (std::getline(file, line)) {
313 if (line.empty()) {
314 continue;
315 }
316
317 // Get the Dialogue ID and then read until the next header
318 }
319
320 return messages;
321}
322
323} // namespace editor
324} // namespace yaze
The Rom class is used to load, save, and modify Rom data.
Definition rom.h:59
auto data() const
Definition rom.h:164
Editors are the view controllers for the application.
uint8_t FindMatchingCharacter(char value)
const uint8_t kMessageTerminator
const std::string DICTIONARYTOKEN
constexpr uint8_t kScrollVertical
std::string ParseTextDataByte(uint8_t value)
constexpr int kTextData
uint8_t FindDictionaryEntry(uint8_t value)
constexpr uint8_t kLine2
constexpr int kPointersDictionaries
constexpr int kNumDictionaryEntries
absl::StatusOr< MessageData > ParseSingleMessage(const std::vector< uint8_t > &rom_data, int *current_pos)
std::vector< std::string > ParseMessageData(std::vector< MessageData > &message_data, const std::vector< DictionaryEntry > &dictionary_entries)
std::vector< DictionaryEntry > BuildDictionaryEntries(Rom *rom)
std::vector< std::string > ImportMessageData(std::string_view filename)
TextElement FindMatchingSpecial(uint8_t value)
std::vector< uint8_t > ParseMessageToData(std::string str)
constexpr uint8_t DICTOFF
ParsedElement FindMatchingElement(const std::string &str)
TextElement FindMatchingCommand(uint8_t b)
constexpr uint8_t kLine3
std::string HexWord(uint16_t word, HexStringParams params)
Definition hex.cc:46
std::string HexLong(uint32_t dword, HexStringParams params)
Definition hex.cc:59
Main namespace for the application.
Definition controller.cc:18
uint32_t Get24LocalFromPC(uint8_t *data, int addr, bool pc=true)
Definition rom.h:349
uint32_t SnesToPc(uint32_t addr) noexcept
Definition rom.h:328
std::vector< uint8_t > Data
std::vector< uint8_t > DataParsed
std::string GetParamToken(uint8_t value=0) const