diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b01889b7..ed03957d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,6 +28,7 @@ set( app/gfx/scad_format.cc app/gfx/snes_palette.cc app/gfx/snes_tile.cc + app/gfx/snes_color.cc ) set( diff --git a/src/app/editor/dungeon_editor.h b/src/app/editor/dungeon_editor.h index 6216489a..3a6cd7f1 100644 --- a/src/app/editor/dungeon_editor.h +++ b/src/app/editor/dungeon_editor.h @@ -90,8 +90,8 @@ class DungeonEditor : public Editor, GfxGroupEditor gfx_group_editor_; PaletteEditor palette_editor_; - gfx::SNESPalette current_palette_; - gfx::SNESPalette full_palette_; + gfx::SnesPalette current_palette_; + gfx::SnesPalette full_palette_; gfx::PaletteGroup current_palette_group_; gui::Canvas canvas_; diff --git a/src/app/editor/graphics_editor.cc b/src/app/editor/graphics_editor.cc index fa42a7da..847f41a4 100644 --- a/src/app/editor/graphics_editor.cc +++ b/src/app/editor/graphics_editor.cc @@ -540,7 +540,7 @@ absl::Status GraphicsEditor::DrawPaletteControls() { col_file_palette_group_.Clear(); } col_file_palette_group_ = gfx::CreatePaletteGroupFromColFile(col_data_); - col_file_palette_ = gfx::SNESPalette(col_data_); + col_file_palette_ = gfx::SnesPalette(col_data_); // gigaleak dev format based code decoded_col_ = gfx::DecodeColFile(col_file_path_); diff --git a/src/app/editor/graphics_editor.h b/src/app/editor/graphics_editor.h index 028440ad..336bb53b 100644 --- a/src/app/editor/graphics_editor.h +++ b/src/app/editor/graphics_editor.h @@ -176,9 +176,9 @@ class GraphicsEditor : public SharedROM { gfx::BitmapTable clipboard_graphics_bin_; gfx::BitmapTable link_graphics_; gfx::PaletteGroup col_file_palette_group_; - gfx::SNESPalette z3_rom_palette_; - gfx::SNESPalette col_file_palette_; - gfx::SNESPalette link_palette_; + gfx::SnesPalette z3_rom_palette_; + gfx::SnesPalette col_file_palette_; + gfx::SnesPalette link_palette_; gui::Canvas import_canvas_; gui::Canvas scr_canvas_; gui::Canvas super_donkey_canvas_; diff --git a/src/app/editor/modules/gfx_group_editor.cc b/src/app/editor/modules/gfx_group_editor.cc index d9d7201d..3e6ae604 100644 --- a/src/app/editor/modules/gfx_group_editor.cc +++ b/src/app/editor/modules/gfx_group_editor.cc @@ -98,13 +98,13 @@ void GfxGroupEditor::DrawBlocksetViewer(bool sheet_only) { for (int i = 0; i < 8; i++) { int sheet_id = rom()->main_blockset_ids[selected_blockset_][i]; auto &sheet = *rom()->bitmap_manager()[sheet_id]; - if (sheet_id != last_sheet_id_) { - last_sheet_id_ = sheet_id; - auto palette_group = rom()->palette_group("ow_main"); - auto palette = palette_group[preview_palette_id_]; - sheet.ApplyPalette(palette); - rom()->UpdateBitmap(&sheet); - } + // if (sheet_id != last_sheet_id_) { + // last_sheet_id_ = sheet_id; + // auto palette_group = rom()->palette_group("ow_main"); + // auto palette = palette_group[preview_palette_id_]; + // sheet.ApplyPalette(palette); + // rom()->UpdateBitmap(&sheet); + // } gui::BitmapCanvasPipeline(blockset_canvas_, sheet, 256, 0x10 * 0x04, 0x20, true, false, 22); } @@ -186,7 +186,7 @@ void GfxGroupEditor::DrawSpritesetViewer(bool sheet_only) { } namespace { -void DrawPaletteFromPaletteGroup(gfx::SNESPalette &palette) { +void DrawPaletteFromPaletteGroup(gfx::SnesPalette &palette) { for (int n = 0; n < palette.size(); n++) { ImGui::PushID(n); if ((n % 8) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y); diff --git a/src/app/editor/modules/gfx_group_editor.h b/src/app/editor/modules/gfx_group_editor.h index bb0f104d..ab1a3db6 100644 --- a/src/app/editor/modules/gfx_group_editor.h +++ b/src/app/editor/modules/gfx_group_editor.h @@ -53,7 +53,7 @@ class GfxGroupEditor : public SharedROM { gui::Canvas roomset_canvas_; gui::Canvas spriteset_canvas_; - gfx::SNESPalette palette_; + gfx::SnesPalette palette_; gfx::PaletteGroup palette_group_; gfx::Bitmap tile16_blockset_bmp_; diff --git a/src/app/editor/modules/palette_editor.cc b/src/app/editor/modules/palette_editor.cc index c394e5f9..8c7fb766 100644 --- a/src/app/editor/modules/palette_editor.cc +++ b/src/app/editor/modules/palette_editor.cc @@ -64,7 +64,7 @@ absl::Status PaletteEditor::Update() { return absl::OkStatus(); } -void PaletteEditor::EditColorInPalette(gfx::SNESPalette& palette, int index) { +void PaletteEditor::EditColorInPalette(gfx::SnesPalette& palette, int index) { if (index >= palette.size()) { // Handle error: the index is out of bounds return; @@ -79,8 +79,8 @@ void PaletteEditor::EditColorInPalette(gfx::SNESPalette& palette, int index) { } void PaletteEditor::ResetColorToOriginal( - gfx::SNESPalette& palette, int index, - const gfx::SNESPalette& originalPalette) { + gfx::SnesPalette& palette, int index, + const gfx::SnesPalette& originalPalette) { if (index >= palette.size() || index >= originalPalette.size()) { // Handle error: the index is out of bounds return; @@ -136,7 +136,7 @@ absl::Status PaletteEditor::DrawPaletteGroup(int category) { return absl::OkStatus(); } -absl::Status PaletteEditor::HandleColorPopup(gfx::SNESPalette& palette, int i, +absl::Status PaletteEditor::HandleColorPopup(gfx::SnesPalette& palette, int i, int j, int n) { auto col = gfx::ToFloatArray(palette[n]); if (ImGui::ColorEdit4("Edit Color", col.data(), color_popup_flags)) { @@ -167,7 +167,7 @@ absl::Status PaletteEditor::HandleColorPopup(gfx::SNESPalette& palette, int i, return absl::OkStatus(); } -void PaletteEditor::DisplayPalette(gfx::SNESPalette& palette, bool loaded) { +void PaletteEditor::DisplayPalette(gfx::SnesPalette& palette, bool loaded) { static ImVec4 color = ImVec4(0, 0, 0, 255.f); ImGuiColorEditFlags misc_flags = ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_NoDragDrop | @@ -245,7 +245,7 @@ void PaletteEditor::DisplayPalette(gfx::SNESPalette& palette, bool loaded) { } } -void PaletteEditor::DrawPortablePalette(gfx::SNESPalette& palette) { +void PaletteEditor::DrawPortablePalette(gfx::SnesPalette& palette) { static bool init = false; if (!init) { InitializeSavedPalette(palette); diff --git a/src/app/editor/modules/palette_editor.h b/src/app/editor/modules/palette_editor.h index a39f252b..c74322a1 100644 --- a/src/app/editor/modules/palette_editor.h +++ b/src/app/editor/modules/palette_editor.h @@ -29,16 +29,16 @@ struct PaletteChange { std::string groupName; size_t paletteIndex; size_t colorIndex; - gfx::SNESColor originalColor; - gfx::SNESColor newColor; + gfx::SnesColor originalColor; + gfx::SnesColor newColor; }; class PaletteEditorHistory { public: // Record a change in the palette editor void RecordChange(const std::string& groupName, size_t paletteIndex, - size_t colorIndex, const gfx::SNESColor& originalColor, - const gfx::SNESColor& newColor) { + size_t colorIndex, const gfx::SnesColor& originalColor, + const gfx::SnesColor& newColor) { // Check size and remove the oldest if necessary if (recentChanges.size() >= maxHistorySize) { recentChanges.pop_front(); @@ -55,7 +55,7 @@ class PaletteEditorHistory { } // Restore the original color - gfx::SNESColor GetOriginalColor(const std::string& groupName, + gfx::SnesColor GetOriginalColor(const std::string& groupName, size_t paletteIndex, size_t colorIndex) const { for (const auto& change : recentChanges) { @@ -67,7 +67,7 @@ class PaletteEditorHistory { } // Handle error or return default (this is just an example, // handle as appropriate for your application) - return gfx::SNESColor(); + return gfx::SnesColor(); } private: @@ -80,17 +80,17 @@ class PaletteEditor : public SharedROM { absl::Status Update(); absl::Status DrawPaletteGroups(); - void EditColorInPalette(gfx::SNESPalette& palette, int index); - void ResetColorToOriginal(gfx::SNESPalette& palette, int index, - const gfx::SNESPalette& originalPalette); - void DisplayPalette(gfx::SNESPalette& palette, bool loaded); - void DrawPortablePalette(gfx::SNESPalette& palette); + void EditColorInPalette(gfx::SnesPalette& palette, int index); + void ResetColorToOriginal(gfx::SnesPalette& palette, int index, + const gfx::SnesPalette& originalPalette); + void DisplayPalette(gfx::SnesPalette& palette, bool loaded); + void DrawPortablePalette(gfx::SnesPalette& palette); absl::Status DrawPaletteGroup(int category); private: - absl::Status HandleColorPopup(gfx::SNESPalette& palette, int i, int j, int n); + absl::Status HandleColorPopup(gfx::SnesPalette& palette, int i, int j, int n); - void InitializeSavedPalette(const gfx::SNESPalette& palette) { + void InitializeSavedPalette(const gfx::SnesPalette& palette) { for (int n = 0; n < palette.size(); n++) { saved_palette_[n].x = palette.GetColor(n).GetRGB().x / 255; saved_palette_[n].y = palette.GetColor(n).GetRGB().y / 255; diff --git a/src/app/editor/modules/tile16_editor.cc b/src/app/editor/modules/tile16_editor.cc index 711034df..5afbbda6 100644 --- a/src/app/editor/modules/tile16_editor.cc +++ b/src/app/editor/modules/tile16_editor.cc @@ -110,7 +110,7 @@ absl::Status Tile16Editor::UpdateTile16Transfer() { absl::Status Tile16Editor::UpdateBlockset() { gui::BeginPadding(2); - gui::BeginChildWithScrollbar(55); + gui::BeginChildWithScrollbar("##Tile16EditorBlocksetScrollRegion"); blockset_canvas_.DrawBackground(); gui::EndPadding(); blockset_canvas_.DrawContextMenu(); diff --git a/src/app/editor/modules/tile16_editor.h b/src/app/editor/modules/tile16_editor.h index b4e6761e..e616ba2a 100644 --- a/src/app/editor/modules/tile16_editor.h +++ b/src/app/editor/modules/tile16_editor.h @@ -109,7 +109,7 @@ class Tile16Editor : public GfxContext, public SharedROM { PaletteEditor palette_editor_; - gfx::SNESPalette palette_; + gfx::SnesPalette palette_; zelda3::Overworld transfer_overworld_; gfx::BitmapTable graphics_bin_; diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index 8abb3027..d98f0fbe 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -350,29 +350,20 @@ void OverworldEditor::RefreshOverworldMap() { // TODO: Palette throws out of bounds error unexpectedly. void OverworldEditor::RefreshMapPalette() { - std::vector> futures; - auto refresh_palette_async = [this](int map_index) { - overworld_.mutable_overworld_map(map_index)->LoadPalette(); - maps_bmp_[map_index].ApplyPalette( - *overworld_.mutable_overworld_map(map_index) - ->mutable_current_palette()); - }; - if (overworld_.overworld_map(current_map_)->is_large_map()) { // We need to update the map and its siblings if it's a large map for (int i = 1; i < 4; i++) { int sibling_index = overworld_.overworld_map(current_map_)->parent() + i; if (i >= 2) sibling_index += 6; - futures.push_back( - std::async(std::launch::async, refresh_palette_async, sibling_index)); + overworld_.mutable_overworld_map(sibling_index)->LoadPalette(); + maps_bmp_[sibling_index].ApplyPalette( + *overworld_.mutable_overworld_map(sibling_index) + ->mutable_current_palette()); } } - futures.push_back( - std::async(std::launch::async, refresh_palette_async, current_map_)); - - for (auto &each : futures) { - each.get(); - } + maps_bmp_[current_map_].ApplyPalette( + *overworld_.mutable_overworld_map(current_map_) + ->mutable_current_palette()); } void OverworldEditor::RefreshMapProperties() { @@ -725,7 +716,8 @@ void OverworldEditor::DrawOverworldCanvas() { void OverworldEditor::DrawTile16Selector() { gui::BeginPadding(3); - gui::BeginChildWithScrollbar(/*id=*/1); + ImGui::BeginGroup(); + gui::BeginChildWithScrollbar("##Tile16SelectorScrollRegion"); blockset_canvas_.DrawBackground(); gui::EndNoPadding(); blockset_canvas_.DrawContextMenu(); @@ -748,6 +740,7 @@ void OverworldEditor::DrawTile16Selector() { blockset_canvas_.DrawGrid(); blockset_canvas_.DrawOverlay(); ImGui::EndChild(); + ImGui::EndGroup(); } void OverworldEditor::DrawTile8Selector() { @@ -773,25 +766,30 @@ void OverworldEditor::DrawTile8Selector() { } void OverworldEditor::DrawAreaGraphics() { + if (overworld_.is_loaded()) { + if (current_graphics_set_.count(current_map_) == 0) { + overworld_.set_current_map(current_map_); + palette_ = overworld_.AreaPalette(); + gfx::Bitmap bmp; + gui::BuildAndRenderBitmapPipeline( + 0x80, 0x200, 0x08, overworld_.AreaGraphics(), *rom(), bmp, palette_); + current_graphics_set_[current_map_] = bmp; + } + } + gui::BeginPadding(3); - gui::BeginChildWithScrollbar(/*id=*/2); + ImGui::BeginGroup(); + gui::BeginChildWithScrollbar("##AreaGraphicsScrollRegion"); current_gfx_canvas_.DrawBackground(); gui::EndPadding(); current_gfx_canvas_.DrawContextMenu(); - if (current_graphics_set_.count(current_map_) == 0) { - overworld_.set_current_map(current_map_); - palette_ = overworld_.AreaPalette(); - gfx::Bitmap bmp; - gui::BuildAndRenderBitmapPipeline( - 0x80, 0x200, 0x08, overworld_.AreaGraphics(), *rom(), bmp, palette_); - current_graphics_set_[current_map_] = bmp; - } current_gfx_canvas_.DrawBitmap(current_graphics_set_[current_map_], /*border_offset=*/2, overworld_.is_loaded()); current_gfx_canvas_.DrawTileSelector(32.0f); current_gfx_canvas_.DrawGrid(); current_gfx_canvas_.DrawOverlay(); ImGui::EndChild(); + ImGui::EndGroup(); } void OverworldEditor::DrawTileSelector() { @@ -803,7 +801,7 @@ void OverworldEditor::DrawTileSelector() { } if (BeginTabItem("Tile8")) { gui::BeginPadding(3); - gui::BeginChildWithScrollbar(/*id=*/2); + gui::BeginChildWithScrollbar("##Tile8SelectorScrollRegion"); DrawTile8Selector(); ImGui::EndChild(); gui::EndNoPadding(); diff --git a/src/app/editor/overworld_editor.h b/src/app/editor/overworld_editor.h index d359c098..764d9fdd 100644 --- a/src/app/editor/overworld_editor.h +++ b/src/app/editor/overworld_editor.h @@ -232,7 +232,7 @@ class OverworldEditor : public Editor, gui::CanvasGridSize::k16x16}; gui::Canvas properties_canvas_; - gfx::SNESPalette palette_; + gfx::SnesPalette palette_; gfx::Bitmap selected_tile_bmp_; gfx::Bitmap tile16_blockset_bmp_; gfx::Bitmap current_gfx_bmp_; diff --git a/src/app/editor/screen_editor.h b/src/app/editor/screen_editor.h index a46f8fdf..c781c706 100644 --- a/src/app/editor/screen_editor.h +++ b/src/app/editor/screen_editor.h @@ -61,7 +61,7 @@ class ScreenEditor : public SharedROM { Bytes all_gfx_; zelda3::Inventory inventory_; - gfx::SNESPalette palette_; + gfx::SnesPalette palette_; gui::Canvas screen_canvas_; gui::Canvas tilesheet_canvas_; gui::Canvas tilemap_canvas_; diff --git a/src/app/gfx/bitmap.cc b/src/app/gfx/bitmap.cc index 88f9674a..b58cefbc 100644 --- a/src/app/gfx/bitmap.cc +++ b/src/app/gfx/bitmap.cc @@ -268,8 +268,14 @@ void Bitmap::UpdateTexture(SDL_Renderer *renderer) { SDL_LockTexture(texture_.get(), nullptr, (void **)&texture_pixels, &converted_surface_->pitch); - memcpy(texture_pixels, converted_surface_->pixels, - converted_surface_->h * converted_surface_->pitch); + try { + memcpy(texture_pixels, converted_surface_->pixels, + converted_surface_->h * converted_surface_->pitch); + // SDL_UpdateTexture(texture_.get(), nullptr, converted_surface_->pixels, + // converted_surface_->pitch); + } catch (const std::exception &e) { + SDL_Log("Exception: %s\n", e.what()); + } SDL_UnlockTexture(texture_.get()); } @@ -313,7 +319,7 @@ void Bitmap::LoadFromPngData(const std::vector &png_data, int width, } // Convert SNESPalette to SDL_Palette for surface. -void Bitmap::ApplyPalette(const SNESPalette &palette) { +void Bitmap::ApplyPalette(const SnesPalette &palette) { palette_ = palette; SDL_UnlockSurface(surface_.get()); for (int i = 0; i < palette.size(); ++i) { @@ -332,7 +338,7 @@ void Bitmap::ApplyPalette(const SNESPalette &palette) { SDL_LockSurface(surface_.get()); } -void Bitmap::ApplyPaletteFromPaletteGroup(const SNESPalette &palette, +void Bitmap::ApplyPaletteFromPaletteGroup(const SnesPalette &palette, int palette_id) { auto start_index = palette_id * 8; palette_ = palette.sub_palette(start_index, start_index + 8); @@ -353,8 +359,8 @@ void Bitmap::ApplyPaletteFromPaletteGroup(const SNESPalette &palette, SDL_LockSurface(surface_.get()); } -void Bitmap::ApplyPaletteWithTransparent(const SNESPalette &palette, - int index) { +void Bitmap::ApplyPaletteWithTransparent(const SnesPalette &palette, int index, + int length) { auto start_index = index * 7; palette_ = palette.sub_palette(start_index, start_index + 7); std::vector colors; diff --git a/src/app/gfx/bitmap.h b/src/app/gfx/bitmap.h index 22a95fdd..d21f4510 100644 --- a/src/app/gfx/bitmap.h +++ b/src/app/gfx/bitmap.h @@ -44,10 +44,11 @@ class Bitmap { void LoadFromPngData(const std::vector &png_data, int width, int height); - void ApplyPalette(const SNESPalette &palette); - void ApplyPaletteWithTransparent(const SNESPalette &palette, int index); + void ApplyPalette(const SnesPalette &palette); + void ApplyPaletteWithTransparent(const SnesPalette &palette, int index, + int length = 7); void ApplyPalette(const std::vector &palette); - void ApplyPaletteFromPaletteGroup(const SNESPalette &palette, int palette_id); + void ApplyPaletteFromPaletteGroup(const SnesPalette &palette, int palette_id); void WriteToPixel(int position, uchar value) { if (pixel_data_ == nullptr) { @@ -222,7 +223,7 @@ class Bitmap { std::vector png_data_; - gfx::SNESPalette palette_; + gfx::SnesPalette palette_; std::shared_ptr texture_ = nullptr; std::shared_ptr surface_ = nullptr; std::shared_ptr converted_surface_ = nullptr; diff --git a/src/app/gfx/snes_color.cc b/src/app/gfx/snes_color.cc new file mode 100644 index 00000000..8f881378 --- /dev/null +++ b/src/app/gfx/snes_color.cc @@ -0,0 +1,60 @@ + +#include "app/gfx/snes_color.h" + +#include + +#include + +namespace yaze { +namespace app { +namespace gfx { + +constexpr uint16_t SNES_RED_MASK = 32; +constexpr uint16_t SNES_GREEN_MASK = 32; +constexpr uint16_t SNES_BLUE_MASK = 32; + +constexpr uint16_t SNES_GREEN_SHIFT = 32; +constexpr uint16_t SNES_BLUE_SHIFT = 1024; + +snes_color ConvertSNEStoRGB(uint16_t color_snes) { + snes_color result; + + result.red = (color_snes % SNES_RED_MASK) * 8; + result.green = ((color_snes / SNES_GREEN_MASK) % SNES_GREEN_MASK) * 8; + result.blue = ((color_snes / SNES_BLUE_SHIFT) % SNES_BLUE_MASK) * 8; + + result.red += result.red / SNES_RED_MASK; + result.green += result.green / SNES_GREEN_MASK; + result.blue += result.blue / SNES_BLUE_MASK; + + return result; +} + +uint16_t ConvertRGBtoSNES(const snes_color& color) { + uint16_t red = color.red / 8; + uint16_t green = color.green / 8; + uint16_t blue = color.blue / 8; + return (blue * SNES_BLUE_SHIFT) + (green * SNES_GREEN_SHIFT) + red; +} + +uint16_t ConvertRGBtoSNES(const ImVec4& color) { + snes_color new_color; + new_color.red = color.x * 255; + new_color.green = color.y * 255; + new_color.blue = color.z * 255; + return ConvertRGBtoSNES(new_color); +} + +SnesColor ReadColorFromRom(int offset, const uint8_t* rom) { + short color = (uint16_t)((rom[offset + 1]) << 8) | rom[offset]; + snes_color new_color; + new_color.red = (color & 0x1F) * 8; + new_color.green = ((color >> 5) & 0x1F) * 8; + new_color.blue = ((color >> 10) & 0x1F) * 8; + SnesColor snes_color(new_color); + return snes_color; +} + +} // namespace gfx +} // namespace app +} // namespace yaze \ No newline at end of file diff --git a/src/app/gfx/snes_color.h b/src/app/gfx/snes_color.h new file mode 100644 index 00000000..3f2c82b0 --- /dev/null +++ b/src/app/gfx/snes_color.h @@ -0,0 +1,106 @@ +#ifndef YAZE_APP_GFX_SNES_COLOR_H_ +#define YAZE_APP_GFX_SNES_COLOR_H_ + +#include + +#include + +namespace yaze { +namespace app { +namespace gfx { + +struct snes_color { + uint16_t red; /**< Red component of the color. */ + uint16_t blue; /**< Blue component of the color. */ + uint16_t green; /**< Green component of the color. */ +}; +typedef struct snes_color snes_color; + +snes_color ConvertSNEStoRGB(uint16_t snes_color); +uint16_t ConvertRGBtoSNES(const snes_color& color); +uint16_t ConvertRGBtoSNES(const ImVec4& color); + +// class SnesColor { +// public: +// SnesColor() : rgb(0.f, 0.f, 0.f, 0.f), snes(0) {} +// SnesColor(const ImVec4 val) : rgb(val) { +// snes_color color; +// color.red = val.x / 255; +// color.green = val.y / 255; +// color.blue = val.z / 255; +// snes = ConvertRGBtoSNES(color); +// } +// SnesColor(const snes_color internal_format) { +// rgb.x = internal_format.red; +// rgb.y = internal_format.green; +// rgb.z = internal_format.blue; +// snes = ConvertRGBtoSNES(internal_format); +// } + +// ImVec4 rgb; /**< The color in RGB format. */ +// uint16_t snes; /**< The color in SNES format. */ +// bool modified = false; +// bool transparent = false; +// }; + +class SnesColor { + public: + SnesColor() : rgb(0.f, 0.f, 0.f, 0.f), snes(0) {} + + explicit SnesColor(const ImVec4 val) : rgb(val) { + snes_color color; + color.red = val.x / 255; + color.green = val.y / 255; + color.blue = val.z / 255; + snes = ConvertRGBtoSNES(color); + } + + explicit SnesColor(const snes_color val) + : rgb(val.red, val.green, val.blue, 255.f), + snes(ConvertRGBtoSNES(val)), + rom_color(val) {} + + ImVec4 GetRGB() const { return rgb; } + void SetRGB(const ImVec4 val) { + rgb.x = val.x / 255; + rgb.y = val.y / 255; + rgb.z = val.z / 255; + snes_color color; + color.red = val.x; + color.green = val.y; + color.blue = val.z; + rom_color = color; + snes = ConvertRGBtoSNES(color); + modified = true; + } + + snes_color GetRomRGB() const { return rom_color; } + + uint16_t GetSNES() const { return snes; } + void SetSNES(uint16_t val) { + snes = val; + snes_color col = ConvertSNEStoRGB(val); + rgb = ImVec4(col.red, col.green, col.blue, 0.f); + modified = true; + } + + bool IsModified() const { return modified; } + bool IsTransparent() const { return transparent; } + void SetTransparent(bool t) { transparent = t; } + void SetModified(bool m) { modified = m; } + + private: + ImVec4 rgb; + uint16_t snes; + snes_color rom_color; + bool modified = false; + bool transparent = false; +}; + +SnesColor ReadColorFromRom(int offset, const uint8_t* rom); + +} // namespace gfx +} // namespace app +} // namespace yaze + +#endif // YAZE_APP_GFX_SNES_COLOR_H_ diff --git a/src/app/gfx/snes_palette.cc b/src/app/gfx/snes_palette.cc index 28f4829d..db1763d9 100644 --- a/src/app/gfx/snes_palette.cc +++ b/src/app/gfx/snes_palette.cc @@ -13,13 +13,14 @@ #include "absl/container/flat_hash_map.h" // for flat_hash_map #include "absl/status/status.h" // for Status #include "app/core/constants.h" +#include "app/gfx/snes_color.h" namespace yaze { namespace app { namespace gfx { // Define a hash map to hold the addresses of different palette groups -const absl::flat_hash_map paletteGroupAddresses = { +const absl::flat_hash_map kPaletteGroupAddressMap = { {"ow_main", core::overworldPaletteMain}, {"ow_aux", core::overworldPaletteAuxialiary}, {"ow_animated", core::overworldPaletteAnimated}, @@ -38,7 +39,7 @@ const absl::flat_hash_map paletteGroupAddresses = { }; // Define a hash map to hold the number of colors in each palette group -const absl::flat_hash_map paletteGroupColorCounts = { +const absl::flat_hash_map kPaletteGroupColorCounts = { {"ow_main", 35}, {"ow_aux", 21}, {"ow_animated", 7}, {"hud", 32}, {"global_sprites", 60}, {"armors", 15}, {"swords", 3}, {"shields", 4}, {"sprites_aux1", 7}, @@ -46,41 +47,6 @@ const absl::flat_hash_map paletteGroupColorCounts = { {"grass", 1}, {"3d_object", 8}, {"ow_mini_map", 128}, }; -constexpr uint16_t SNES_RED_MASK = 32; -constexpr uint16_t SNES_GREEN_MASK = 32; -constexpr uint16_t SNES_BLUE_MASK = 32; - -constexpr uint16_t SNES_GREEN_SHIFT = 32; -constexpr uint16_t SNES_BLUE_SHIFT = 1024; - -uint16_t ConvertRGBtoSNES(const snes_color& color) { - uint16_t red = color.red / 8; - uint16_t green = color.green / 8; - uint16_t blue = color.blue / 8; - return (blue * SNES_BLUE_SHIFT) + (green * SNES_GREEN_SHIFT) + red; -} - -uint16_t ConvertRGBtoSNES(const ImVec4& color) { - snes_color new_color; - new_color.red = color.x * 255; - new_color.green = color.y * 255; - new_color.blue = color.z * 255; - return ConvertRGBtoSNES(new_color); -} - -snes_color ConvertSNEStoRGB(uint16_t color_snes) { - snes_color result; - - result.red = (color_snes % SNES_RED_MASK) * 8; - result.green = ((color_snes / SNES_GREEN_MASK) % SNES_GREEN_MASK) * 8; - result.blue = ((color_snes / SNES_BLUE_SHIFT) % SNES_BLUE_MASK) * 8; - - result.red += result.red / SNES_RED_MASK; - result.green += result.green / SNES_GREEN_MASK; - result.blue += result.blue / SNES_BLUE_MASK; - - return result; -} std::vector Extract(const char* data, unsigned int offset, unsigned int palette_size) { @@ -103,28 +69,19 @@ std::vector Convert(const std::vector& palette) { return data; } -SNESColor ReadColorFromROM(int offset, const uchar* rom) { - short color = (ushort)((rom[offset + 1]) << 8) | rom[offset]; - snes_color new_color; - new_color.red = (color & 0x1F) * 8; - new_color.green = ((color >> 5) & 0x1F) * 8; - new_color.blue = ((color >> 10) & 0x1F) * 8; - SNESColor snes_color(new_color); - return snes_color; -} -SNESColor GetCgxColor(uint16_t color) { +SnesColor GetCgxColor(uint16_t color) { ImVec4 rgb; rgb.x = (color & 0x1F) * 8; rgb.y = ((color & 0x3E0) >> 5) * 8; rgb.z = ((color & 0x7C00) >> 10) * 8; - SNESColor toret; + SnesColor toret; toret.SetRGB(rgb); return toret; } -std::vector GetColFileData(uchar* data) { - std::vector colors; +std::vector GetColFileData(uchar* data) { + std::vector colors; colors.reserve(256); colors.resize(256); @@ -137,64 +94,67 @@ std::vector GetColFileData(uchar* data) { // ============================================================================ -SNESPalette::SNESPalette(uint8_t mSize) : size_(mSize) { +SnesPalette::SnesPalette(uint8_t mSize) : size_(mSize) { for (unsigned int i = 0; i < mSize; i++) { - SNESColor col; + SnesColor col; colors.push_back(col); } + size_ = mSize; } -SNESPalette::SNESPalette(char* data) : size_(sizeof(data) / 2) { +SnesPalette::SnesPalette(char* data) : size_(sizeof(data) / 2) { assert((sizeof(data) % 4 == 0) && (sizeof(data) <= 32)); for (unsigned i = 0; i < sizeof(data); i += 2) { - SNESColor col; + SnesColor col; col.SetSNES(static_cast(data[i + 1]) << 8); col.SetSNES(col.GetSNES() | static_cast(data[i])); snes_color mColor = ConvertSNEStoRGB(col.GetSNES()); col.SetRGB(ImVec4(mColor.red, mColor.green, mColor.blue, 1.f)); colors.push_back(col); } + size_ = sizeof(data) / 2; } -SNESPalette::SNESPalette(const unsigned char* snes_pal) +SnesPalette::SnesPalette(const unsigned char* snes_pal) : size_(sizeof(snes_pal) / 2) { assert((sizeof(snes_pal) % 4 == 0) && (sizeof(snes_pal) <= 32)); for (unsigned i = 0; i < sizeof(snes_pal); i += 2) { - SNESColor col; + SnesColor col; col.SetSNES(snes_pal[i + 1] << (uint16_t)8); col.SetSNES(col.GetSNES() | snes_pal[i]); snes_color mColor = ConvertSNEStoRGB(col.GetSNES()); col.SetRGB(ImVec4(mColor.red, mColor.green, mColor.blue, 1.f)); colors.push_back(col); } + size_ = sizeof(snes_pal) / 2; } -SNESPalette::SNESPalette(const std::vector& cols) { +SnesPalette::SnesPalette(const std::vector& cols) { for (const auto& each : cols) { - SNESColor scol; + SnesColor scol; scol.SetRGB(each); colors.push_back(scol); } size_ = cols.size(); } -SNESPalette::SNESPalette(const std::vector& cols) { +SnesPalette::SnesPalette(const std::vector& cols) { for (const auto& each : cols) { - SNESColor scol; + SnesColor scol; scol.SetSNES(ConvertRGBtoSNES(each)); colors.push_back(scol); } size_ = cols.size(); } -SNESPalette::SNESPalette(const std::vector& cols) { +SnesPalette::SnesPalette(const std::vector& cols) { for (const auto& each : cols) { colors.push_back(each); } size_ = cols.size(); } -SDL_Palette* SNESPalette::GetSDL_Palette() { +SDL_Palette* SnesPalette::GetSDL_Palette() { auto sdl_palette = std::make_shared(); sdl_palette->ncolors = size_; @@ -211,9 +171,9 @@ SDL_Palette* SNESPalette::GetSDL_Palette() { return sdl_palette.get(); } -SNESPalette ReadPaletteFromROM(int offset, int num_colors, const uchar* rom) { +SnesPalette ReadPaletteFromROM(int offset, int num_colors, const uchar* rom) { int color_offset = 0; - std::vector colors(num_colors); + std::vector colors(num_colors); while (color_offset < num_colors) { short color = (ushort)((rom[offset + 1]) << 8) | rom[offset]; @@ -229,17 +189,17 @@ SNESPalette ReadPaletteFromROM(int offset, int num_colors, const uchar* rom) { offset += 2; } - gfx::SNESPalette palette(colors); + gfx::SnesPalette palette(colors); return palette; } uint32_t GetPaletteAddress(const std::string& group_name, size_t palette_index, size_t color_index) { // Retrieve the base address for the palette group - uint32_t base_address = paletteGroupAddresses.at(group_name); + uint32_t base_address = kPaletteGroupAddressMap.at(group_name); // Retrieve the number of colors for each palette in the group - uint32_t colors_per_palette = paletteGroupColorCounts.at(group_name); + uint32_t colors_per_palette = kPaletteGroupColorCounts.at(group_name); // Calculate the address for thes specified color in the ROM uint32_t address = base_address + (palette_index * colors_per_palette * 2) + @@ -248,7 +208,7 @@ uint32_t GetPaletteAddress(const std::string& group_name, size_t palette_index, return address; } -std::array ToFloatArray(const SNESColor& color) { +std::array ToFloatArray(const SnesColor& color) { std::array colorArray; colorArray[0] = color.GetRGB().x / 255.0f; colorArray[1] = color.GetRGB().y / 255.0f; @@ -260,11 +220,11 @@ std::array ToFloatArray(const SNESColor& color) { PaletteGroup::PaletteGroup(uint8_t mSize) : size_(mSize) {} PaletteGroup CreatePaletteGroupFromColFile( - std::vector& palette_rows) { + std::vector& palette_rows) { PaletteGroup toret; for (int i = 0; i < palette_rows.size(); i += 8) { - SNESPalette palette; + SnesPalette palette; for (int j = 0; j < 8; j++) { palette.AddColor(palette_rows[i + j].GetRomRGB()); } @@ -275,11 +235,11 @@ PaletteGroup CreatePaletteGroupFromColFile( // Take a SNESPalette with N many colors and divide it into palettes of 8 colors // each -PaletteGroup CreatePaletteGroupFromLargePalette(SNESPalette& palette) { +PaletteGroup CreatePaletteGroupFromLargePalette(SnesPalette& palette) { PaletteGroup toret; for (int i = 0; i < palette.size(); i += 8) { - SNESPalette new_palette; + SnesPalette new_palette; if (i + 8 < palette.size()) { for (int j = 0; j < 8; j++) { new_palette.AddColor(palette[i + j]); diff --git a/src/app/gfx/snes_palette.h b/src/app/gfx/snes_palette.h index 0bcdb38a..17e0bbe1 100644 --- a/src/app/gfx/snes_palette.h +++ b/src/app/gfx/snes_palette.h @@ -14,18 +14,12 @@ #include "absl/base/casts.h" #include "absl/status/status.h" #include "app/core/constants.h" +#include "app/gfx/snes_color.h" namespace yaze { namespace app { namespace gfx { -struct snes_color { - uint16_t red; /**< Red component of the color. */ - uint16_t blue; /**< Blue component of the color. */ - uint16_t green; /**< Green component of the color. */ -}; -using snes_color = struct snes_color; - struct snes_palette { uint id; /**< ID of the palette. */ uint size; /**< Size of the palette. */ @@ -33,10 +27,6 @@ struct snes_palette { }; using snes_palette = struct snes_palette; -uint16_t ConvertRGBtoSNES(const snes_color& color); -uint16_t ConvertRGBtoSNES(const ImVec4& color); -snes_color ConvertSNEStoRGB(uint16_t snes_color); - /** * @brief Extracts a vector of SNES colors from a data buffer. * @@ -56,92 +46,38 @@ std::vector Extract(const char* data, unsigned int offset, */ std::vector Convert(const std::vector& palette); -struct SNESColor { - SNESColor() : rgb(0.f, 0.f, 0.f, 0.f), snes(0) {} +SnesColor GetCgxColor(uint16_t color); +std::vector GetColFileData(uint8_t* data); - explicit SNESColor(const ImVec4 val) : rgb(val) { - snes_color color; - color.red = val.x / 255; - color.green = val.y / 255; - color.blue = val.z / 255; - snes = ConvertRGBtoSNES(color); - } - - explicit SNESColor(const snes_color val) - : rgb(val.red, val.green, val.blue, 255.f), - snes(ConvertRGBtoSNES(val)), - rom_color(val) {} - - ImVec4 GetRGB() const { return rgb; } - void SetRGB(const ImVec4 val) { - rgb.x = val.x / 255; - rgb.y = val.y / 255; - rgb.z = val.z / 255; - snes_color color; - color.red = val.x; - color.green = val.y; - color.blue = val.z; - rom_color = color; - snes = ConvertRGBtoSNES(color); - modified = true; - } - - snes_color GetRomRGB() const { return rom_color; } - - uint16_t GetSNES() const { return snes; } - void SetSNES(uint16_t val) { - snes = val; - snes_color col = ConvertSNEStoRGB(val); - rgb = ImVec4(col.red, col.green, col.blue, 0.f); - modified = true; - } - - bool IsModified() const { return modified; } - bool IsTransparent() const { return transparent; } - void SetTransparent(bool t) { transparent = t; } - void SetModified(bool m) { modified = m; } - - private: - ImVec4 rgb; - uint16_t snes; - snes_color rom_color; - bool modified = false; - bool transparent = false; -}; - -gfx::SNESColor ReadColorFromROM(int offset, const uint8_t* rom); - -SNESColor GetCgxColor(uint16_t color); -std::vector GetColFileData(uint8_t* data); - -class SNESPalette { +class SnesPalette { public: template - explicit SNESPalette(const std::vector& data) { + explicit SnesPalette(const std::vector& data) { for (const auto& item : data) { - colors.push_back(SNESColor(item)); + colors.push_back(SnesColor(item)); } + size_ = data.size(); } - SNESPalette() = default; + SnesPalette() = default; - explicit SNESPalette(uint8_t mSize); - explicit SNESPalette(char* snesPal); - explicit SNESPalette(const unsigned char* snes_pal); - explicit SNESPalette(const std::vector&); - explicit SNESPalette(const std::vector&); - explicit SNESPalette(const std::vector&); + explicit SnesPalette(uint8_t mSize); + explicit SnesPalette(char* snesPal); + explicit SnesPalette(const unsigned char* snes_pal); + explicit SnesPalette(const std::vector&); + explicit SnesPalette(const std::vector&); + explicit SnesPalette(const std::vector&); SDL_Palette* GetSDL_Palette(); - void Create(const std::vector& cols) { + void Create(const std::vector& cols) { for (const auto& each : cols) { colors.push_back(each); } size_ = cols.size(); } - void AddColor(SNESColor color) { + void AddColor(SnesColor color) { colors.push_back(color); size_++; } @@ -166,7 +102,7 @@ class SNESPalette { auto size() const { return colors.size(); } - SNESColor& operator[](int i) { + SnesColor& operator[](int i) { if (i > size_) { std::cout << "SNESPalette: Index out of bounds" << std::endl; return colors[0]; @@ -174,7 +110,7 @@ class SNESPalette { return colors[i]; } - void operator()(int i, const SNESColor& color) { + void operator()(int i, const SnesColor& color) { if (i >= size_) { throw std::out_of_range("SNESPalette: Index out of bounds"); } @@ -189,8 +125,8 @@ class SNESPalette { colors[i].SetModified(true); } - SNESPalette sub_palette(int start, int end) const { - SNESPalette pal; + SnesPalette sub_palette(int start, int end) const { + SnesPalette pal; for (int i = start; i < end; i++) { pal.AddColor(colors[i]); } @@ -199,13 +135,13 @@ class SNESPalette { private: int size_ = 0; /**< The size of the palette. */ - std::vector colors; /**< The colors in the palette. */ + std::vector colors; /**< The colors in the palette. */ }; -SNESPalette ReadPaletteFromROM(int offset, int num_colors, const uint8_t* rom); +SnesPalette ReadPaletteFromROM(int offset, int num_colors, const uint8_t* rom); uint32_t GetPaletteAddress(const std::string& group_name, size_t palette_index, size_t color_index); -std::array ToFloatArray(const SNESColor& color); +std::array ToFloatArray(const SnesColor& color); struct PaletteGroup { PaletteGroup() = default; @@ -214,13 +150,13 @@ struct PaletteGroup { auto mutable_palette(int i) { return &palettes[i]; } - absl::Status AddPalette(SNESPalette pal) { + absl::Status AddPalette(SnesPalette pal) { palettes.emplace_back(pal); size_ = palettes.size(); return absl::OkStatus(); } - absl::Status AddColor(SNESColor color) { + absl::Status AddColor(SnesColor color) { if (size_ == 0) { palettes.emplace_back(); } @@ -235,7 +171,7 @@ struct PaletteGroup { auto size() const { return palettes.size(); } - SNESPalette operator[](int i) { + SnesPalette operator[](int i) { if (i > size_) { std::cout << "PaletteGroup: Index out of bounds" << std::endl; return palettes[0]; @@ -243,7 +179,7 @@ struct PaletteGroup { return palettes[i]; } - const SNESPalette& operator[](int i) const { + const SnesPalette& operator[](int i) const { if (i > size_) { std::cout << "PaletteGroup: Index out of bounds" << std::endl; return palettes[0]; @@ -251,7 +187,7 @@ struct PaletteGroup { return palettes[i]; } - absl::Status operator()(int i, const SNESColor& color) { + absl::Status operator()(int i, const SnesColor& color) { if (i >= size_) { return absl::InvalidArgumentError("PaletteGroup: Index out of bounds"); } @@ -269,19 +205,19 @@ struct PaletteGroup { private: int size_ = 0; - std::vector palettes; + std::vector palettes; }; -PaletteGroup CreatePaletteGroupFromColFile(std::vector& colors); +PaletteGroup CreatePaletteGroupFromColFile(std::vector& colors); -PaletteGroup CreatePaletteGroupFromLargePalette(SNESPalette& palette); +PaletteGroup CreatePaletteGroupFromLargePalette(SnesPalette& palette); struct Paletteset { Paletteset() = default; - Paletteset(gfx::SNESPalette main, gfx::SNESPalette animated, - gfx::SNESPalette aux1, gfx::SNESPalette aux2, - gfx::SNESColor background, gfx::SNESPalette hud, - gfx::SNESPalette spr, gfx::SNESPalette spr2) + Paletteset(gfx::SnesPalette main, gfx::SnesPalette animated, + gfx::SnesPalette aux1, gfx::SnesPalette aux2, + gfx::SnesColor background, gfx::SnesPalette hud, + gfx::SnesPalette spr, gfx::SnesPalette spr2, gfx::SnesPalette comp) : main(main), animated(animated), aux1(aux1), @@ -289,15 +225,17 @@ struct Paletteset { background(background), hud(hud), spr(spr), - spr2(spr2) {} - gfx::SNESPalette main; - gfx::SNESPalette animated; - gfx::SNESPalette aux1; - gfx::SNESPalette aux2; - gfx::SNESColor background; - gfx::SNESPalette hud; - gfx::SNESPalette spr; - gfx::SNESPalette spr2; + spr2(spr2), + composite(comp) {} + gfx::SnesPalette main; + gfx::SnesPalette animated; + gfx::SnesPalette aux1; + gfx::SnesPalette aux2; + gfx::SnesColor background; + gfx::SnesPalette hud; + gfx::SnesPalette spr; + gfx::SnesPalette spr2; + gfx::SnesPalette composite; }; } // namespace gfx diff --git a/src/app/gfx/tilesheet.h b/src/app/gfx/tilesheet.h index 9fa5b15f..81ca60a2 100644 --- a/src/app/gfx/tilesheet.h +++ b/src/app/gfx/tilesheet.h @@ -123,7 +123,7 @@ class Tilesheet { auto num_tiles() const { return num_tiles_; } auto tile_width() const { return tile_width_; } auto tile_height() const { return tile_height_; } - auto set_palette(gfx::SNESPalette& palette) { palette_ = palette; } + auto set_palette(gfx::SnesPalette& palette) { palette_ = palette; } auto palette() const { return palette_; } auto tile_type() const { return tile_type_; } auto tile_info() const { return tile_info_; } @@ -217,7 +217,7 @@ class Tilesheet { tileDataOffset); } - gfx::SNESPalette palette_; + gfx::SnesPalette palette_; std::vector internal_data_; std::shared_ptr bitmap_; struct InternalTile16 { diff --git a/src/app/gui/color.cc b/src/app/gui/color.cc index 4871cd7e..7703969c 100644 --- a/src/app/gui/color.cc +++ b/src/app/gui/color.cc @@ -12,7 +12,7 @@ namespace yaze { namespace app { namespace gui { -ImVec4 ConvertSNESColorToImVec4(const SNESColor& color) { +ImVec4 ConvertSNESColorToImVec4(const SnesColor& color) { return ImVec4(static_cast(color.GetRGB().x) / 255.0f, static_cast(color.GetRGB().y) / 255.0f, static_cast(color.GetRGB().z) / 255.0f, @@ -21,7 +21,7 @@ ImVec4 ConvertSNESColorToImVec4(const SNESColor& color) { ); } -IMGUI_API bool SNESColorButton(absl::string_view id, SNESColor& color, +IMGUI_API bool SNESColorButton(absl::string_view id, SnesColor& color, ImGuiColorEditFlags flags, const ImVec2& size_arg) { // Convert the SNES color values to ImGui color values (normalized to 0-1 @@ -34,7 +34,7 @@ IMGUI_API bool SNESColorButton(absl::string_view id, SNESColor& color, return pressed; } -void DisplayPalette(app::gfx::SNESPalette& palette, bool loaded) { +void DisplayPalette(app::gfx::SnesPalette& palette, bool loaded) { static ImVec4 color = ImVec4(0, 0, 0, 255.f); ImGuiColorEditFlags misc_flags = ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_NoDragDrop | diff --git a/src/app/gui/color.h b/src/app/gui/color.h index 7e944a1e..fbb99123 100644 --- a/src/app/gui/color.h +++ b/src/app/gui/color.h @@ -13,18 +13,18 @@ namespace yaze { namespace app { namespace gui { -using gfx::SNESColor; +using gfx::SnesColor; -// A utility function to convert an SNESColor object to an ImVec4 with +// A utility function to convert an SnesColor object to an ImVec4 with // normalized color values -ImVec4 ConvertSNESColorToImVec4(const SNESColor& color); +ImVec4 ConvertSNESColorToImVec4(const SnesColor& color); -// The wrapper function for ImGui::ColorButton that takes a SNESColor reference -IMGUI_API bool SNESColorButton(absl::string_view id, SNESColor& color, +// The wrapper function for ImGui::ColorButton that takes a SnesColor reference +IMGUI_API bool SNESColorButton(absl::string_view id, SnesColor& color, ImGuiColorEditFlags flags = 0, const ImVec2& size_arg = ImVec2(0, 0)); -void DisplayPalette(app::gfx::SNESPalette& palette, bool loaded); +void DisplayPalette(app::gfx::SnesPalette& palette, bool loaded); } // namespace gui } // namespace app diff --git a/src/app/gui/pipeline.cc b/src/app/gui/pipeline.cc index d039f0a5..5a300fa7 100644 --- a/src/app/gui/pipeline.cc +++ b/src/app/gui/pipeline.cc @@ -22,7 +22,7 @@ namespace app { namespace gui { void SelectablePalettePipeline(uint64_t& palette_id, bool& refresh_graphics, - gfx::SNESPalette& palette) { + gfx::SnesPalette& palette) { const auto palette_row_size = 7; if (ImGuiID child_id = ImGui::GetID((void*)(intptr_t)100); ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(), true, @@ -160,7 +160,7 @@ void BitmapCanvasPipeline(gui::Canvas& canvas, const gfx::Bitmap& bitmap, void BuildAndRenderBitmapPipeline(int width, int height, int depth, Bytes data, ROM& z3_rom, gfx::Bitmap& bitmap, - gfx::SNESPalette& palette) { + gfx::SnesPalette& palette) { bitmap.Create(width, height, depth, data); bitmap.ApplyPalette(palette); z3_rom.RenderBitmap(&bitmap); diff --git a/src/app/gui/pipeline.h b/src/app/gui/pipeline.h index d78e6d61..ac33de13 100644 --- a/src/app/gui/pipeline.h +++ b/src/app/gui/pipeline.h @@ -21,7 +21,7 @@ namespace app { namespace gui { void SelectablePalettePipeline(uint64_t& palette_id, bool& refresh_graphics, - gfx::SNESPalette& palette); + gfx::SnesPalette& palette); void GraphicsBinCanvasPipeline(int width, int height, int tile_size, int num_sheets_to_load, int canvas_id, @@ -40,7 +40,7 @@ void GraphicsManagerCanvasPipeline(int width, int height, int tile_size, void BuildAndRenderBitmapPipeline(int width, int height, int depth, Bytes data, ROM& z3_rom, gfx::Bitmap& bitmap, - gfx::SNESPalette& palette); + gfx::SnesPalette& palette); void FileDialogPipeline(absl::string_view display_key, absl::string_view file_extensions, diff --git a/src/app/gui/style.cc b/src/app/gui/style.cc index c9baa7df..7ce91b32 100644 --- a/src/app/gui/style.cc +++ b/src/app/gui/style.cc @@ -44,9 +44,8 @@ void BeginNoPadding() { } void EndNoPadding() { ImGui::PopStyleVar(2); } -void BeginChildWithScrollbar(int id) { - ImGuiID child_id = ImGui::GetID((void*)(intptr_t)id); - ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(), true, +void BeginChildWithScrollbar(const char* str_id) { + ImGui::BeginChild(str_id, ImGui::GetContentRegionAvail(), true, ImGuiWindowFlags_AlwaysVerticalScrollbar); } diff --git a/src/app/gui/style.h b/src/app/gui/style.h index 15c2108a..ad726983 100644 --- a/src/app/gui/style.h +++ b/src/app/gui/style.h @@ -21,7 +21,7 @@ void EndPadding(); void BeginNoPadding(); void EndNoPadding(); -void BeginChildWithScrollbar(int id); +void BeginChildWithScrollbar(const char *str_id); void BeginChildBothScrollbars(int id); diff --git a/src/app/rom.cc b/src/app/rom.cc index bc9f70d6..f362b247 100644 --- a/src/app/rom.cc +++ b/src/app/rom.cc @@ -22,7 +22,8 @@ #include "app/core/constants.h" // for Bytes, ASSIGN_OR_RETURN #include "app/gfx/bitmap.h" // for Bitmap, BitmapTable #include "app/gfx/compression.h" // for DecompressV2 -#include "app/gfx/snes_palette.h" // for PaletteGroup, SNESColor +#include "app/gfx/snes_color.h" // for SNESColor +#include "app/gfx/snes_palette.h" // for PaletteGroup #include "app/gfx/snes_tile.h" // for SnesTo8bppSheet namespace yaze { @@ -156,11 +157,11 @@ absl::Status LoadDungeonMainPalettes(const Bytes& rom_data, absl::Status LoadGrassColors(const Bytes& rom_data, PaletteGroupMap& palette_groups) { RETURN_IF_ERROR(palette_groups["grass"].AddColor( - gfx::ReadColorFromROM(core::hardcodedGrassLW, rom_data.data()))) + gfx::ReadColorFromRom(core::hardcodedGrassLW, rom_data.data()))) RETURN_IF_ERROR(palette_groups["grass"].AddColor( - gfx::ReadColorFromROM(core::hardcodedGrassDW, rom_data.data()))) + gfx::ReadColorFromRom(core::hardcodedGrassDW, rom_data.data()))) RETURN_IF_ERROR(palette_groups["grass"].AddColor( - gfx::ReadColorFromROM(core::hardcodedGrassSpecial, rom_data.data()))) + gfx::ReadColorFromRom(core::hardcodedGrassSpecial, rom_data.data()))) return absl::OkStatus(); } @@ -477,10 +478,10 @@ absl::Status ROM::SaveToFile(bool backup, bool save_new, std::string filename) { } void ROM::SavePalette(int index, const std::string& group_name, - gfx::SNESPalette& palette) { + gfx::SnesPalette& palette) { // Iterate through all colors in the palette for (size_t j = 0; j < palette.size(); ++j) { - gfx::SNESColor color = palette[j]; + gfx::SnesColor color = palette[j]; // If the color is modified, save the color to the ROM if (color.IsModified()) { WriteColor(gfx::GetPaletteAddress(group_name, index, j), color); @@ -502,7 +503,7 @@ void ROM::SaveAllPalettes() { absl::Status ROM::UpdatePaletteColor(const std::string& groupName, size_t paletteIndex, size_t colorIndex, - const gfx::SNESColor& newColor) { + const gfx::SnesColor& newColor) { // Check if the groupName exists in the palette_groups_ map if (palette_groups_.find(groupName) != palette_groups_.end()) { // Check if the paletteIndex is within the range of available palettes in diff --git a/src/app/rom.h b/src/app/rom.h index c6ddd09b..acb92dbe 100644 --- a/src/app/rom.h +++ b/src/app/rom.h @@ -134,7 +134,7 @@ constexpr uint32_t gfx_groups_pointer = 0x6237; struct WriteAction { int address; std::variant, - gfx::SNESColor, std::vector> + gfx::SnesColor, std::vector> value; }; @@ -157,12 +157,12 @@ class ROM : public core::ExperimentFlags { } else if (std::holds_alternative>(action.value)) { return WriteVector(action.address, std::get>(action.value)); - } else if (std::holds_alternative(action.value)) { - return WriteColor(action.address, std::get(action.value)); - } else if (std::holds_alternative>( + } else if (std::holds_alternative(action.value)) { + return WriteColor(action.address, std::get(action.value)); + } else if (std::holds_alternative>( action.value)) { return absl::UnimplementedError( - "WriteHelper: std::vector"); + "WriteHelper: std::vector"); } auto error_message = absl::StrFormat("Invalid write argument type: %s", typeid(action.value).name()); @@ -271,7 +271,7 @@ class ROM : public core::ExperimentFlags { * @param palette The palette to save. */ void SavePalette(int index, const std::string& group_name, - gfx::SNESPalette& palette); + gfx::SnesPalette& palette); /** * @brief Saves all palettes in the ROM. @@ -300,7 +300,7 @@ class ROM : public core::ExperimentFlags { */ absl::Status UpdatePaletteColor(const std::string& group_name, size_t palette_index, size_t colorIndex, - const gfx::SNESColor& newColor); + const gfx::SnesColor& newColor); // Read functions absl::StatusOr ReadByte(int offset) { @@ -452,7 +452,7 @@ class ROM : public core::ExperimentFlags { return absl::OkStatus(); } - absl::Status WriteColor(uint32_t address, const gfx::SNESColor& color) { + absl::Status WriteColor(uint32_t address, const gfx::SnesColor& color) { uint16_t bgr = ((color.GetSNES() >> 10) & 0x1F) | ((color.GetSNES() & 0x1F) << 10) | (color.GetSNES() & 0x7C00); @@ -663,7 +663,7 @@ class ROM : public core::ExperimentFlags { gfx::BitmapTable graphics_bin_; gfx::BitmapManager graphics_manager_; gfx::BitmapTable link_graphics_; - gfx::SNESPalette link_palette_; + gfx::SnesPalette link_palette_; PaletteGroupMap palette_groups_; core::ResourceLabelManager resource_label_manager_; diff --git a/src/app/zelda3/dungeon/object_renderer.h b/src/app/zelda3/dungeon/object_renderer.h index f4d7efe4..fd2f4277 100644 --- a/src/app/zelda3/dungeon/object_renderer.h +++ b/src/app/zelda3/dungeon/object_renderer.h @@ -22,7 +22,7 @@ class DungeonObjectRenderer : public SharedROM { public: struct PseudoVram { std::array sheets; - std::vector palettes; + std::vector palettes; }; DungeonObjectRenderer() = default; diff --git a/src/app/zelda3/overworld_map.cc b/src/app/zelda3/overworld_map.cc index 587ea5a2..0cc2fbf6 100644 --- a/src/app/zelda3/overworld_map.cc +++ b/src/app/zelda3/overworld_map.cc @@ -229,16 +229,16 @@ void OverworldMap::LoadAreaGraphics() { namespace palette_internal { -void SetColorsPalette(ROM& rom, int index, gfx::SNESPalette& current, - gfx::SNESPalette main, gfx::SNESPalette animated, - gfx::SNESPalette aux1, gfx::SNESPalette aux2, - gfx::SNESPalette hud, gfx::SNESColor bgrcolor, - gfx::SNESPalette spr, gfx::SNESPalette spr2) { +void SetColorsPalette(ROM& rom, int index, gfx::SnesPalette& current, + gfx::SnesPalette main, gfx::SnesPalette animated, + gfx::SnesPalette aux1, gfx::SnesPalette aux2, + gfx::SnesPalette hud, gfx::SnesColor bgrcolor, + gfx::SnesPalette spr, gfx::SnesPalette spr2) { // Palettes infos, color 0 of a palette is always transparent (the arrays // contains 7 colors width wide) There is 16 color per line so 16*Y // Left side of the palette - Main, Animated - std::vector new_palette(256); + std::vector new_palette(256); // Main Palette, Location 0,2 : 35 colors [7x5] int k = 0; @@ -347,7 +347,7 @@ void SetColorsPalette(ROM& rom, int index, gfx::SNESPalette& current, } // namespace palette_internal // New helper function to get a palette from the ROM. -gfx::SNESPalette OverworldMap::GetPalette(const std::string& group, int index, +gfx::SnesPalette OverworldMap::GetPalette(const std::string& group, int index, int previousIndex, int limit) { if (index == 255) { index = rom_[rom_.version_constants().overworldMapPaletteGroup + @@ -382,10 +382,10 @@ void OverworldMap::LoadPalette() { uchar pal5 = rom_[overworldSpritePaletteGroup + (sprite_palette_[game_state_] * 2) + 1]; - gfx::SNESColor bgr = rom_.palette_group("grass")[0].GetColor(0); + gfx::SnesColor bgr = rom_.palette_group("grass")[0].GetColor(0); - gfx::SNESPalette aux1 = GetPalette("ow_aux", pal1, previousPalId, 20); - gfx::SNESPalette aux2 = GetPalette("ow_aux", pal2, previousPalId, 20); + gfx::SnesPalette aux1 = GetPalette("ow_aux", pal1, previousPalId, 20); + gfx::SnesPalette aux2 = GetPalette("ow_aux", pal2, previousPalId, 20); // Additional handling of `pal3` and `parent_` if (pal3 == 255) { @@ -405,20 +405,22 @@ void OverworldMap::LoadPalette() { if (parent_ == 0x88) { pal0 = 4; } - gfx::SNESPalette main = GetPalette("ow_main", pal0, previousPalId, 255); - gfx::SNESPalette animated = + gfx::SnesPalette main = GetPalette("ow_main", pal0, previousPalId, 255); + gfx::SnesPalette animated = GetPalette("ow_animated", std::min((int)pal3, 13), previousPalId, 14); - gfx::SNESPalette hud = rom_.palette_group("hud")[0]; + gfx::SnesPalette hud = rom_.palette_group("hud")[0]; - gfx::SNESPalette spr = GetPalette("sprites_aux3", pal4, previousSprPalId, 24); - gfx::SNESPalette spr2 = + gfx::SnesPalette spr = GetPalette("sprites_aux3", pal4, previousSprPalId, 24); + gfx::SnesPalette spr2 = GetPalette("sprites_aux3", pal5, previousSprPalId, 24); palette_internal::SetColorsPalette(rom_, parent_, current_palette_, main, animated, aux1, aux2, hud, bgr, spr, spr2); - gfx::Paletteset paletteset{main, animated, aux1, aux2, bgr, hud, spr, spr2}; - palettesets_[area_graphics_] = paletteset; + if (palettesets_.count(area_palette_) == 0) { + palettesets_[area_palette_] = gfx::Paletteset{ + main, animated, aux1, aux2, bgr, hud, spr, spr2, current_palette_}; + } } // New helper function to process graphics buffer. diff --git a/src/app/zelda3/overworld_map.h b/src/app/zelda3/overworld_map.h index 7e3aaa49..3d17bd77 100644 --- a/src/app/zelda3/overworld_map.h +++ b/src/app/zelda3/overworld_map.h @@ -103,7 +103,7 @@ class OverworldMap : public GfxContext { void LoadDeathMountainGFX(); void ProcessGraphicsBuffer(int index, int static_graphics_offset, int size); - gfx::SNESPalette GetPalette(const std::string& group, int index, + gfx::SnesPalette GetPalette(const std::string& group, int index, int previousIndex, int limit); bool built_ = false; @@ -133,7 +133,7 @@ class OverworldMap : public GfxContext { Bytes bitmap_data_; OWMapTiles map_tiles_; - gfx::SNESPalette current_palette_; + gfx::SnesPalette current_palette_; std::vector tiles16_; }; diff --git a/src/app/zelda3/screen/inventory.h b/src/app/zelda3/screen/inventory.h index 9a50c9e9..e2bd27d1 100644 --- a/src/app/zelda3/screen/inventory.h +++ b/src/app/zelda3/screen/inventory.h @@ -31,7 +31,7 @@ class Inventory : public SharedROM { Bytes tilesheets_; Bytes test_; gfx::Bitmap tilesheets_bmp_; - gfx::SNESPalette palette_; + gfx::SnesPalette palette_; gui::Canvas canvas_; std::vector tiles_; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1aeb1f35..53de6e0c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -34,6 +34,7 @@ add_executable( ../src/app/editor/context/gfx_context.cc ../src/app/gfx/bitmap.cc ../src/app/gfx/snes_tile.cc + ../src/app/gfx/snes_color.cc ../src/app/gfx/snes_palette.cc ../src/app/gfx/compression.cc ../src/app/core/common.cc diff --git a/test/snes_palette_test.cc b/test/snes_palette_test.cc index b72f55c7..fca0672f 100644 --- a/test/snes_palette_test.cc +++ b/test/snes_palette_test.cc @@ -3,6 +3,8 @@ #include #include +#include "app/gfx/snes_color.h" + namespace yaze_test { namespace gfx_test { @@ -12,7 +14,7 @@ using yaze::app::gfx::ConvertSNEStoRGB; using yaze::app::gfx::Extract; using yaze::app::gfx::snes_color; using yaze::app::gfx::snes_palette; -using yaze::app::gfx::SNESPalette; +using yaze::app::gfx::SnesPalette; namespace { unsigned int test_convert(yaze::app::gfx::snes_color col) { @@ -25,15 +27,15 @@ unsigned int test_convert(yaze::app::gfx::snes_color col) { } // namespace TEST(SNESPaletteTest, AddColor) { - yaze::app::gfx::SNESPalette palette; - yaze::app::gfx::SNESColor color; + yaze::app::gfx::SnesPalette palette; + yaze::app::gfx::SnesColor color; palette.AddColor(color); ASSERT_EQ(palette.size(), 1); } TEST(SNESPaletteTest, GetColorOutOfBounds) { - yaze::app::gfx::SNESPalette palette; - std::vector colors(5); + yaze::app::gfx::SnesPalette palette; + std::vector colors(5); palette.Create(colors); // TODO: Fix this test, behavior has changed since the original