From 03a38fc7129b8f4b83addf1fe5242589206dbc30 Mon Sep 17 00:00:00 2001 From: scawful Date: Sun, 7 Apr 2024 12:07:47 -0400 Subject: [PATCH] Add error handling to SnesPalette and SnesColor member fns --- src/app/editor/dungeon_editor.cc | 19 +++--- src/app/editor/dungeon_editor.h | 2 +- src/app/editor/graphics_editor.cc | 18 ++++-- src/app/editor/modules/palette_editor.cc | 27 ++++---- src/app/editor/modules/palette_editor.h | 15 +++-- src/app/editor/modules/tile16_editor.cc | 14 ++-- src/app/editor/modules/tile16_editor.h | 10 +-- src/app/editor/overworld_editor.cc | 12 ++-- src/app/editor/overworld_editor.h | 2 +- src/app/gfx/bitmap.cc | 63 ++++++++++++------ src/app/gfx/bitmap.h | 6 +- src/app/gfx/snes_palette.cc | 2 + src/app/gfx/snes_palette.h | 5 +- src/app/gui/color.cc | 9 +-- src/app/gui/color.h | 3 +- src/app/rom.h | 6 +- src/app/zelda3/overworld_map.cc | 82 +++++++++++++++--------- src/app/zelda3/overworld_map.h | 7 +- src/app/zelda3/screen/inventory.cc | 3 +- 19 files changed, 188 insertions(+), 117 deletions(-) diff --git a/src/app/editor/dungeon_editor.cc b/src/app/editor/dungeon_editor.cc index 7a50a429..cbc96a33 100644 --- a/src/app/editor/dungeon_editor.cc +++ b/src/app/editor/dungeon_editor.cc @@ -59,6 +59,8 @@ absl::Status DungeonEditor::Update() { } absl::Status DungeonEditor::Initialize() { + ASSIGN_OR_RETURN(auto dungeon_man_pal_group, + rom()->palette_group("dungeon_main")); for (int i = 0; i < 0x100 + 40; i++) { rooms_.emplace_back(zelda3::dungeon::Room(i)); rooms_[i].LoadHeader(); @@ -76,8 +78,7 @@ absl::Status DungeonEditor::Initialize() { ASSIGN_OR_RETURN(auto palette_id, rom()->ReadWord(0xDEC4B + dungeon_palette_ptr)); int p_id = palette_id / 180; - auto color = rom()->palette_group("dungeon_main")[p_id][3]; - + auto color = dungeon_man_pal_group[p_id][3]; room_palette_[rooms_[i].palette] = color.rgb(); } @@ -85,8 +86,7 @@ absl::Status DungeonEditor::Initialize() { LoadRoomEntrances(); // Load the palette group and palette for the dungeon - full_palette_ = - rom()->palette_group("dungeon_main")[current_palette_group_id_]; + full_palette_ = dungeon_man_pal_group[current_palette_group_id_]; ASSIGN_OR_RETURN(current_palette_group_, gfx::CreatePaletteGroupFromLargePalette(full_palette_)); @@ -105,10 +105,12 @@ absl::Status DungeonEditor::RefreshGraphics() { current_palette_group_[current_palette_id_], 0); rom()->UpdateBitmap(graphics_bin_[block].get(), true); } + ASSIGN_OR_RETURN(auto sprites_aux1_pal_group, + rom()->palette_group("sprites_aux1")); for (int i = 9; i < 16; i++) { int block = rooms_[current_room_id_].blocks()[i]; graphics_bin_[block].get()->ApplyPaletteWithTransparent( - rom()->palette_group("sprites_aux1")[current_palette_id_], 0); + sprites_aux1_pal_group[current_palette_id_], 0); rom()->UpdateBitmap(graphics_bin_[block].get(), true); } return absl::OkStatus(); @@ -156,13 +158,14 @@ void DungeonEditor::LoadDungeonRoomSize() { } } -void DungeonEditor::UpdateDungeonRoomView() { +absl::Status DungeonEditor::UpdateDungeonRoomView() { DrawToolset(); if (palette_showing_) { ImGui::Begin("Palette Editor", &palette_showing_, 0); - current_palette_ = - rom()->palette_group("dungeon_main")[current_palette_group_id_]; + ASSIGN_OR_RETURN(auto dungeon_main_pal_group, + rom()->palette_group("dungeon_main")); + current_palette_ = dungeon_main_pal_group[current_palette_group_id_]; gui::SelectablePalettePipeline(current_palette_id_, refresh_graphics_, current_palette_); ImGui::End(); diff --git a/src/app/editor/dungeon_editor.h b/src/app/editor/dungeon_editor.h index c7bfa2df..a217dabd 100644 --- a/src/app/editor/dungeon_editor.h +++ b/src/app/editor/dungeon_editor.h @@ -51,7 +51,7 @@ class DungeonEditor : public Editor, void LoadDungeonRoomSize(); - void UpdateDungeonRoomView(); + absl::Status UpdateDungeonRoomView(); void DrawToolset(); void DrawRoomSelector(); diff --git a/src/app/editor/graphics_editor.cc b/src/app/editor/graphics_editor.cc index 5c525a24..69ae514b 100644 --- a/src/app/editor/graphics_editor.cc +++ b/src/app/editor/graphics_editor.cc @@ -321,8 +321,10 @@ absl::Status GraphicsEditor::UpdateGfxTabView() { } absl::Status GraphicsEditor::UpdatePaletteColumn() { - auto palette_group = rom()->palette_group( - kPaletteGroupAddressesKeys[edit_palette_group_name_index_]); + ASSIGN_OR_RETURN( + auto palette_group, + rom()->palette_group( + kPaletteGroupAddressesKeys[edit_palette_group_name_index_])); auto palette = palette_group[edit_palette_index_]; @@ -711,7 +713,7 @@ absl::Status GraphicsEditor::DecompressImportData(int size) { converted_sheet); if (rom()->is_loaded()) { - auto palette_group = rom()->palette_group("ow_main"); + ASSIGN_OR_RETURN(auto palette_group, rom()->palette_group("ow_main")); z3_rom_palette_ = palette_group[current_palette_]; if (col_file_) { bin_bitmap_.ApplyPalette(col_file_palette_); @@ -743,8 +745,9 @@ absl::Status GraphicsEditor::DecompressSuperDonkey() { col_file_palette_group_[current_palette_index_]); } else { // ROM palette - auto palette_group = - rom()->palette_group(kPaletteGroupAddressesKeys[current_palette_]); + ASSIGN_OR_RETURN( + auto palette_group, + rom()->palette_group(kPaletteGroupAddressesKeys[current_palette_])); z3_rom_palette_ = palette_group[current_palette_index_]; graphics_bin_[i].ApplyPalette(z3_rom_palette_); } @@ -768,8 +771,9 @@ absl::Status GraphicsEditor::DecompressSuperDonkey() { col_file_palette_group_[current_palette_index_]); } else { // ROM palette - auto palette_group = - rom()->palette_group(kPaletteGroupAddressesKeys[current_palette_]); + ASSIGN_OR_RETURN( + auto palette_group, + rom()->palette_group(kPaletteGroupAddressesKeys[current_palette_])); z3_rom_palette_ = palette_group[current_palette_index_]; graphics_bin_[i].ApplyPalette(z3_rom_palette_); } diff --git a/src/app/editor/modules/palette_editor.cc b/src/app/editor/modules/palette_editor.cc index b0a3c498..2bd5d7ce 100644 --- a/src/app/editor/modules/palette_editor.cc +++ b/src/app/editor/modules/palette_editor.cc @@ -75,39 +75,42 @@ absl::Status PaletteEditor::Update() { return absl::OkStatus(); } -void PaletteEditor::EditColorInPalette(gfx::SnesPalette& palette, int index) { +absl::Status PaletteEditor::EditColorInPalette(gfx::SnesPalette& palette, + int index) { if (index >= palette.size()) { // Handle error: the index is out of bounds - return; + return absl::InvalidArgumentError("Index out of bounds"); } // Get the current color - auto currentColor = palette.GetColor(index).rgb(); + ASSIGN_OR_RETURN(auto color, palette.GetColor(index)); + auto currentColor = color.rgb(); if (ImGui::ColorPicker4("Color Picker", (float*)&palette[index])) { // The color was modified, update it in the palette palette(index, currentColor); } + return absl::OkStatus(); } -void PaletteEditor::ResetColorToOriginal( +absl::Status PaletteEditor::ResetColorToOriginal( 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; + return absl::InvalidArgumentError("Index out of bounds"); } - - auto originalColor = originalPalette.GetColor(index).rgb(); + ASSIGN_OR_RETURN(auto color, originalPalette.GetColor(index)); + auto originalColor = color.rgb(); palette(index, originalColor); + return absl::OkStatus(); } absl::Status PaletteEditor::DrawPaletteGroup(int category) { if (!rom()->is_loaded()) { return absl::NotFoundError("ROM not open, no palettes to display"); } - - const auto size = - rom()->palette_group(kPaletteGroupNames[category].data()).size(); + ASSIGN_OR_RETURN(auto palette_group, + rom()->palette_group(kPaletteGroupNames[category].data())); + const auto size = palette_group.size(); auto palettes = rom()->mutable_palette_group(kPaletteGroupNames[category].data()); static bool edit_color = false; @@ -129,7 +132,7 @@ absl::Status PaletteEditor::DrawPaletteGroup(int category) { // Small icon of the color in the palette if (gui::SnesColorButton(popup_id, *palette->mutable_color(n), palette_button_flags)) { - current_color_ = palette->GetColor(n); + ASSIGN_OR_RETURN(current_color_, palette->GetColor(n)); // EditColorInPalette(*palette, n); } diff --git a/src/app/editor/modules/palette_editor.h b/src/app/editor/modules/palette_editor.h index 06f7bc68..acf2ff25 100644 --- a/src/app/editor/modules/palette_editor.h +++ b/src/app/editor/modules/palette_editor.h @@ -80,9 +80,9 @@ 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); + absl::Status EditColorInPalette(gfx::SnesPalette& palette, int index); + absl::Status 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); @@ -90,11 +90,12 @@ class PaletteEditor : public SharedROM { private: absl::Status HandleColorPopup(gfx::SnesPalette& palette, int i, int j, int n); - void InitializeSavedPalette(const gfx::SnesPalette& palette) { + absl::Status InitializeSavedPalette(const gfx::SnesPalette& palette) { for (int n = 0; n < palette.size(); n++) { - saved_palette_[n].x = palette.GetColor(n).rgb().x / 255; - saved_palette_[n].y = palette.GetColor(n).rgb().y / 255; - saved_palette_[n].z = palette.GetColor(n).rgb().z / 255; + ASSIGN_OR_RETURN(auto color, palette.GetColor(n)); + saved_palette_[n].x = color.rgb().x / 255; + saved_palette_[n].y = color.rgb().y / 255; + saved_palette_[n].z = color.rgb().z / 255; saved_palette_[n].w = 255; // Alpha } } diff --git a/src/app/editor/modules/tile16_editor.cc b/src/app/editor/modules/tile16_editor.cc index f7ac1c37..13e720ef 100644 --- a/src/app/editor/modules/tile16_editor.cc +++ b/src/app/editor/modules/tile16_editor.cc @@ -107,8 +107,8 @@ absl::Status Tile16Editor::UpdateBlockset() { if (notify_tile16.modified()) { current_tile16_ = notify_tile16.get(); current_tile16_bmp_ = tile16_individual_[notify_tile16]; - current_tile16_bmp_.ApplyPalette( - rom()->palette_group("ow_main")[current_palette_]); + ASSIGN_OR_RETURN(auto ow_main_pal_group, rom()->palette_group("ow_main")); + current_tile16_bmp_.ApplyPalette(ow_main_pal_group[current_palette_]); rom()->RenderBitmap(¤t_tile16_bmp_); } } @@ -150,6 +150,8 @@ absl::Status Tile16Editor::DrawToCurrentTile16(ImVec2 click_position) { } absl::Status Tile16Editor::UpdateTile16Edit() { + ASSIGN_OR_RETURN(auto ow_main_pal_group, rom()->palette_group("ow_main")); + if (ImGui::BeginChild("Tile8 Selector", ImVec2(ImGui::GetContentRegionAvail().x, 0x175), true)) { @@ -157,7 +159,7 @@ absl::Status Tile16Editor::UpdateTile16Edit() { tile8_source_canvas_.DrawContextMenu(); if (tile8_source_canvas_.DrawTileSelector(32)) { current_gfx_individual_[current_tile8_].ApplyPaletteWithTransparent( - rom()->palette_group("ow_main")[0], current_palette_); + ow_main_pal_group[0], current_palette_); rom()->UpdateBitmap(¤t_gfx_individual_[current_tile8_]); } tile8_source_canvas_.DrawBitmap(current_gfx_bmp_, 0, 0, 4.0f); @@ -173,7 +175,7 @@ absl::Status Tile16Editor::UpdateTile16Edit() { current_tile8_ = x + (y * 8); current_gfx_individual_[current_tile8_].ApplyPaletteWithTransparent( - rom()->palette_group("ow_main")[0], current_palette_); + ow_main_pal_group[0], current_palette_); rom()->UpdateBitmap(¤t_gfx_individual_[current_tile8_]); } @@ -244,6 +246,8 @@ absl::Status Tile16Editor::InitBlockset( } absl::Status Tile16Editor::LoadTile8() { + ASSIGN_OR_RETURN(auto ow_main_pal_group, rom()->palette_group("ow_main")); + current_gfx_individual_.reserve(1024); for (int index = 0; index < 1024; index++) { @@ -278,7 +282,7 @@ absl::Status Tile16Editor::LoadTile8() { current_gfx_individual_.emplace_back(); current_gfx_individual_[index].Create(0x08, 0x08, 0x08, tile_data); current_gfx_individual_[index].ApplyPaletteWithTransparent( - rom()->palette_group("ow_main")[0], current_palette_); + ow_main_pal_group[0], current_palette_); rom()->RenderBitmap(¤t_gfx_individual_[index]); } diff --git a/src/app/editor/modules/tile16_editor.h b/src/app/editor/modules/tile16_editor.h index ec5c5640..1fb72bfd 100644 --- a/src/app/editor/modules/tile16_editor.h +++ b/src/app/editor/modules/tile16_editor.h @@ -45,12 +45,13 @@ class Tile16Editor : public GfxContext, public SharedROM { absl::Status LoadTile8(); - auto set_tile16(int id) { + absl::Status set_tile16(int id) { current_tile16_ = id; current_tile16_bmp_ = tile16_individual_[id]; - current_tile16_bmp_.ApplyPalette( - rom()->palette_group("ow_main")[current_palette_]); + ASSIGN_OR_RETURN(auto ow_main_pal_group, rom()->palette_group("ow_main")); + current_tile16_bmp_.ApplyPalette(ow_main_pal_group[current_palette_]); rom()->RenderBitmap(¤t_tile16_bmp_); + return absl::OkStatus(); } private: @@ -86,7 +87,8 @@ class Tile16Editor : public GfxContext, public SharedROM { gfx::Bitmap tile16_blockset_bmp_; // Canvas for editing the selected tile - gui::Canvas tile16_edit_canvas_{ImVec2(0x40, 0x40), gui::CanvasGridSize::k64x64}; + gui::Canvas tile16_edit_canvas_{ImVec2(0x40, 0x40), + gui::CanvasGridSize::k64x64}; gfx::Bitmap current_tile16_bmp_; gfx::Bitmap current_tile8_bmp_; diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index 4c902198..7e3201f4 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -344,21 +344,21 @@ void OverworldEditor::RefreshOverworldMap() { } // TODO: Palette throws out of bounds error unexpectedly. -void OverworldEditor::RefreshMapPalette() { +absl::Status OverworldEditor::RefreshMapPalette() { 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; overworld_.mutable_overworld_map(sibling_index)->LoadPalette(); - maps_bmp_[sibling_index].ApplyPalette( + RETURN_IF_ERROR(maps_bmp_[sibling_index].ApplyPalette( *overworld_.mutable_overworld_map(sibling_index) - ->mutable_current_palette()); + ->mutable_current_palette())); } } - maps_bmp_[current_map_].ApplyPalette( + RETURN_IF_ERROR(maps_bmp_[current_map_].ApplyPalette( *overworld_.mutable_overworld_map(current_map_) - ->mutable_current_palette()); + ->mutable_current_palette())); } void OverworldEditor::RefreshMapProperties() { @@ -415,7 +415,7 @@ void OverworldEditor::DrawOverworldMapSettings() { ->mutable_area_palette(), kInputFieldSize)) { RefreshMapProperties(); - RefreshMapPalette(); + status_ = RefreshMapPalette(); } ImGui::EndGroup(); diff --git a/src/app/editor/overworld_editor.h b/src/app/editor/overworld_editor.h index fcf4f271..54e1efc4 100644 --- a/src/app/editor/overworld_editor.h +++ b/src/app/editor/overworld_editor.h @@ -103,7 +103,7 @@ class OverworldEditor : public Editor, void RefreshChildMap(int i); void RefreshOverworldMap(); - void RefreshMapPalette(); + absl::Status RefreshMapPalette(); void RefreshMapProperties(); void RefreshTile16Blockset(); diff --git a/src/app/gfx/bitmap.cc b/src/app/gfx/bitmap.cc index 03252cde..e61d97b9 100644 --- a/src/app/gfx/bitmap.cc +++ b/src/app/gfx/bitmap.cc @@ -325,54 +325,76 @@ void Bitmap::LoadFromPngData(const std::vector &png_data, int width, } // Convert SNESPalette to SDL_Palette for surface. -void Bitmap::ApplyPalette(const SnesPalette &palette) { +absl::Status Bitmap::ApplyPalette(const SnesPalette &palette) { + if (surface_ == nullptr) { + return absl::FailedPreconditionError("Surface is null"); + } + + if (surface_->format == nullptr || surface_->format->palette == nullptr) { + return absl::FailedPreconditionError("Surface format or palette is null"); + } + palette_ = palette; + + SDL_Palette *sdlPalette = surface_->format->palette; + if (sdlPalette == nullptr) { + return absl::InternalError("Failed to get SDL palette"); + } + SDL_UnlockSurface(surface_.get()); + for (int i = 0; i < palette.size(); ++i) { - if (palette.GetColor(i).is_transparent()) { - surface_->format->palette->colors[i].r = 0; - surface_->format->palette->colors[i].g = 0; - surface_->format->palette->colors[i].b = 0; - surface_->format->palette->colors[i].a = 0; + ASSIGN_OR_RETURN(gfx::SnesColor pal_color, palette.GetColor(i)); + if (pal_color.is_transparent()) { + sdlPalette->colors[i].r = 0; + sdlPalette->colors[i].g = 0; + sdlPalette->colors[i].b = 0; + sdlPalette->colors[i].a = 0; } else { - surface_->format->palette->colors[i].r = palette.GetColor(i).rgb().x; - surface_->format->palette->colors[i].g = palette.GetColor(i).rgb().y; - surface_->format->palette->colors[i].b = palette.GetColor(i).rgb().z; - surface_->format->palette->colors[i].a = palette.GetColor(i).rgb().w; + sdlPalette->colors[i].r = pal_color.rgb().x; + sdlPalette->colors[i].g = pal_color.rgb().y; + sdlPalette->colors[i].b = pal_color.rgb().z; + sdlPalette->colors[i].a = pal_color.rgb().w; } } + SDL_LockSurface(surface_.get()); + + return absl::OkStatus(); } -void Bitmap::ApplyPaletteFromPaletteGroup(const SnesPalette &palette, - int palette_id) { +absl::Status Bitmap::ApplyPaletteFromPaletteGroup(const SnesPalette &palette, + int palette_id) { auto start_index = palette_id * 8; palette_ = palette.sub_palette(start_index, start_index + 8); SDL_UnlockSurface(surface_.get()); for (int i = 0; i < palette_.size(); ++i) { - if (palette_.GetColor(i).is_transparent()) { + ASSIGN_OR_RETURN(auto pal_color, palette_.GetColor(i)); + if (pal_color.is_transparent()) { surface_->format->palette->colors[i].r = 0; surface_->format->palette->colors[i].g = 0; surface_->format->palette->colors[i].b = 0; surface_->format->palette->colors[i].a = 0; } else { - surface_->format->palette->colors[i].r = palette_.GetColor(i).rgb().x; - surface_->format->palette->colors[i].g = palette_.GetColor(i).rgb().y; - surface_->format->palette->colors[i].b = palette_.GetColor(i).rgb().z; - surface_->format->palette->colors[i].a = palette_.GetColor(i).rgb().w; + surface_->format->palette->colors[i].r = pal_color.rgb().x; + surface_->format->palette->colors[i].g = pal_color.rgb().y; + surface_->format->palette->colors[i].b = pal_color.rgb().z; + surface_->format->palette->colors[i].a = pal_color.rgb().w; } } SDL_LockSurface(surface_.get()); + return absl::OkStatus(); } -void Bitmap::ApplyPaletteWithTransparent(const SnesPalette &palette, int index, - int length) { +absl::Status 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; colors.push_back(ImVec4(0, 0, 0, 0)); for (int i = start_index; i < start_index + 7; ++i) { - colors.push_back(palette.GetColor(i).rgb()); + ASSIGN_OR_RETURN(auto pal_color, palette.GetColor(i)); + colors.push_back(pal_color.rgb()); } SDL_UnlockSurface(surface_.get()); @@ -385,6 +407,7 @@ void Bitmap::ApplyPaletteWithTransparent(const SnesPalette &palette, int index, i++; } SDL_LockSurface(surface_.get()); + return absl::OkStatus(); } void Bitmap::ApplyPalette(const std::vector &palette) { diff --git a/src/app/gfx/bitmap.h b/src/app/gfx/bitmap.h index ede665c1..3195124b 100644 --- a/src/app/gfx/bitmap.h +++ b/src/app/gfx/bitmap.h @@ -47,11 +47,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, + absl::Status ApplyPalette(const SnesPalette &palette); + absl::Status ApplyPaletteWithTransparent(const SnesPalette &palette, int index, int length = 7); void ApplyPalette(const std::vector &palette); - void ApplyPaletteFromPaletteGroup(const SnesPalette &palette, int palette_id); + absl::Status ApplyPaletteFromPaletteGroup(const SnesPalette &palette, int palette_id); void WriteToPixel(int position, uchar value) { if (pixel_data_ == nullptr) { diff --git a/src/app/gfx/snes_palette.cc b/src/app/gfx/snes_palette.cc index 4873234a..0183871d 100644 --- a/src/app/gfx/snes_palette.cc +++ b/src/app/gfx/snes_palette.cc @@ -194,9 +194,11 @@ absl::StatusOr CreatePaletteGroupFromLargePalette( for (int i = 0; i < palette.size(); i += 8) { SnesPalette new_palette; if (i + 8 < palette.size()) { + //new_palette.AddColor(SnesColor(ImVec4(0,0,0,0))); for (int j = 0; j < 8; j++) { new_palette.AddColor(palette[i + j]); } + } RETURN_IF_ERROR(toret.AddPalette(new_palette)); diff --git a/src/app/gfx/snes_palette.h b/src/app/gfx/snes_palette.h index 22ae861a..120fc20e 100644 --- a/src/app/gfx/snes_palette.h +++ b/src/app/gfx/snes_palette.h @@ -69,10 +69,9 @@ class SnesPalette { size_++; } - auto GetColor(int i) const { + absl::StatusOr GetColor(int i) const { if (i > size_) { - std::cout << "SNESPalette: Index out of bounds" << std::endl; - return colors[0]; + return absl::InvalidArgumentError("SnesPalette: Index out of bounds"); } return colors[i]; } diff --git a/src/app/gui/color.cc b/src/app/gui/color.cc index 3d2fc7fb..ccf96c94 100644 --- a/src/app/gui/color.cc +++ b/src/app/gui/color.cc @@ -52,7 +52,7 @@ IMGUI_API bool SnesColorEdit4(absl::string_view label, SnesColor& color, return pressed; } -void DisplayPalette(app::gfx::SnesPalette& palette, bool loaded) { +absl::Status DisplayPalette(app::gfx::SnesPalette& palette, bool loaded) { static ImVec4 color = ImVec4(0, 0, 0, 255.f); ImGuiColorEditFlags misc_flags = ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_NoDragDrop | @@ -63,9 +63,10 @@ void DisplayPalette(app::gfx::SnesPalette& palette, bool loaded) { static ImVec4 saved_palette[32] = {}; if (loaded && !init) { for (int n = 0; n < palette.size(); n++) { - saved_palette[n].x = palette.GetColor(n).rgb().x / 255; - saved_palette[n].y = palette.GetColor(n).rgb().y / 255; - saved_palette[n].z = palette.GetColor(n).rgb().z / 255; + ASSIGN_OR_RETURN(auto color, palette.GetColor(n)); + saved_palette[n].x = color.rgb().x / 255; + saved_palette[n].y = color.rgb().y / 255; + saved_palette[n].z = color.rgb().z / 255; saved_palette[n].w = 255; // Alpha } init = true; diff --git a/src/app/gui/color.h b/src/app/gui/color.h index 3ecd3585..1db45db5 100644 --- a/src/app/gui/color.h +++ b/src/app/gui/color.h @@ -6,6 +6,7 @@ #include #include +#include "absl/status/status.h" #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" @@ -27,7 +28,7 @@ IMGUI_API bool SnesColorButton(absl::string_view id, SnesColor& color, IMGUI_API bool SnesColorEdit4(absl::string_view label, SnesColor& color, ImGuiColorEditFlags flags = 0); -void DisplayPalette(app::gfx::SnesPalette& palette, bool loaded); +absl::Status DisplayPalette(app::gfx::SnesPalette& palette, bool loaded); } // namespace gui } // namespace app diff --git a/src/app/rom.h b/src/app/rom.h index 0bf1e3fe..c088ca69 100644 --- a/src/app/rom.h +++ b/src/app/rom.h @@ -497,7 +497,11 @@ class ROM : public core::ExperimentFlags { return core::SnesToPc(snes_addr); } - gfx::PaletteGroup palette_group(const std::string& group) { + absl::StatusOr palette_group(const std::string& group) { + if (palette_groups_.find(group) == palette_groups_.end()) { + return absl::InvalidArgumentError( + absl::StrCat("Palette group ", group, " not found")); + } return palette_groups_[group]; } auto mutable_palette_group(const std::string& group) { diff --git a/src/app/zelda3/overworld_map.cc b/src/app/zelda3/overworld_map.cc index 4ca2c146..56360664 100644 --- a/src/app/zelda3/overworld_map.cc +++ b/src/app/zelda3/overworld_map.cc @@ -49,7 +49,7 @@ absl::Status OverworldMap::BuildMap(int count, int game_state, int world, LoadAreaGraphics(); RETURN_IF_ERROR(BuildTileset()) RETURN_IF_ERROR(BuildTiles16Gfx(count)) - LoadPalette(); + RETURN_IF_ERROR(LoadPalette()); RETURN_IF_ERROR(BuildBitmap(world_blockset)) built_ = true; return absl::OkStatus(); @@ -229,11 +229,11 @@ 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) { +absl::Status 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 @@ -289,7 +289,8 @@ void SetColorsPalette(ROM& rom, int index, gfx::SnesPalette& current, k = 0; for (int y = 8; y < 9; y++) { for (int x = 1; x < 8; x++) { - new_palette[x + (16 * y)] = rom.palette_group("sprites_aux1")[1][k]; + ASSIGN_OR_RETURN(auto pal_group, rom.palette_group("sprites_aux1")); + new_palette[x + (16 * y)] = pal_group[1][k]; k++; } } @@ -298,7 +299,8 @@ void SetColorsPalette(ROM& rom, int index, gfx::SnesPalette& current, k = 0; for (int y = 8; y < 9; y++) { for (int x = 9; x < 16; x++) { - new_palette[x + (16 * y)] = rom.palette_group("sprites_aux3")[0][k]; + ASSIGN_OR_RETURN(auto pal_group, rom.palette_group("sprites_aux3")); + new_palette[x + (16 * y)] = pal_group[0][k]; k++; } } @@ -307,7 +309,8 @@ void SetColorsPalette(ROM& rom, int index, gfx::SnesPalette& current, k = 0; for (int y = 9; y < 13; y++) { for (int x = 1; x < 16; x++) { - new_palette[x + (16 * y)] = rom.palette_group("global_sprites")[0][k]; + ASSIGN_OR_RETURN(auto pal_group, rom.palette_group("global_sprites")); + new_palette[x + (16 * y)] = pal_group[0][k]; k++; } } @@ -334,7 +337,8 @@ void SetColorsPalette(ROM& rom, int index, gfx::SnesPalette& current, k = 0; for (int y = 15; y < 16; y++) { for (int x = 1; x < 16; x++) { - new_palette[x + (16 * y)] = rom.palette_group("armors")[0][k]; + ASSIGN_OR_RETURN(auto pal_group, rom.palette_group("armors")); + new_palette[x + (16 * y)] = pal_group[0][k]; k++; } } @@ -343,12 +347,14 @@ void SetColorsPalette(ROM& rom, int index, gfx::SnesPalette& current, for (int i = 0; i < 256; i++) { current[(i / 16) * 16].set_transparent(true); } + + return absl::OkStatus(); } } // namespace palette_internal // New helper function to get a palette from the ROM. -gfx::SnesPalette OverworldMap::GetPalette(const std::string& group, int index, - int previousIndex, int limit) { +absl::StatusOr OverworldMap::GetPalette( + const std::string& group, int index, int previousIndex, int limit) { if (index == 255) { index = rom_[rom_.version_constants().overworldMapPaletteGroup + (previousIndex * 4)]; @@ -357,13 +363,15 @@ gfx::SnesPalette OverworldMap::GetPalette(const std::string& group, int index, if (index >= limit) { index = limit - 1; } - return rom_.palette_group(group)[index]; + ASSIGN_OR_RETURN(auto pal_group, rom_.palette_group(group)); + return pal_group[index]; } else { - return rom_.palette_group(group)[0]; + ASSIGN_OR_RETURN(auto pal_group, rom_.palette_group(group)); + return pal_group[0]; } } -void OverworldMap::LoadPalette() { +absl::Status OverworldMap::LoadPalette() { int previousPalId = index_ > 0 ? rom_[overworldMapPalette + parent_ - 1] : 0; int previousSprPalId = index_ > 0 ? rom_[overworldSpritePalette + parent_ - 1] : 0; @@ -382,45 +390,59 @@ void OverworldMap::LoadPalette() { uchar pal5 = rom_[overworldSpritePaletteGroup + (sprite_palette_[game_state_] * 2) + 1]; - gfx::SnesColor bgr = rom_.palette_group("grass")[0].GetColor(0); + ASSIGN_OR_RETURN(auto grass_pal_group, rom_.palette_group("grass")); + ASSIGN_OR_RETURN(gfx::SnesColor bgr, grass_pal_group[0].GetColor(0)); - gfx::SnesPalette aux1 = GetPalette("ow_aux", pal1, previousPalId, 20); - gfx::SnesPalette aux2 = GetPalette("ow_aux", pal2, previousPalId, 20); + ASSIGN_OR_RETURN(gfx::SnesPalette aux1, + GetPalette("ow_aux", pal1, previousPalId, 20)); + ASSIGN_OR_RETURN(gfx::SnesPalette aux2, + GetPalette("ow_aux", pal2, previousPalId, 20)); // Additional handling of `pal3` and `parent_` if (pal3 == 255) { pal3 = rom_[rom_.version_constants().overworldMapPaletteGroup + (previousPalId * 4) + 2]; } + if (parent_ < 0x40) { pal0 = parent_ == 0x03 || parent_ == 0x05 || parent_ == 0x07 ? 2 : 0; - bgr = rom_.palette_group("grass")[0].GetColor(0); + ASSIGN_OR_RETURN(bgr, grass_pal_group[0].GetColor(0)); } else if (parent_ >= 0x40 && parent_ < 0x80) { pal0 = parent_ == 0x43 || parent_ == 0x45 || parent_ == 0x47 ? 3 : 1; - bgr = rom_.palette_group("grass")[0].GetColor(1); + ASSIGN_OR_RETURN(bgr, grass_pal_group[0].GetColor(1)); } else if (parent_ >= 128 && parent_ < kNumOverworldMaps) { pal0 = 0; - bgr = rom_.palette_group("grass")[0].GetColor(2); + ASSIGN_OR_RETURN(bgr, grass_pal_group[0].GetColor(2)); } + if (parent_ == 0x88) { pal0 = 4; } - 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 spr = GetPalette("sprites_aux3", pal4, previousSprPalId, 24); - gfx::SnesPalette spr2 = - GetPalette("sprites_aux3", pal5, previousSprPalId, 24); + ASSIGN_OR_RETURN(gfx::SnesPalette main, + GetPalette("ow_main", pal0, previousPalId, 255)); + ASSIGN_OR_RETURN( + gfx::SnesPalette animated, + GetPalette("ow_animated", std::min((int)pal3, 13), previousPalId, 14)); - palette_internal::SetColorsPalette(rom_, parent_, current_palette_, main, - animated, aux1, aux2, hud, bgr, spr, spr2); + ASSIGN_OR_RETURN(auto hud_pal_group, rom_.palette_group("hud")); + gfx::SnesPalette hud = hud_pal_group[0]; + + ASSIGN_OR_RETURN(gfx::SnesPalette spr, + GetPalette("sprites_aux3", pal4, previousSprPalId, 24)); + ASSIGN_OR_RETURN(gfx::SnesPalette spr2, + GetPalette("sprites_aux3", pal5, previousSprPalId, 24)); + + RETURN_IF_ERROR(palette_internal::SetColorsPalette( + rom_, parent_, current_palette_, main, animated, aux1, aux2, hud, bgr, + spr, spr2)); if (palettesets_.count(area_palette_) == 0) { palettesets_[area_palette_] = gfx::Paletteset{ main, animated, aux1, aux2, bgr, hud, spr, spr2, current_palette_}; } + + return absl::OkStatus(); } // New helper function to process graphics buffer. diff --git a/src/app/zelda3/overworld_map.h b/src/app/zelda3/overworld_map.h index f672a89c..ac2740fa 100644 --- a/src/app/zelda3/overworld_map.h +++ b/src/app/zelda3/overworld_map.h @@ -34,7 +34,7 @@ class OverworldMap : public GfxContext { OWBlockset& world_blockset); void LoadAreaGraphics(); - void LoadPalette(); + absl::Status LoadPalette(); absl::Status BuildTileset(); absl::Status BuildTiles16Gfx(int count); absl::Status BuildBitmap(OWBlockset& world_blockset); @@ -108,8 +108,9 @@ 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, - int previousIndex, int limit); + absl::StatusOr GetPalette(const std::string& group, + int index, int previousIndex, + int limit); bool built_ = false; bool large_map_ = false; diff --git a/src/app/zelda3/screen/inventory.cc b/src/app/zelda3/screen/inventory.cc index afe41d31..7dcf1fff 100644 --- a/src/app/zelda3/screen/inventory.cc +++ b/src/app/zelda3/screen/inventory.cc @@ -79,7 +79,8 @@ absl::Status Inventory::BuildTileset() { test_.push_back(tilesheets_[i]); } tilesheets_bmp_.Create(128, 0x130, 64, test_); - palette_ = rom()->palette_group("hud")[0]; + ASSIGN_OR_RETURN(auto hud_pal_group, rom()->palette_group("hud")); + palette_ = hud_pal_group[0]; tilesheets_bmp_.ApplyPalette(palette_); rom()->RenderBitmap(&tilesheets_bmp_); return absl::OkStatus();