diff --git a/src/app/editor/message/message_data.cc b/src/app/editor/message/message_data.cc index abcd6150..e90538d6 100644 --- a/src/app/editor/message/message_data.cc +++ b/src/app/editor/message/message_data.cc @@ -329,9 +329,8 @@ std::vector ParseMessageData( return parsed_messages; } -void ReadAllTextData(Rom *rom, std::vector &list_of_texts_) { - // Read all text data from the ROM. - int pos = kTextData; +std::vector ReadAllTextData(uint8_t *rom, int pos) { + std::vector list_of_texts; int message_id = 0; std::vector raw_message; @@ -341,9 +340,9 @@ void ReadAllTextData(Rom *rom, std::vector &list_of_texts_) { uint8_t current_byte = 0; while (current_byte != 0xFF) { - current_byte = rom->data()[pos++]; + current_byte = rom[pos++]; if (current_byte == kMessageTerminator) { - list_of_texts_.push_back( + list_of_texts.push_back( MessageData(message_id++, pos, current_raw_message, raw_message, current_parsed_message, parsed_message)); raw_message.clear(); @@ -361,7 +360,7 @@ void ReadAllTextData(Rom *rom, std::vector &list_of_texts_) { if (text_element != std::nullopt) { parsed_message.push_back(current_byte); if (text_element->HasArgument) { - current_byte = rom->data()[pos++]; + current_byte = rom[pos++]; raw_message.push_back(current_byte); parsed_message.push_back(current_byte); } @@ -391,14 +390,14 @@ void ReadAllTextData(Rom *rom, std::vector &list_of_texts_) { current_raw_message.append(absl::StrFormat("[%s:%s]", DICTIONARYTOKEN, util::HexByte(dictionary))); - uint32_t address = Get24LocalFromPC( - rom->mutable_data(), kPointersDictionaries + (dictionary * 2)); - uint32_t address_end = Get24LocalFromPC( - rom->mutable_data(), kPointersDictionaries + ((dictionary + 1) * 2)); + 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->data()[i]); - current_parsed_message.append(ParseTextDataByte(rom->data()[i])); + parsed_message.push_back(rom[i]); + current_parsed_message.append(ParseTextDataByte(rom[i])); } continue; @@ -413,6 +412,8 @@ void ReadAllTextData(Rom *rom, std::vector &list_of_texts_) { parsed_message.push_back(current_byte); } } + + return list_of_texts; } } // namespace editor diff --git a/src/app/editor/message/message_data.h b/src/app/editor/message/message_data.h index 43abd090..6df29fd5 100644 --- a/src/app/editor/message/message_data.h +++ b/src/app/editor/message/message_data.h @@ -310,7 +310,7 @@ constexpr int kTextData2 = 0x75F40; constexpr int kTextData2End = 0x773FF; // Reads all text data from the ROM and returns a vector of MessageData objects. -void ReadAllTextData(Rom *rom, std::vector &list_of_texts_); +std::vector ReadAllTextData(uint8_t *rom, int pos = kTextData); } // namespace editor } // namespace yaze diff --git a/src/app/editor/message/message_editor.cc b/src/app/editor/message/message_editor.cc index 0c3f964c..baba2975 100644 --- a/src/app/editor/message/message_editor.cc +++ b/src/app/editor/message/message_editor.cc @@ -21,6 +21,21 @@ namespace yaze { namespace editor { +namespace { +std::string DisplayTextOverflowError(int pos, bool bank) { + int space = bank ? kTextDataEnd - kTextData : kTextData2End - kTextData2; + std::string bankSTR = bank ? "1st" : "2nd"; + std::string posSTR = + bank ? absl::StrFormat("%X4", pos & 0xFFFF) + : absl::StrFormat("%X4", (pos - kTextData2) & 0xFFFF); + std::string message = absl::StrFormat( + "There is too much text data in the %s block to save.\n" + "Available: %X4 | Used: %s", + bankSTR, space, posSTR); + return message; +} +} // namespace + using core::Renderer; using ImGui::BeginChild; @@ -49,7 +64,7 @@ void MessageEditor::Initialize() { } message_preview_.all_dictionaries_ = BuildDictionaryEntries(rom()); - ReadAllTextData(rom(), list_of_texts_); + list_of_texts_ = ReadAllTextData(rom()->mutable_data()); font_preview_colors_ = rom()->palette_group().hud.palette(0); for (int i = 0; i < 0x4000; i++) { @@ -102,7 +117,6 @@ absl::Status MessageEditor::Update() { EndTable(); } - CLEAR_AND_RETURN_STATUS(status_); return absl::OkStatus(); } @@ -132,6 +146,22 @@ void MessageEditor::DrawMessageList() { TextWrapped("%s", util::HexLong(list_of_texts_[message.ID].Address).c_str()); } + for (const auto& expanded_message : expanded_messages_) { + TableNextColumn(); + PushID(expanded_message.ID + 0x18D); + if (Button(util::HexWord(expanded_message.ID + 0x18D).c_str())) { + current_message_ = expanded_message; + message_text_box_.text = + parsed_messages_[expanded_message.ID + 0x18D]; + DrawMessagePreview(); + } + PopID(); + TableNextColumn(); + TextWrapped("%s", + parsed_messages_[expanded_message.ID + 0x18C].c_str()); + TableNextColumn(); + TextWrapped("%s", util::HexLong(expanded_message.Address).c_str()); + } EndTable(); } @@ -158,7 +188,7 @@ void MessageEditor::DrawCurrentMessage() { ImGui::OpenPopup("Palette"); } if (ImGui::BeginPopup("Palette")) { - status_ = gui::DisplayPalette(font_preview_colors_, true); + gui::DisplayPalette(font_preview_colors_, true); ImGui::EndPopup(); } gui::BeginPadding(1); @@ -211,15 +241,44 @@ void MessageEditor::DrawExpandedMessageSettings() { expanded_message_path = core::FileDialogWrapper::ShowOpenFileDialog(); if (!expanded_message_path.empty()) { // Load the expanded message from the path. - // TODO: Implement this. + static Rom expanded_message_rom; + if (!expanded_message_rom.LoadFromFile(expanded_message_path, false) + .ok()) { + context_->popup_manager->Show("Error"); + } + expanded_messages_ = + ReadAllTextData(expanded_message_rom.mutable_data(), 0); + auto parsed_expanded_messages = ParseMessageData( + expanded_messages_, message_preview_.all_dictionaries_); + // Insert into parsed_messages + for (const auto& expanded_message : expanded_messages_) { + parsed_messages_.push_back( + parsed_expanded_messages[expanded_message.ID]); + } } } + + if (expanded_messages_.size() > 0) { + ImGui::Text("Expanded Path: %s", expanded_message_path.c_str()); + ImGui::Text("Expanded Messages: %lu", expanded_messages_.size()); + if (ImGui::Button("Add New Message")) { + MessageData new_message; + new_message.ID = expanded_messages_.back().ID + 1; + new_message.Address = expanded_messages_.back().Address + + expanded_messages_.back().Data.size(); + expanded_messages_.push_back(new_message); + } + if (ImGui::Button("Save Expanded Messages")) { + PRINT_IF_ERROR(SaveExpandedMessages()); + } + } + EndChild(); } void MessageEditor::DrawTextCommands() { ImGui::BeginChild("##TextCommands", - ImVec2(0, ImGui::GetWindowContentRegionMax().y / 3), true, + ImVec2(0, ImGui::GetContentRegionAvail().y / 2), true, ImGuiWindowFlags_AlwaysVerticalScrollbar); static uint8_t command_parameter = 0; gui::InputHexByte("Command Parameter", &command_parameter); @@ -237,7 +296,7 @@ void MessageEditor::DrawTextCommands() { void MessageEditor::DrawSpecialCharacters() { ImGui::BeginChild("##SpecialChars", - ImVec2(0, ImGui::GetWindowContentRegionMax().y / 3), true, + ImVec2(0, ImGui::GetContentRegionAvail().y / 2), true, ImGuiWindowFlags_AlwaysVerticalScrollbar); for (const auto& text_element : SpecialChars) { if (Button(text_element.GenericToken.c_str())) { @@ -251,7 +310,8 @@ void MessageEditor::DrawSpecialCharacters() { } void MessageEditor::DrawDictionary() { - if (ImGui::BeginChild("##DictionaryChild", ImVec2(0, 200), true, + if (ImGui::BeginChild("##DictionaryChild", + ImVec2(0, ImGui::GetContentRegionAvail().y), true, ImGuiWindowFlags_AlwaysVerticalScrollbar)) { if (BeginTable("##Dictionary", 2, kMessageTableFlags)) { TableSetupColumn("ID"); @@ -319,7 +379,7 @@ absl::Status MessageEditor::Save() { // Verify that we didn't go over the space available for the second block. // 0x14BF available. if ((in_second_bank & pos) > kTextData2End) { - // TODO: Restore the backup. + std::copy(backup.begin(), backup.end(), rom()->mutable_data()); return absl::InternalError(DisplayTextOverflowError(pos, false)); } @@ -328,17 +388,17 @@ absl::Status MessageEditor::Save() { return absl::OkStatus(); } -std::string MessageEditor::DisplayTextOverflowError(int pos, bool bank) { - int space = bank ? kTextDataEnd - kTextData : kTextData2End - kTextData2; - std::string bankSTR = bank ? "1st" : "2nd"; - std::string posSTR = - bank ? absl::StrFormat("%X4", pos & 0xFFFF) - : absl::StrFormat("%X4", (pos - kTextData2) & 0xFFFF); - std::string message = absl::StrFormat( - "There is too much text data in the %s block to save.\n" - "Available: %X4 | Used: %s", - bankSTR, space, posSTR); - return message; +absl::Status MessageEditor::SaveExpandedMessages() { + for (const auto& expanded_message : expanded_messages_) { + std::copy(expanded_message.Data.begin(), expanded_message.Data.end(), + expanded_message_bin_.mutable_data() + expanded_message.Address); + } + RETURN_IF_ERROR(expanded_message_bin_.WriteByte( + expanded_messages_.back().Address + expanded_messages_.back().Data.size(), + 0xFF)); + RETURN_IF_ERROR(expanded_message_bin_.SaveToFile( + Rom::SaveSettings{.backup = true, .save_new = false, .z3_save = false})); + return absl::OkStatus(); } absl::Status MessageEditor::Cut() { diff --git a/src/app/editor/message/message_editor.h b/src/app/editor/message/message_editor.h index af529a04..c852590b 100644 --- a/src/app/editor/message/message_editor.h +++ b/src/app/editor/message/message_editor.h @@ -37,16 +37,6 @@ class MessageEditor : public Editor { absl::Status Load() override; absl::Status Update() override; - absl::Status Cut() override; - absl::Status Copy() override; - absl::Status Paste() override; - absl::Status Undo() override; - absl::Status Redo() override; - absl::Status Find() override; - absl::Status Save() override; - void Delete(); - void SelectAll(); - void DrawMessageList(); void DrawCurrentMessage(); void DrawFontAtlas(); @@ -55,13 +45,23 @@ class MessageEditor : public Editor { void DrawExpandedMessageSettings(); void DrawDictionary(); void DrawMessagePreview(); - std::string DisplayTextOverflowError(int pos, bool bank); + + absl::Status Save() override; + absl::Status SaveExpandedMessages(); + + absl::Status Cut() override; + absl::Status Copy() override; + absl::Status Paste() override; + absl::Status Undo() override; + absl::Status Redo() override; + absl::Status Find() override; + void Delete(); + void SelectAll(); void set_rom(Rom* rom) { rom_ = rom; } Rom* rom() const { return rom_; } private: - Rom* rom_; bool case_sensitive_ = false; bool match_whole_word_ = false; std::string search_text_ = ""; @@ -81,10 +81,9 @@ class MessageEditor : public Editor { gui::Canvas font_gfx_canvas_{"##FontGfxCanvas", ImVec2(256, 256)}; gui::Canvas current_font_gfx16_canvas_{"##CurrentMessageGfx", ImVec2(172 * 2, 4096)}; - gui::TextBox message_text_box_; - - absl::Status status_; + Rom* rom_; + Rom expanded_message_bin_; }; } // namespace editor