7#include <unordered_map>
10#include "absl/status/status.h"
11#include "absl/strings/str_format.h"
12#include "absl/strings/str_replace.h"
13#include "absl/strings/str_split.h"
30using ImGui::BeginChild;
31using ImGui::BeginTable;
35using ImGui::InputText;
36using ImGui::InputTextMultiline;
38using ImGui::Separator;
39using ImGui::TableHeadersRow;
40using ImGui::TableNextColumn;
41using ImGui::TableSetupColumn;
43using ImGui::TextWrapped;
58 std::vector<uint8_t> data(0x4000, 0);
59 for (
int i = 0; i < 0x4000; i++) {
89 std::string parsed_message =
"";
90 for (
const auto&
byte : each_message.Data) {
92 if (CharEncoder.contains(
byte)) {
93 parsed_message.push_back(CharEncoder.at(
byte));
100 parsed_message.append(dictionaryEntry.Contents);
104 if (!textElement.
Empty()) {
108 parsed_message.append(
"\n");
120 return absl::OkStatus();
130 if (BeginTable(
"##MessageEditor", 4,
131 ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable)) {
132 TableSetupColumn(
"List");
133 TableSetupColumn(
"Contents");
134 TableSetupColumn(
"Commands");
135 TableSetupColumn(
"Dictionary");
149 if (ImGui::BeginChild(
"##DictionaryChild", ImVec2(0, 0),
true,
150 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
151 if (BeginTable(
"##Dictionary", 2,
152 ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable)) {
153 TableSetupColumn(
"ID");
154 TableSetupColumn(
"Contents");
160 Text(
"%s", dictionary.Contents.c_str());
171 return absl::OkStatus();
179 if (BeginChild(
"##MessagesList", ImVec2(0, 0),
true,
180 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
181 if (BeginTable(
"##MessagesTable", 3,
182 ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders |
183 ImGuiTableFlags_Resizable)) {
184 TableSetupColumn(
"ID");
185 TableSetupColumn(
"Contents");
186 TableSetupColumn(
"Data");
212 if (InputTextMultiline(
"##MessageEditor",
214 ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
220 Text(
"Font Graphics");
222 BeginChild(
"MessageEditorCanvas", ImVec2(0, 130));
232 Text(
"Message Preview");
233 if (Button(
"Refresh Bitmap")) {
237 BeginChild(
"CurrentGfxFont", ImVec2(0, 0),
true,
238 ImGuiWindowFlags_AlwaysVerticalScrollbar);
249 if (BeginChild(
"##TextCommands", ImVec2(0, 0),
true,
250 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
251 for (
const auto& text_element : TextCommands) {
252 if (Button(text_element.GenericToken.c_str())) {
255 TextWrapped(
"%s", text_element.Description.c_str());
269 std::vector<uint8_t> raw_message;
270 std::vector<uint8_t> parsed_message;
272 std::string current_raw_message;
273 std::string current_parsed_message;
275 uint8_t current_byte = 0;
276 while (current_byte != 0xFF) {
277 current_byte =
rom()->data()[pos++];
280 MessageData(message_id++, pos, current_raw_message, raw_message,
281 current_parsed_message, parsed_message);
286 parsed_message.clear();
287 current_raw_message.clear();
288 current_parsed_message.clear();
293 raw_message.push_back(current_byte);
297 if (!text_element.
Empty()) {
299 parsed_message.push_back(current_byte);
301 current_byte =
rom()->data()[pos++];
302 raw_message.push_back(current_byte);
303 parsed_message.push_back(current_byte);
306 current_raw_message.append(
308 current_parsed_message.append(
320 if (!text_element.
Empty()) {
323 parsed_message.push_back(current_byte);
329 if (dictionary >= 0) {
330 current_raw_message.append(
"[");
332 current_raw_message.append(
":");
334 current_raw_message.append(
"]");
341 for (uint32_t i = address; i < address_end; i++) {
342 parsed_message.push_back(
rom()->data()[i]);
350 if (CharEncoder.contains(current_byte)) {
351 std::string str =
"";
352 str.push_back(CharEncoder.at(current_byte));
353 current_raw_message.append(str);
354 current_parsed_message.append(str);
355 parsed_message.push_back(current_byte);
363 uint8_t current_byte;
364 std::vector<uint8_t> temp_bytes_raw;
365 std::vector<uint8_t> temp_bytes_parsed;
367 std::string current_message_raw;
368 std::string current_message_parsed;
372 current_byte =
rom()->data()[pos++];
376 MessageData(message_id++, pos, current_message_raw, temp_bytes_raw,
377 current_message_parsed, temp_bytes_parsed);
381 temp_bytes_raw.clear();
382 temp_bytes_parsed.clear();
383 current_message_raw.clear();
384 current_message_parsed.clear();
387 }
else if (current_byte == 0xFF) {
391 temp_bytes_raw.push_back(current_byte);
396 if (!text_element.
Empty()) {
397 temp_bytes_parsed.push_back(current_byte);
399 current_byte =
rom()->data()[pos++];
400 temp_bytes_raw.push_back(current_byte);
401 temp_bytes_parsed.push_back(current_byte);
404 current_message_raw.append(
406 current_message_parsed.append(
418 if (!text_element.
Empty()) {
421 temp_bytes_parsed.push_back(current_byte);
428 if (dictionary >= 0) {
429 current_message_raw.append(
"[");
431 current_message_raw.append(
":");
433 current_message_raw.append(
"]");
440 for (uint32_t i = address; i < address_end; i++) {
441 temp_bytes_parsed.push_back(
rom()->data()[i]);
449 if (CharEncoder.contains(current_byte)) {
450 std::string str =
"";
451 str.push_back(CharEncoder.at(current_byte));
452 current_message_raw.append(str);
453 current_message_parsed.append(str);
454 temp_bytes_parsed.push_back(current_byte);
460 std::vector<DictionaryEntry> dictionary) {
461 std::string temp = str;
462 for (
const auto& entry : dictionary) {
463 if (absl::StrContains(temp, entry.Contents)) {
464 temp = absl::StrReplaceAll(temp, {{entry.Contents, entry.Contents}});
478 int sizex,
int sizey) {
479 int drawid = srcx + (srcy * 32);
480 for (
int yl = 0; yl < sizey * 8; yl++) {
481 for (
int xl = 0; xl < 4; xl++) {
487 int tx = ((drawid / 16) * 512) + ((drawid - ((drawid / 16) * 16)) * 4);
492 int index = x + (y * 172) + (mx * 2) + (my * 172);
493 if ((pixel & 0x0F) != 0) {
495 (uint8_t)((pixel & 0x0F) + (0 * 4));
498 if (((pixel >> 4) & 0x0F) != 0) {
500 (uint8_t)(((pixel >> 4) & 0x0F) + (0 * 4));
507 for (
const auto c : str) {
517 for (
const uint8_t& value : text) {
524 int srcy = value / 16;
525 int srcx = value - (value & (~0xF));
534 }
else if (value ==
kLine1) {
540 }
else if (value ==
kLine2) {
543 }
else if (value ==
kLine3) {
546 }
else if (value == 0x6B || value == 0x6D || value == 0x6E ||
547 value == 0x77 || value == 0x78 || value == 0x79 ||
552 }
else if (value == 0x6C)
558 }
else if (value == 0x6A) {
572 for (
int i = 0; i < (172 * 4096); i++) {
586 return absl::OkStatus();
591 if (ImGui::GetClipboardText() !=
nullptr) {
595 return absl::OkStatus();
604 return absl::OkStatus();
616 return absl::OkStatus();
620 std::vector<uint8_t> backup =
rom()->vector();
622 for (
int i = 0; i < 100; i++) {
627 bool in_second_bank =
false;
630 for (
const auto value : message.Data) {
642 in_second_bank =
true;
661 return absl::OkStatus();
666 std::string bankSTR = bank ?
"1st" :
"2nd";
668 bank ? absl::StrFormat(
"%X4", pos & 0xFFFF)
669 : absl::StrFormat(
"%X4", (pos -
kTextData2) & 0xFFFF);
670 std::string message = absl::StrFormat(
671 "There is too much text data in the %s block to save.\n"
672 "Available: %X4 | Used: %s",
673 bankSTR, space, posSTR);
static Renderer & GetInstance()
void UpdateBitmap(gfx::Bitmap *bitmap, bool use_sdl_update=false)
Used to update a bitmap on the screen.
DictionaryEntry GetDictionaryFromID(uint8_t value)
gui::Canvas font_gfx_canvas_
void DrawTileToPreview(int x, int y, int srcx, int srcy, int pal, int sizex=1, int sizey=1)
void DrawCurrentMessage()
absl::Status Paste() override
std::string DisplayTextOverflowError(int pos, bool bank)
std::vector< std::string > parsed_messages_
void DrawCharacterToPreview(char c)
std::vector< uint8_t > current_font_gfx16_data_
absl::Status Copy() override
MessageData current_message_
TextBox message_text_box_
void DrawMessagePreview()
absl::Status Cut() override
gfx::Bitmap font_gfx_bitmap_
gfx::SnesPalette font_preview_colors_
gfx::Bitmap current_font_gfx16_bitmap_
absl::Status Update() override
absl::Status Initialize()
std::vector< MessageData > list_of_texts_
std::vector< uint8_t > font_gfx16_data_
gui::Canvas current_font_gfx16_canvas_
std::vector< DictionaryEntry > all_dictionaries_
void DrawStringToPreview(std::string str)
uint8_t width_array[kWidthArraySize]
absl::Status Undo() override
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
void AddColor(const SnesColor &color)
auto mutable_color(int i)
void DrawBackground(ImVec2 canvas_size=ImVec2(0, 0), bool drag=false)
void DrawGrid(float grid_step=64.0f, int tile_id_offset=8)
void DrawBitmap(const Bitmap &bitmap, int border_offset=0, bool ready=true)
void DrawContextMenu(gfx::Bitmap *bitmap=nullptr)
#define RETURN_IF_ERROR(expression)
std::string UppercaseHexWord(uint16_t word)
uint32_t Get24LocalFromPC(uint8_t *data, int addr, bool pc)
std::string UppercaseHexLong(uint32_t dword)
const std::string DICTIONARYTOKEN
uint8_t FindDictionaryEntry(uint8_t value)
constexpr uint8_t DICTOFF
constexpr int kPointersDictionaries
constexpr int kTextDataEnd
constexpr int kCurrentMessageHeight
std::vector< DictionaryEntry > BuildDictionaryEntries(app::Rom *rom)
constexpr uint8_t kWidthArraySize
const uint8_t kMessageTerminator
const std::string BANKToken
uint8_t FindMatchingCharacter(char value)
constexpr int kCurrentMessageWidth
TextElement FindMatchingSpecial(uint8_t value)
constexpr int kTextData2End
constexpr uint8_t kBlockTerminator
TextElement FindMatchingCommand(uint8_t b)
constexpr int kCharactersWidth
std::vector< uint8_t > ParseMessageToData(std::string str)
std::string ParseTextDataByte(uint8_t value)
constexpr uint8_t kScrollVertical
std::string ReplaceAllDictionaryWords(std::string str, std::vector< DictionaryEntry > dictionary)
std::vector< uint8_t > SnesTo8bppSheet(const std::vector< uint8_t > &sheet, int bpp)
std::vector< uint8_t > Data
std::string GetParameterizedToken(uint8_t value=0)