From aed54f14932d9df4467cad8187b368182a5442b0 Mon Sep 17 00:00:00 2001 From: scawful Date: Sat, 3 Feb 2024 00:04:21 -0500 Subject: [PATCH] fix hyrule magic decompression memory leak, misc housekeeping --- src/app/editor/master_editor.cc | 6 +++- src/app/editor/modules/gfx_group_editor.cc | 2 +- src/app/editor/overworld_editor.cc | 42 +++++++++++++++++----- src/app/gfx/bitmap.h | 10 +++--- src/app/gfx/snes_palette.h | 2 ++ src/app/gui/canvas.cc | 2 ++ src/app/gui/canvas.h | 2 ++ src/app/zelda3/overworld.cc | 2 ++ src/app/zelda3/overworld.h | 4 +++ src/app/zelda3/overworld_map.cc | 4 +-- 10 files changed, 58 insertions(+), 18 deletions(-) diff --git a/src/app/editor/master_editor.cc b/src/app/editor/master_editor.cc index 1b441359..6f8abd48 100644 --- a/src/app/editor/master_editor.cc +++ b/src/app/editor/master_editor.cc @@ -338,7 +338,11 @@ void MasterEditor::DrawFileMenu() { ImGui::EndMenu(); } - MENU_ITEM2("Save", "Ctrl+S") { SaveRom(); } + MENU_ITEM2("Save", "Ctrl+S") { + if (rom()->is_loaded()) { + SaveRom(); + } + } MENU_ITEM("Save As..") { save_as_menu = true; } if (rom()->is_loaded()) { diff --git a/src/app/editor/modules/gfx_group_editor.cc b/src/app/editor/modules/gfx_group_editor.cc index 3e6ae604..0ef738eb 100644 --- a/src/app/editor/modules/gfx_group_editor.cc +++ b/src/app/editor/modules/gfx_group_editor.cc @@ -194,7 +194,7 @@ void DrawPaletteFromPaletteGroup(gfx::SnesPalette &palette) { auto popup_id = absl::StrCat("Palette", n); // Small icon of the color in the palette - if (gui::SNESColorButton(popup_id, palette[n], + if (gui::SnesColorButton(popup_id, palette[n], ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip)) { diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index 93cc55dd..422395db 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -486,8 +486,8 @@ void OverworldEditor::DrawOverworldMaps() { void OverworldEditor::DrawOverworldEdits() { // Determine which overworld map the user is currently editing. - auto mouse_position = ow_map_canvas_.drawn_tile_position(); constexpr int small_map_size = 512; + auto mouse_position = ow_map_canvas_.drawn_tile_position(); int map_x = mouse_position.x / small_map_size; int map_y = mouse_position.y / small_map_size; current_map_ = map_x + map_y * 8; @@ -780,8 +780,9 @@ void OverworldEditor::DrawAreaGraphics() { overworld_.set_current_map(current_map_); palette_ = overworld_.AreaPalette(); gfx::Bitmap bmp; - gui::BuildAndRenderBitmapPipeline( - 0x80, 0x200, 0x08, overworld_.current_graphics(), *rom(), bmp, palette_); + gui::BuildAndRenderBitmapPipeline(0x80, 0x200, 0x08, + overworld_.current_graphics(), *rom(), + bmp, palette_); current_graphics_set_[current_map_] = bmp; } } @@ -915,12 +916,17 @@ void HandleEntityDragging(zelda3::OverworldEntity *entity, ImVec2 canvas_p0, namespace entrance_internal { -void DrawEntranceInserterPopup() { +bool DrawEntranceInserterPopup() { + bool set_done = false; + if (set_done) { + set_done = false; + } if (ImGui::BeginPopup("Entrance Inserter")) { static int entrance_id = 0; gui::InputHex("Entrance ID", &entrance_id); if (ImGui::Button(ICON_MD_DONE)) { + set_done = true; ImGui::CloseCurrentPopup(); } @@ -931,6 +937,7 @@ void DrawEntranceInserterPopup() { ImGui::EndPopup(); } + return set_done; } bool DrawOverworldEntrancePopup(zelda3::OverworldEntrance &entrance) { @@ -949,12 +956,16 @@ bool DrawOverworldEntrancePopup(zelda3::OverworldEntrance &entrance) { if (ImGui::Button(ICON_MD_DONE)) { ImGui::CloseCurrentPopup(); } - ImGui::SameLine(); if (ImGui::Button(ICON_MD_CANCEL)) { set_done = true; ImGui::CloseCurrentPopup(); } + ImGui::SameLine(); + if (ImGui::Button(ICON_MD_DELETE)) { + entrance.deleted = true; + ImGui::CloseCurrentPopup(); + } ImGui::EndPopup(); } return set_done; @@ -973,9 +984,6 @@ void OverworldEditor::DrawOverworldEntrances(ImVec2 canvas_p0, ImVec2 scrolling, if (each.is_hole_) { color = ImVec4(255, 255, 255, 200); } - if (each.deleted) { - color = ImVec4(0, 0, 0, 0); - } ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16, color); std::string str = core::UppercaseHexByte(each.entrance_id_); @@ -1003,7 +1011,18 @@ void OverworldEditor::DrawOverworldEntrances(ImVec2 canvas_p0, ImVec2 scrolling, i++; } - entrance_internal::DrawEntranceInserterPopup(); + if (entrance_internal::DrawEntranceInserterPopup()) { + // Get the deleted entrance ID and insert it at the mouse position + auto deleted_entrance_id = overworld_.deleted_entrances().back(); + overworld_.deleted_entrances().pop_back(); + auto &entrance = overworld_.entrances()[deleted_entrance_id]; + entrance.map_id_ = current_map_; + entrance.entrance_id_ = deleted_entrance_id; + entrance.x_ = ow_map_canvas_.hover_mouse_pos().x; + entrance.y_ = ow_map_canvas_.hover_mouse_pos().y; + entrance.deleted = false; + } + if (current_mode == EditingMode::ENTRANCES) { const auto is_hovering = entity_internal::IsMouseHoveringOverEntity( current_entrance_, canvas_p0, scrolling); @@ -1015,6 +1034,11 @@ void OverworldEditor::DrawOverworldEntrances(ImVec2 canvas_p0, ImVec2 scrolling, overworld_.entrances()[current_entrance_id_])) { overworld_.entrances()[current_entrance_id_] = current_entrance_; } + + if (overworld_.entrances()[current_entrance_id_].deleted) { + overworld_.mutable_deleted_entrances()->emplace_back( + current_entrance_id_); + } } } } diff --git a/src/app/gfx/bitmap.h b/src/app/gfx/bitmap.h index fae07e3a..ede665c1 100644 --- a/src/app/gfx/bitmap.h +++ b/src/app/gfx/bitmap.h @@ -72,13 +72,13 @@ class Bitmap { void Get8x8Tile(int tile_index, int x, int y, std::vector &tile_data, int &tile_data_offset) { - int tile_offset = tile_index * 64; - int tile_x = x * 8; - int tile_y = y * 8; + int tile_offset = tile_index * (width_ * height_); + int tile_x = (x * 8) % width_; + int tile_y = (y * 8) % height_; for (int i = 0; i < 8; i++) { - int row_offset = tile_offset + (i * 8); + int row_offset = tile_offset + ((tile_y + i) * width_); for (int j = 0; j < 8; j++) { - int pixel_offset = row_offset + j; + int pixel_offset = row_offset + (tile_x + j); int pixel_value = data_[pixel_offset]; tile_data[tile_data_offset] = pixel_value; tile_data_offset++; diff --git a/src/app/gfx/snes_palette.h b/src/app/gfx/snes_palette.h index 359f784d..22ae861a 100644 --- a/src/app/gfx/snes_palette.h +++ b/src/app/gfx/snes_palette.h @@ -77,6 +77,8 @@ class SnesPalette { return colors[i]; } + auto mutable_color(int i) { return &colors[i]; } + void Clear() { colors.clear(); size_ = 0; diff --git a/src/app/gui/canvas.cc b/src/app/gui/canvas.cc index e63ae1ba..07cbab49 100644 --- a/src/app/gui/canvas.cc +++ b/src/app/gui/canvas.cc @@ -173,6 +173,8 @@ bool Canvas::DrawTilePainter(const Bitmap &bitmap, int size, float scale) { painter_pos.y = std::floor((double)mouse_pos.y / (size * scale)) * (size * scale); + mouse_pos_in_canvas_ = painter_pos; + auto painter_pos_end = ImVec2(painter_pos.x + (size * scale), painter_pos.y + (size * scale)); points_.push_back(painter_pos); diff --git a/src/app/gui/canvas.h b/src/app/gui/canvas.h index af6f796c..0ae29bc3 100644 --- a/src/app/gui/canvas.h +++ b/src/app/gui/canvas.h @@ -163,6 +163,8 @@ class Canvas { bool select_rect_active() const { return select_rect_active_; } auto selected_points() const { return selected_points_; } + auto hover_mouse_pos() const { return mouse_pos_in_canvas_; } + private: bool draggable_ = false; bool enable_grid_ = true; diff --git a/src/app/zelda3/overworld.cc b/src/app/zelda3/overworld.cc index bc74cae6..08c91541 100644 --- a/src/app/zelda3/overworld.cc +++ b/src/app/zelda3/overworld.cc @@ -275,11 +275,13 @@ absl::Status Overworld::DecompressAllMapTiles() { for (int i = 0; i < size1; i++) { bytes[i] = decomp[i]; } + free(decomp); decomp = gfx::lc_lz2::Uncompress(rom()->data() + p1, &size2, 1); bytes2.resize(size2); for (int i = 0; i < size2; i++) { bytes2[i] = decomp[i]; } + free(decomp); OrganizeMapTiles(bytes, bytes2, i, sx, sy, ttpos); diff --git a/src/app/zelda3/overworld.h b/src/app/zelda3/overworld.h index c412ba03..5d77eb30 100644 --- a/src/app/zelda3/overworld.h +++ b/src/app/zelda3/overworld.h @@ -535,6 +535,8 @@ class Overworld : public SharedROM, public core::ExperimentFlags { auto mutable_entrances() { return &all_entrances_; } auto &holes() { return all_holes_; } auto mutable_holes() { return &all_holes_; } + auto deleted_entrances() const { return deleted_entrances_; } + auto mutable_deleted_entrances() { return &deleted_entrances_; } auto AreaPalette() const { return overworld_maps_[current_map_].current_palette(); } @@ -599,6 +601,8 @@ class Overworld : public SharedROM, public core::ExperimentFlags { std::vector all_items_; std::vector> all_sprites_; + std::vector deleted_entrances_; + std::vector> map_data_p1 = std::vector>(kNumOverworldMaps); std::vector> map_data_p2 = diff --git a/src/app/zelda3/overworld_map.cc b/src/app/zelda3/overworld_map.cc index c54ee5a5..4ca2c146 100644 --- a/src/app/zelda3/overworld_map.cc +++ b/src/app/zelda3/overworld_map.cc @@ -65,6 +65,8 @@ void OverworldMap::LoadAreaInfo() { } } + message_id_ = rom_.toint16(overworldMessages + (parent_ * 2)); + if (index_ < 0x40) { area_graphics_ = rom_[mapGfx + parent_]; area_palette_ = rom_[overworldMapPalette + parent_]; @@ -117,8 +119,6 @@ void OverworldMap::LoadAreaInfo() { parent_ = 129; } - message_id_ = rom_[overworldMessages + parent_]; - area_palette_ = rom_[overworldSpecialPALGroup + parent_ - 0x80]; if ((index_ >= 0x80 && index_ <= 0x8A && index_ != 0x88) || index_ == 0x94) {