backend-infra-engineer: Release v0.3.0 snapshot

This commit is contained in:
scawful
2025-09-27 00:25:45 -04:00
parent 8ce29e1436
commit e32ac75b9c
346 changed files with 55946 additions and 11764 deletions

View File

@@ -1,6 +1,11 @@
#include "message_data.h"
#include "app/core/common.h"
#include <optional>
#include <string>
#include "app/snes.h"
#include "util/hex.h"
#include "util/log.h"
namespace yaze {
namespace editor {
@@ -14,45 +19,46 @@ uint8_t FindMatchingCharacter(char value) {
return 0xFF;
}
uint8_t FindDictionaryEntry(uint8_t value) {
int8_t FindDictionaryEntry(uint8_t value) {
if (value < DICTOFF || value == 0xFF) {
return -1;
}
return value - DICTOFF;
}
TextElement FindMatchingCommand(uint8_t b) {
TextElement empty_element;
std::optional<TextElement> FindMatchingCommand(uint8_t b) {
for (const auto& text_element : TextCommands) {
if (text_element.ID == b) {
return text_element;
}
}
return empty_element;
return std::nullopt;
}
TextElement FindMatchingSpecial(uint8_t value) {
auto it = std::find_if(SpecialChars.begin(), SpecialChars.end(),
[value](const TextElement& text_element) {
return text_element.ID == value;
});
std::optional<TextElement> FindMatchingSpecial(uint8_t value) {
auto it = std::ranges::find_if(SpecialChars,
[value](const TextElement& text_element) {
return text_element.ID == value;
});
if (it != SpecialChars.end()) {
return *it;
}
return TextElement();
return std::nullopt;
}
ParsedElement FindMatchingElement(const std::string& str) {
std::smatch match;
for (auto& textElement : TextCommands) {
match = textElement.MatchMe(str);
std::vector<TextElement> commands_and_chars = TextCommands;
commands_and_chars.insert(commands_and_chars.end(), SpecialChars.begin(),
SpecialChars.end());
for (auto& text_element : commands_and_chars) {
match = text_element.MatchMe(str);
if (match.size() > 0) {
if (textElement.HasArgument) {
return ParsedElement(textElement,
std::stoi(match[1].str(), nullptr, 16));
if (text_element.HasArgument) {
std::string arg = match[1].str().substr(1);
return ParsedElement(text_element, std::stoi(arg, nullptr, 16));
} else {
return ParsedElement(textElement, 0);
return ParsedElement(text_element, 0);
}
}
}
@@ -77,21 +83,21 @@ std::string ParseTextDataByte(uint8_t value) {
}
// Check for command.
TextElement textElement = FindMatchingCommand(value);
if (!textElement.Empty()) {
return textElement.GenericToken;
if (auto text_element = FindMatchingCommand(value);
text_element != std::nullopt) {
return text_element->GenericToken;
}
// Check for special characters.
textElement = FindMatchingSpecial(value);
if (!textElement.Empty()) {
return textElement.GenericToken;
if (auto special_element = FindMatchingSpecial(value);
special_element != std::nullopt) {
return special_element->GenericToken;
}
// Check for dictionary.
int dictionary = FindDictionaryEntry(value);
if (dictionary >= 0) {
return absl::StrFormat("[%s:%X]", DICTIONARYTOKEN, dictionary);
return absl::StrFormat("[%s:%02X]", DICTIONARYTOKEN, dictionary);
}
return "";
@@ -101,7 +107,6 @@ std::vector<uint8_t> ParseMessageToData(std::string str) {
std::vector<uint8_t> bytes;
std::string temp_string = str;
int pos = 0;
while (pos < temp_string.size()) {
// Get next text fragment.
if (temp_string[pos] == '[') {
@@ -117,7 +122,7 @@ std::vector<uint8_t> ParseMessageToData(std::string str) {
TextElement(0x80, DICTIONARYTOKEN, true, "Dictionary");
if (!parsedElement.Active) {
core::logf("Error parsing message: %s", temp_string);
util::logf("Error parsing message: %s", temp_string);
break;
} else if (parsedElement.Parent == dictionary_element) {
bytes.push_back(parsedElement.Value);
@@ -135,7 +140,6 @@ std::vector<uint8_t> ParseMessageToData(std::string str) {
uint8_t bb = FindMatchingCharacter(temp_string[pos++]);
if (bb != 0xFF) {
core::logf("Error parsing message: %s", temp_string);
bytes.push_back(bb);
}
}
@@ -150,14 +154,14 @@ std::vector<DictionaryEntry> BuildDictionaryEntries(Rom* rom) {
std::vector<uint8_t> bytes;
std::stringstream stringBuilder;
int address = core::SnesToPc(
int address = SnesToPc(
kTextData + (rom->data()[kPointersDictionaries + (i * 2) + 1] << 8) +
rom->data()[kPointersDictionaries + (i * 2)]);
int temppush_backress = core::SnesToPc(
kTextData +
(rom->data()[kPointersDictionaries + ((i + 1) * 2) + 1] << 8) +
rom->data()[kPointersDictionaries + ((i + 1) * 2)]);
int temppush_backress =
SnesToPc(kTextData +
(rom->data()[kPointersDictionaries + ((i + 1) * 2) + 1] << 8) +
rom->data()[kPointersDictionaries + ((i + 1) * 2)]);
while (address < temppush_backress) {
uint8_t uint8_tDictionary = rom->data()[address++];
@@ -168,13 +172,271 @@ std::vector<DictionaryEntry> BuildDictionaryEntries(Rom* rom) {
AllDictionaries.push_back(DictionaryEntry{(uint8_t)i, stringBuilder.str()});
}
std::sort(AllDictionaries.begin(), AllDictionaries.end(),
[](const DictionaryEntry& a, const DictionaryEntry& b) {
return a.Contents.size() > b.Contents.size();
});
std::ranges::sort(AllDictionaries,
[](const DictionaryEntry& a, const DictionaryEntry& b) {
return a.Contents.size() > b.Contents.size();
});
return AllDictionaries;
}
std::string ReplaceAllDictionaryWords(std::string str,
std::vector<DictionaryEntry> dictionary) {
std::string temp = str;
for (const auto& entry : dictionary) {
if (entry.ContainedInString(temp)) {
temp = entry.ReplaceInstancesOfIn(temp);
}
}
return temp;
}
DictionaryEntry FindRealDictionaryEntry(
uint8_t value, std::vector<DictionaryEntry> dictionary) {
for (const auto& entry : dictionary) {
if (entry.ID + DICTOFF == value) {
return entry;
}
}
return DictionaryEntry();
}
absl::StatusOr<MessageData> ParseSingleMessage(
const std::vector<uint8_t>& rom_data, int* current_pos) {
MessageData message_data;
int pos = *current_pos;
uint8_t current_byte;
std::vector<uint8_t> temp_bytes_raw;
std::vector<uint8_t> temp_bytes_parsed;
std::string current_message_raw;
std::string current_message_parsed;
// Read the message data
while (true) {
current_byte = rom_data[pos++];
if (current_byte == kMessageTerminator) {
message_data.ID = message_data.ID + 1;
message_data.Address = pos;
message_data.RawString = current_message_raw;
message_data.Data = temp_bytes_raw;
message_data.DataParsed = temp_bytes_parsed;
message_data.ContentsParsed = current_message_parsed;
temp_bytes_raw.clear();
temp_bytes_parsed.clear();
current_message_raw.clear();
current_message_parsed.clear();
break;
} else if (current_byte == 0xFF) {
break;
}
temp_bytes_raw.push_back(current_byte);
// Check for command.
auto text_element = FindMatchingCommand(current_byte);
if (text_element != std::nullopt) {
current_message_raw.append(text_element->GetParamToken());
current_message_parsed.append(text_element->GetParamToken());
temp_bytes_parsed.push_back(current_byte);
continue;
}
// Check for dictionary.
int dictionary = FindDictionaryEntry(current_byte);
if (dictionary >= 0) {
current_message_raw.append("[");
current_message_raw.append(DICTIONARYTOKEN);
current_message_raw.append(":");
current_message_raw.append(util::HexWord(dictionary));
current_message_raw.append("]");
auto mutable_rom_data = const_cast<uint8_t*>(rom_data.data());
uint32_t address = Get24LocalFromPC(
mutable_rom_data, kPointersDictionaries + (dictionary * 2));
uint32_t address_end = Get24LocalFromPC(
mutable_rom_data, kPointersDictionaries + ((dictionary + 1) * 2));
for (uint32_t i = address; i < address_end; i++) {
temp_bytes_parsed.push_back(rom_data[i]);
current_message_parsed.append(ParseTextDataByte(rom_data[i]));
}
continue;
}
// Everything else.
if (CharEncoder.contains(current_byte)) {
std::string str = "";
str.push_back(CharEncoder.at(current_byte));
current_message_raw.append(str);
current_message_parsed.append(str);
temp_bytes_parsed.push_back(current_byte);
}
}
*current_pos = pos;
return message_data;
}
std::vector<std::string> ParseMessageData(
std::vector<MessageData>& message_data,
const std::vector<DictionaryEntry>& dictionary_entries) {
std::vector<std::string> parsed_messages;
for (auto& message : message_data) {
std::string parsed_message = "";
int pos = 0;
for (const uint8_t& byte : message.Data) {
if (CharEncoder.contains(byte)) {
parsed_message.push_back(CharEncoder.at(byte));
} else {
if (byte >= DICTOFF && byte < (DICTOFF + 97)) {
DictionaryEntry dic_entry;
for (const auto& entry : dictionary_entries) {
if (entry.ID == byte - DICTOFF) {
dic_entry = entry;
break;
}
}
parsed_message.append(dic_entry.Contents);
} else {
auto text_element = FindMatchingCommand(byte);
if (text_element != std::nullopt) {
if (text_element->ID == kScrollVertical ||
text_element->ID == kLine2 || text_element->ID == kLine3) {
parsed_message.append("\n");
}
// If there is a param, add it to the message using GetParamToken.
if (text_element->HasArgument) {
// The next byte is the param.
parsed_message.append(
text_element->GetParamToken(message.Data[pos + 1]));
pos++;
} else {
parsed_message.append(text_element->GetParamToken());
}
}
auto special_element = FindMatchingSpecial(byte);
if (special_element != std::nullopt) {
parsed_message.append(special_element->GetParamToken());
}
}
}
pos++;
}
parsed_messages.push_back(parsed_message);
}
return parsed_messages;
}
std::vector<MessageData> ReadAllTextData(uint8_t* rom, int pos) {
std::vector<MessageData> list_of_texts;
int message_id = 0;
std::vector<uint8_t> raw_message;
std::vector<uint8_t> parsed_message;
std::string current_raw_message;
std::string current_parsed_message;
uint8_t current_byte = 0;
while (current_byte != 0xFF) {
current_byte = rom[pos++];
if (current_byte == kMessageTerminator) {
list_of_texts.push_back(
MessageData(message_id++, pos, current_raw_message, raw_message,
current_parsed_message, parsed_message));
raw_message.clear();
parsed_message.clear();
current_raw_message.clear();
current_parsed_message.clear();
continue;
} else if (current_byte == 0xFF) {
break;
}
raw_message.push_back(current_byte);
auto text_element = FindMatchingCommand(current_byte);
if (text_element != std::nullopt) {
parsed_message.push_back(current_byte);
if (text_element->HasArgument) {
current_byte = rom[pos++];
raw_message.push_back(current_byte);
parsed_message.push_back(current_byte);
}
current_raw_message.append(text_element->GetParamToken(current_byte));
current_parsed_message.append(text_element->GetParamToken(current_byte));
if (text_element->Token == kBankToken) {
pos = kTextData2;
}
continue;
}
// Check for special characters.
auto special_element = FindMatchingSpecial(current_byte);
if (special_element != std::nullopt) {
current_raw_message.append(special_element->GetParamToken());
current_parsed_message.append(special_element->GetParamToken());
parsed_message.push_back(current_byte);
continue;
}
// Check for dictionary.
int dictionary = FindDictionaryEntry(current_byte);
if (dictionary >= 0) {
current_raw_message.append(absl::StrFormat("[%s:%s]", DICTIONARYTOKEN,
util::HexByte(dictionary)));
uint32_t address =
Get24LocalFromPC(rom, kPointersDictionaries + (dictionary * 2));
uint32_t address_end =
Get24LocalFromPC(rom, kPointersDictionaries + ((dictionary + 1) * 2));
for (uint32_t i = address; i < address_end; i++) {
parsed_message.push_back(rom[i]);
current_parsed_message.append(ParseTextDataByte(rom[i]));
}
continue;
}
// Everything else.
if (CharEncoder.contains(current_byte)) {
std::string str = "";
str.push_back(CharEncoder.at(current_byte));
current_raw_message.append(str);
current_parsed_message.append(str);
parsed_message.push_back(current_byte);
}
}
return list_of_texts;
}
absl::Status LoadExpandedMessages(std::string& expanded_message_path,
std::vector<std::string>& parsed_messages,
std::vector<MessageData>& expanded_messages,
std::vector<DictionaryEntry>& dictionary) {
static Rom expanded_message_rom;
if (!expanded_message_rom.LoadFromFile(expanded_message_path, false).ok()) {
return absl::InternalError("Failed to load expanded message ROM");
}
expanded_messages = ReadAllTextData(expanded_message_rom.mutable_data(), 0);
auto parsed_expanded_messages =
ParseMessageData(expanded_messages, dictionary);
// Insert into parsed_messages
for (const auto& expanded_message : expanded_messages) {
parsed_messages.push_back(parsed_expanded_messages[expanded_message.ID]);
}
return absl::OkStatus();
}
} // namespace editor
} // namespace yaze
} // namespace yaze