Refactor bitmap palette management across various components to streamline palette setting and improve error handling; remove unnecessary status checks and enhance consistency in palette application methods.

This commit is contained in:
scawful
2025-04-17 21:49:47 -04:00
parent eeab477e72
commit 44e13cf4bb
17 changed files with 253 additions and 316 deletions

View File

@@ -60,9 +60,7 @@ class Renderer {
const std::vector<uint8_t> &data, const std::vector<uint8_t> &data,
gfx::Bitmap &bitmap, gfx::SnesPalette &palette) { gfx::Bitmap &bitmap, gfx::SnesPalette &palette) {
bitmap.Create(width, height, depth, data); bitmap.Create(width, height, depth, data);
if (!bitmap.SetPalette(palette).ok()) { bitmap.SetPalette(palette);
throw std::runtime_error("Failed to set palette");
}
RenderBitmap(&bitmap); RenderBitmap(&bitmap);
} }

View File

@@ -115,24 +115,22 @@ absl::Status DungeonEditor::Update() {
} }
absl::Status DungeonEditor::RefreshGraphics() { absl::Status DungeonEditor::RefreshGraphics() {
std::for_each_n( std::for_each_n(rooms_[current_room_id_].blocks().begin(), 8,
rooms_[current_room_id_].blocks().begin(), 8, [this](int block) -> absl::Status {
[this](int block) -> absl::Status { graphics_bin_[block].SetPaletteWithTransparent(
RETURN_IF_ERROR(graphics_bin_[block].SetPaletteWithTransparent( current_palette_group_[current_palette_id_], 0);
current_palette_group_[current_palette_id_], 0)); Renderer::GetInstance().UpdateBitmap(&graphics_bin_[block]);
Renderer::GetInstance().UpdateBitmap(&graphics_bin_[block]); return absl::OkStatus();
return absl::OkStatus(); });
});
auto sprites_aux1_pal_group = rom()->palette_group().sprites_aux1; auto sprites_aux1_pal_group = rom()->palette_group().sprites_aux1;
std::for_each_n( std::for_each_n(rooms_[current_room_id_].blocks().begin() + 8, 8,
rooms_[current_room_id_].blocks().begin() + 8, 8, [this, &sprites_aux1_pal_group](int block) -> absl::Status {
[this, &sprites_aux1_pal_group](int block) -> absl::Status { graphics_bin_[block].SetPaletteWithTransparent(
RETURN_IF_ERROR(graphics_bin_[block].SetPaletteWithTransparent( sprites_aux1_pal_group[current_palette_id_], 0);
sprites_aux1_pal_group[current_palette_id_], 0)); Renderer::GetInstance().UpdateBitmap(&graphics_bin_[block]);
Renderer::GetInstance().UpdateBitmap(&graphics_bin_[block]); return absl::OkStatus();
return absl::OkStatus(); });
});
return absl::OkStatus(); return absl::OkStatus();
} }

View File

@@ -4,6 +4,7 @@
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "app/core/platform/clipboard.h" #include "app/core/platform/clipboard.h"
#include "app/core/platform/file_dialog.h" #include "app/core/platform/file_dialog.h"
#include "app/core/platform/renderer.h" #include "app/core/platform/renderer.h"
@@ -42,10 +43,7 @@ constexpr ImGuiTableFlags kGfxEditTableFlags =
void GraphicsEditor::Initialize() {} void GraphicsEditor::Initialize() {}
absl::Status GraphicsEditor::Load() { absl::Status GraphicsEditor::Load() { return absl::OkStatus(); }
return absl::OkStatus();
}
absl::Status GraphicsEditor::Update() { absl::Status GraphicsEditor::Update() {
if (ImGui::BeginTabBar("##TabBar")) { if (ImGui::BeginTabBar("##TabBar")) {
@@ -374,11 +372,10 @@ absl::Status GraphicsEditor::UpdatePaletteColumn() {
palette); palette);
if (refresh_graphics_ && !open_sheets_.empty()) { if (refresh_graphics_ && !open_sheets_.empty()) {
RETURN_IF_ERROR( GraphicsSheetManager::GetInstance()
GraphicsSheetManager::GetInstance() .mutable_gfx_sheets()
.mutable_gfx_sheets() ->data()[current_sheet_]
->data()[current_sheet_] .SetPaletteWithTransparent(palette, edit_palette_sub_index_);
.SetPaletteWithTransparent(palette, edit_palette_sub_index_));
Renderer::GetInstance().UpdateBitmap(&GraphicsSheetManager::GetInstance() Renderer::GetInstance().UpdateBitmap(&GraphicsSheetManager::GetInstance()
.mutable_gfx_sheets() .mutable_gfx_sheets()
->data()[current_sheet_]); ->data()[current_sheet_]);
@@ -777,9 +774,9 @@ absl::Status GraphicsEditor::DecompressImportData(int size) {
auto palette_group = rom()->palette_group().overworld_animated; auto palette_group = rom()->palette_group().overworld_animated;
z3_rom_palette_ = palette_group[current_palette_]; z3_rom_palette_ = palette_group[current_palette_];
if (col_file_) { if (col_file_) {
status_ = bin_bitmap_.SetPalette(col_file_palette_); bin_bitmap_.SetPalette(col_file_palette_);
} else { } else {
status_ = bin_bitmap_.SetPalette(z3_rom_palette_); bin_bitmap_.SetPalette(z3_rom_palette_);
} }
} }
@@ -801,7 +798,7 @@ absl::Status GraphicsEditor::DecompressSuperDonkey() {
gfx_sheets_[i] = gfx::Bitmap(gfx::kTilesheetWidth, gfx::kTilesheetHeight, gfx_sheets_[i] = gfx::Bitmap(gfx::kTilesheetWidth, gfx::kTilesheetHeight,
gfx::kTilesheetDepth, converted_sheet); gfx::kTilesheetDepth, converted_sheet);
if (col_file_) { if (col_file_) {
status_ = gfx_sheets_[i].SetPalette( gfx_sheets_[i].SetPalette(
col_file_palette_group_[current_palette_index_]); col_file_palette_group_[current_palette_index_]);
} else { } else {
// ROM palette // ROM palette
@@ -809,7 +806,7 @@ absl::Status GraphicsEditor::DecompressSuperDonkey() {
auto palette_group = rom()->palette_group().get_group( auto palette_group = rom()->palette_group().get_group(
kPaletteGroupAddressesKeys[current_palette_]); kPaletteGroupAddressesKeys[current_palette_]);
z3_rom_palette_ = *palette_group->mutable_palette(current_palette_index_); z3_rom_palette_ = *palette_group->mutable_palette(current_palette_index_);
status_ = gfx_sheets_[i].SetPalette(z3_rom_palette_); gfx_sheets_[i].SetPalette(z3_rom_palette_);
} }
Renderer::GetInstance().RenderBitmap(&gfx_sheets_[i]); Renderer::GetInstance().RenderBitmap(&gfx_sheets_[i]);
@@ -826,14 +823,14 @@ absl::Status GraphicsEditor::DecompressSuperDonkey() {
gfx_sheets_[i] = gfx::Bitmap(gfx::kTilesheetWidth, gfx::kTilesheetHeight, gfx_sheets_[i] = gfx::Bitmap(gfx::kTilesheetWidth, gfx::kTilesheetHeight,
gfx::kTilesheetDepth, converted_sheet); gfx::kTilesheetDepth, converted_sheet);
if (col_file_) { if (col_file_) {
status_ = gfx_sheets_[i].SetPalette( gfx_sheets_[i].SetPalette(
col_file_palette_group_[current_palette_index_]); col_file_palette_group_[current_palette_index_]);
} else { } else {
// ROM palette // ROM palette
auto palette_group = rom()->palette_group().get_group( auto palette_group = rom()->palette_group().get_group(
kPaletteGroupAddressesKeys[current_palette_]); kPaletteGroupAddressesKeys[current_palette_]);
z3_rom_palette_ = *palette_group->mutable_palette(current_palette_index_); z3_rom_palette_ = *palette_group->mutable_palette(current_palette_index_);
status_ = gfx_sheets_[i].SetPalette(z3_rom_palette_); gfx_sheets_[i].SetPalette(z3_rom_palette_);
} }
Renderer::GetInstance().RenderBitmap(&gfx_sheets_[i]); Renderer::GetInstance().RenderBitmap(&gfx_sheets_[i]);

View File

@@ -253,15 +253,14 @@ absl::Status ScreenEditor::LoadDungeonMapTile16(
tile16_sheet_.ComposeTile16(gfx_data, t1, t2, t3, t4, sheet_offset); tile16_sheet_.ComposeTile16(gfx_data, t1, t2, t3, t4, sheet_offset);
} }
RETURN_IF_ERROR(tile16_sheet_.mutable_bitmap()->SetPalette( tile16_sheet_.mutable_bitmap()->SetPalette(
*rom()->mutable_dungeon_palette(3))); *rom()->mutable_dungeon_palette(3));
Renderer::GetInstance().RenderBitmap(&*tile16_sheet_.mutable_bitmap().get()); Renderer::GetInstance().RenderBitmap(&*tile16_sheet_.mutable_bitmap().get());
for (int i = 0; i < tile16_sheet_.num_tiles(); ++i) { for (int i = 0; i < tile16_sheet_.num_tiles(); ++i) {
auto tile = tile16_sheet_.GetTile16(i); auto tile = tile16_sheet_.GetTile16(i);
tile16_individual_[i] = tile; tile16_individual_[i] = tile;
RETURN_IF_ERROR( tile16_individual_[i].SetPalette(*rom()->mutable_dungeon_palette(3));
tile16_individual_[i].SetPalette(*rom()->mutable_dungeon_palette(3)));
Renderer::GetInstance().RenderBitmap(&tile16_individual_[i]); Renderer::GetInstance().RenderBitmap(&tile16_individual_[i]);
} }
@@ -447,8 +446,8 @@ void ScreenEditor::DrawDungeonMapsRoomGfx() {
current_tile16_info.tiles[3], selected_tile16_, 212); current_tile16_info.tiles[3], selected_tile16_, 212);
tile16_individual_[selected_tile16_] = tile16_individual_[selected_tile16_] =
tile16_sheet_.GetTile16(selected_tile16_); tile16_sheet_.GetTile16(selected_tile16_);
RETURN_VOID_IF_ERROR(tile16_individual_[selected_tile16_].SetPalette( tile16_individual_[selected_tile16_].SetPalette(
*rom()->mutable_dungeon_palette(3))); *rom()->mutable_dungeon_palette(3));
Renderer::GetInstance().RenderBitmap( Renderer::GetInstance().RenderBitmap(
&tile16_individual_[selected_tile16_]); &tile16_individual_[selected_tile16_]);
} }
@@ -478,8 +477,8 @@ void ScreenEditor::DrawDungeonMapsEditor() {
int y = (j / 8) * 8; int y = (j / 8) * 8;
sheets_[i].Get8x8Tile(tile_index, 0, 0, tile_data, tile_data_offset); sheets_[i].Get8x8Tile(tile_index, 0, 0, tile_data, tile_data_offset);
tile8_individual_.emplace_back(gfx::Bitmap(8, 8, 4, tile_data)); tile8_individual_.emplace_back(gfx::Bitmap(8, 8, 4, tile_data));
RETURN_VOID_IF_ERROR(tile8_individual_.back().SetPalette( tile8_individual_.back().SetPalette(
*rom()->mutable_dungeon_palette(3))); *rom()->mutable_dungeon_palette(3));
Renderer::GetInstance().RenderBitmap(&tile8_individual_.back()); Renderer::GetInstance().RenderBitmap(&tile8_individual_.back());
} }
tile_data_offset = 0; tile_data_offset = 0;
@@ -579,10 +578,8 @@ void ScreenEditor::LoadBinaryGfx() {
gfx_sheets.emplace_back(converted_bin.begin() + (i * 0x1000), gfx_sheets.emplace_back(converted_bin.begin() + (i * 0x1000),
converted_bin.begin() + ((i + 1) * 0x1000)); converted_bin.begin() + ((i + 1) * 0x1000));
sheets_.emplace(i, gfx::Bitmap(128, 32, 8, gfx_sheets[i])); sheets_.emplace(i, gfx::Bitmap(128, 32, 8, gfx_sheets[i]));
status_ = sheets_[i].SetPalette(*rom()->mutable_dungeon_palette(3)); sheets_[i].SetPalette(*rom()->mutable_dungeon_palette(3));
if (status_.ok()) { Renderer::GetInstance().RenderBitmap(&sheets_[i]);
Renderer::GetInstance().RenderBitmap(&sheets_[i]);
}
} }
binary_gfx_loaded_ = true; binary_gfx_loaded_ = true;
} else { } else {

View File

@@ -27,13 +27,12 @@ absl::Status Tile16Editor::Initialize(
all_tiles_types_ = all_tiles_types; all_tiles_types_ = all_tiles_types;
current_gfx_bmp_.Create(current_gfx_bmp.width(), current_gfx_bmp.height(), current_gfx_bmp_.Create(current_gfx_bmp.width(), current_gfx_bmp.height(),
current_gfx_bmp.depth(), current_gfx_bmp.vector()); current_gfx_bmp.depth(), current_gfx_bmp.vector());
RETURN_IF_ERROR(current_gfx_bmp_.SetPalette(current_gfx_bmp.palette())); current_gfx_bmp_.SetPalette(current_gfx_bmp.palette());
core::Renderer::GetInstance().RenderBitmap(&current_gfx_bmp_); core::Renderer::GetInstance().RenderBitmap(&current_gfx_bmp_);
tile16_blockset_bmp_.Create( tile16_blockset_bmp_.Create(
tile16_blockset_bmp.width(), tile16_blockset_bmp.height(), tile16_blockset_bmp.width(), tile16_blockset_bmp.height(),
tile16_blockset_bmp.depth(), tile16_blockset_bmp.vector()); tile16_blockset_bmp.depth(), tile16_blockset_bmp.vector());
RETURN_IF_ERROR( tile16_blockset_bmp_.SetPalette(tile16_blockset_bmp.palette());
tile16_blockset_bmp_.SetPalette(tile16_blockset_bmp.palette()));
core::Renderer::GetInstance().RenderBitmap(&tile16_blockset_bmp_); core::Renderer::GetInstance().RenderBitmap(&tile16_blockset_bmp_);
RETURN_IF_ERROR(LoadTile8()); RETURN_IF_ERROR(LoadTile8());
// current_gfx_individual_ = gfx::ExtractTile8Bitmaps( // current_gfx_individual_ = gfx::ExtractTile8Bitmaps(
@@ -190,8 +189,7 @@ absl::Status Tile16Editor::UpdateBlockset() {
current_tile16_ = notify_tile16.get(); current_tile16_ = notify_tile16.get();
current_tile16_bmp_ = (*tile16_individual_)[notify_tile16]; current_tile16_bmp_ = (*tile16_individual_)[notify_tile16];
auto ow_main_pal_group = rom()->palette_group().overworld_main; auto ow_main_pal_group = rom()->palette_group().overworld_main;
RETURN_IF_ERROR( current_tile16_bmp_.SetPalette(ow_main_pal_group[current_palette_]);
current_tile16_bmp_.SetPalette(ow_main_pal_group[current_palette_]));
Renderer::GetInstance().RenderBitmap(&current_tile16_bmp_); Renderer::GetInstance().RenderBitmap(&current_tile16_bmp_);
} }
} }
@@ -276,9 +274,8 @@ absl::Status Tile16Editor::UpdateTile16Edit() {
tile8_source_canvas_.DrawBackground(); tile8_source_canvas_.DrawBackground();
tile8_source_canvas_.DrawContextMenu(); tile8_source_canvas_.DrawContextMenu();
if (tile8_source_canvas_.DrawTileSelector(32)) { if (tile8_source_canvas_.DrawTileSelector(32)) {
RETURN_IF_ERROR(current_gfx_individual_[current_tile8_] current_gfx_individual_[current_tile8_].SetPaletteWithTransparent(
.SetPaletteWithTransparent(ow_main_pal_group[0], ow_main_pal_group[0], current_palette_);
current_palette_));
Renderer::GetInstance().UpdateBitmap( Renderer::GetInstance().UpdateBitmap(
&current_gfx_individual_[current_tile8_]); &current_gfx_individual_[current_tile8_]);
} }
@@ -347,12 +344,10 @@ absl::Status Tile16Editor::UpdateTile16Edit() {
} }
if (value > 0x00) { if (value > 0x00) {
RETURN_IF_ERROR( current_gfx_bmp_.SetPaletteWithTransparent(palette, value);
current_gfx_bmp_.SetPaletteWithTransparent(palette, value));
Renderer::GetInstance().UpdateBitmap(&current_gfx_bmp_); Renderer::GetInstance().UpdateBitmap(&current_gfx_bmp_);
RETURN_IF_ERROR( current_tile16_bmp_.SetPaletteWithTransparent(palette, value);
current_tile16_bmp_.SetPaletteWithTransparent(palette, value));
Renderer::GetInstance().UpdateBitmap(&current_tile16_bmp_); Renderer::GetInstance().UpdateBitmap(&current_tile16_bmp_);
} }
} }
@@ -428,9 +423,8 @@ absl::Status Tile16Editor::UpdateTile16Edit() {
uint16_t y = tile8_source_canvas_.points().front().y / 16; uint16_t y = tile8_source_canvas_.points().front().y / 16;
current_tile8_ = x + (y * 8); current_tile8_ = x + (y * 8);
RETURN_IF_ERROR( current_gfx_individual_[current_tile8_].SetPaletteWithTransparent(
current_gfx_individual_[current_tile8_].SetPaletteWithTransparent( ow_main_pal_group[0], current_palette_);
ow_main_pal_group[0], current_palette_));
Renderer::GetInstance().UpdateBitmap( Renderer::GetInstance().UpdateBitmap(
&current_gfx_individual_[current_tile8_]); &current_gfx_individual_[current_tile8_]);
} }
@@ -481,8 +475,8 @@ absl::Status Tile16Editor::LoadTile8() {
current_gfx_individual_.emplace_back(); current_gfx_individual_.emplace_back();
auto &tile_bitmap = current_gfx_individual_.back(); auto &tile_bitmap = current_gfx_individual_.back();
tile_bitmap.Create(0x08, 0x08, 0x08, tile_data); tile_bitmap.Create(0x08, 0x08, 0x08, tile_data);
RETURN_IF_ERROR(tile_bitmap.SetPaletteWithTransparent(ow_main_pal_group[0], tile_bitmap.SetPaletteWithTransparent(ow_main_pal_group[0],
current_palette_)); current_palette_);
Renderer::GetInstance().RenderBitmap(&tile_bitmap); Renderer::GetInstance().RenderBitmap(&tile_bitmap);
} }
@@ -495,8 +489,7 @@ absl::Status Tile16Editor::SetCurrentTile(int id) {
current_tile16_ = id; current_tile16_ = id;
current_tile16_bmp_ = (*tile16_individual_)[id]; current_tile16_bmp_ = (*tile16_individual_)[id];
auto ow_main_pal_group = rom()->palette_group().overworld_main; auto ow_main_pal_group = rom()->palette_group().overworld_main;
RETURN_IF_ERROR( current_tile16_bmp_.SetPalette(ow_main_pal_group[current_palette_]);
current_tile16_bmp_.SetPalette(ow_main_pal_group[current_palette_]));
Renderer::GetInstance().RenderBitmap(&current_tile16_bmp_); Renderer::GetInstance().RenderBitmap(&current_tile16_bmp_);
return absl::OkStatus(); return absl::OkStatus();
} }
@@ -569,8 +562,7 @@ absl::Status Tile16Editor::CopyTile16ToClipboard(int tile_id) {
// Create a copy of the tile16 bitmap // Create a copy of the tile16 bitmap
clipboard_tile16_.Create(16, 16, 8, (*tile16_individual_)[tile_id].vector()); clipboard_tile16_.Create(16, 16, 8, (*tile16_individual_)[tile_id].vector());
RETURN_IF_ERROR( clipboard_tile16_.SetPalette((*tile16_individual_)[tile_id].palette());
clipboard_tile16_.SetPalette((*tile16_individual_)[tile_id].palette()));
core::Renderer::GetInstance().RenderBitmap(&clipboard_tile16_); core::Renderer::GetInstance().RenderBitmap(&clipboard_tile16_);
clipboard_has_data_ = true; clipboard_has_data_ = true;
@@ -584,7 +576,7 @@ absl::Status Tile16Editor::PasteTile16FromClipboard() {
// Copy the clipboard data to the current tile16 // Copy the clipboard data to the current tile16
current_tile16_bmp_.Create(16, 16, 8, clipboard_tile16_.vector()); current_tile16_bmp_.Create(16, 16, 8, clipboard_tile16_.vector());
RETURN_IF_ERROR(current_tile16_bmp_.SetPalette(clipboard_tile16_.palette())); current_tile16_bmp_.SetPalette(clipboard_tile16_.palette());
core::Renderer::GetInstance().RenderBitmap(&current_tile16_bmp_); core::Renderer::GetInstance().RenderBitmap(&current_tile16_bmp_);
return absl::OkStatus(); return absl::OkStatus();
@@ -597,8 +589,7 @@ absl::Status Tile16Editor::SaveTile16ToScratchSpace(int slot) {
// Create a copy of the current tile16 bitmap // Create a copy of the current tile16 bitmap
scratch_space_[slot].Create(16, 16, 8, current_tile16_bmp_.vector()); scratch_space_[slot].Create(16, 16, 8, current_tile16_bmp_.vector());
RETURN_IF_ERROR( scratch_space_[slot].SetPalette(current_tile16_bmp_.palette());
scratch_space_[slot].SetPalette(current_tile16_bmp_.palette()));
core::Renderer::GetInstance().RenderBitmap(&scratch_space_[slot]); core::Renderer::GetInstance().RenderBitmap(&scratch_space_[slot]);
scratch_space_used_[slot] = true; scratch_space_used_[slot] = true;
@@ -616,8 +607,7 @@ absl::Status Tile16Editor::LoadTile16FromScratchSpace(int slot) {
// Copy the scratch space data to the current tile16 // Copy the scratch space data to the current tile16
current_tile16_bmp_.Create(16, 16, 8, scratch_space_[slot].vector()); current_tile16_bmp_.Create(16, 16, 8, scratch_space_[slot].vector());
RETURN_IF_ERROR( current_tile16_bmp_.SetPalette(scratch_space_[slot].palette());
current_tile16_bmp_.SetPalette(scratch_space_[slot].palette()));
core::Renderer::GetInstance().RenderBitmap(&current_tile16_bmp_); core::Renderer::GetInstance().RenderBitmap(&current_tile16_bmp_);
return absl::OkStatus(); return absl::OkStatus();

View File

@@ -1068,7 +1068,7 @@ absl::Status OverworldEditor::LoadGraphics() {
} }
} }
RETURN_IF_ERROR(tile16_individual_[i].SetPalette(palette_)); tile16_individual_[i].SetPalette(palette_);
Renderer::GetInstance().RenderBitmap(&tile16_individual_[i]); Renderer::GetInstance().RenderBitmap(&tile16_individual_[i]);
} }
@@ -1109,7 +1109,7 @@ absl::Status OverworldEditor::LoadSpriteGraphics() {
} }
sprite_previews_[sprite.id()].Create(width, height, depth, sprite_previews_[sprite.id()].Create(width, height, depth,
*sprite.preview_graphics()); *sprite.preview_graphics());
RETURN_IF_ERROR(sprite_previews_[sprite.id()].SetPalette(palette_)); sprite_previews_[sprite.id()].SetPalette(palette_);
Renderer::GetInstance().RenderBitmap(&(sprite_previews_[sprite.id()])); Renderer::GetInstance().RenderBitmap(&(sprite_previews_[sprite.id()]));
} }
return absl::OkStatus(); return absl::OkStatus();
@@ -1178,11 +1178,11 @@ absl::Status OverworldEditor::RefreshMapPalette() {
if (i >= 2) sibling_index += 6; if (i >= 2) sibling_index += 6;
RETURN_IF_ERROR( RETURN_IF_ERROR(
overworld_.mutable_overworld_map(sibling_index)->LoadPalette()); overworld_.mutable_overworld_map(sibling_index)->LoadPalette());
RETURN_IF_ERROR(maps_bmp_[sibling_index].SetPalette(current_map_palette)); maps_bmp_[sibling_index].SetPalette(current_map_palette);
} }
} }
RETURN_IF_ERROR(maps_bmp_[current_map_].SetPalette(current_map_palette)); maps_bmp_[current_map_].SetPalette(current_map_palette);
return absl::OkStatus(); return absl::OkStatus();
} }
@@ -1218,7 +1218,7 @@ absl::Status OverworldEditor::RefreshTile16Blockset() {
palette_ = overworld_.current_area_palette(); palette_ = overworld_.current_area_palette();
// Create the tile16 blockset image // Create the tile16 blockset image
Renderer::GetInstance().UpdateBitmap(&tile16_blockset_bmp_); Renderer::GetInstance().UpdateBitmap(&tile16_blockset_bmp_);
RETURN_IF_ERROR(tile16_blockset_bmp_.SetPalette(palette_)); tile16_blockset_bmp_.SetPalette(palette_);
// Copy the tile16 data into individual tiles. // Copy the tile16 data into individual tiles.
const auto tile16_data = overworld_.tile16_blockset_data(); const auto tile16_data = overworld_.tile16_blockset_data();
@@ -1240,7 +1240,7 @@ absl::Status OverworldEditor::RefreshTile16Blockset() {
} }
} }
tile16_individual_[index].set_data(tile_data); tile16_individual_[index].set_data(tile_data);
RETURN_IF_ERROR(tile16_individual_[index].SetPalette(palette_)); tile16_individual_[index].SetPalette(palette_);
return absl::OkStatus(); return absl::OkStatus();
}, },
i)); i));

View File

@@ -8,13 +8,11 @@
#include <cstdint> #include <cstdint>
#include <future> #include <future>
#include <memory> #include <memory>
#include <iostream>
#include "absl/status/status.h"
#include "app/core/platform/memory_tracker.h" #include "app/core/platform/memory_tracker.h"
#include "app/core/platform/sdl_deleter.h"
#include "app/gfx/snes_palette.h" #include "app/gfx/snes_palette.h"
#include "app/gfx/texture_pool.h" #include "app/gfx/texture_pool.h"
#include "util/macro.h"
namespace yaze { namespace yaze {
namespace gfx { namespace gfx {
@@ -202,7 +200,7 @@ Uint32 GetSnesPixelFormat(int format) {
} }
// Custom allocator for SDL_Surface // Custom allocator for SDL_Surface
SDL_Surface* AllocateSurface(int width, int height, int depth, Uint32 format) { SDL_Surface *AllocateSurface(int width, int height, int depth, Uint32 format) {
SDL_Surface *surface = SDL_Surface *surface =
SDL_CreateRGBSurfaceWithFormat(0, width, height, depth, format); SDL_CreateRGBSurfaceWithFormat(0, width, height, depth, format);
if (surface) { if (surface) {
@@ -213,7 +211,7 @@ SDL_Surface* AllocateSurface(int width, int height, int depth, Uint32 format) {
} }
// Custom allocator for SDL_Texture // Custom allocator for SDL_Texture
SDL_Texture* AllocateTexture(SDL_Renderer *renderer, Uint32 format, int access, SDL_Texture *AllocateTexture(SDL_Renderer *renderer, Uint32 format, int access,
int width, int height) { int width, int height) {
SDL_Texture *texture = SDL_Texture *texture =
SDL_CreateTexture(renderer, format, access, width, height); SDL_CreateTexture(renderer, format, access, width, height);
@@ -227,22 +225,21 @@ SDL_Texture* AllocateTexture(SDL_Renderer *renderer, Uint32 format, int access,
} }
// Bitmap class implementation // Bitmap class implementation
Bitmap::Bitmap(int width, int height, int depth, const std::vector<uint8_t> &data) Bitmap::Bitmap(int width, int height, int depth,
const std::vector<uint8_t> &data)
: width_(width), height_(height), depth_(depth), data_(data) { : width_(width), height_(height), depth_(depth), data_(data) {
Create(width, height, depth, data); Create(width, height, depth, data);
} }
Bitmap::Bitmap(int width, int height, int depth, const std::vector<uint8_t> &data, Bitmap::Bitmap(int width, int height, int depth,
const SnesPalette &palette) const std::vector<uint8_t> &data, const SnesPalette &palette)
: width_(width), : width_(width),
height_(height), height_(height),
depth_(depth), depth_(depth),
data_(data), data_(data),
palette_(palette) { palette_(palette) {
Create(width, height, depth, data); Create(width, height, depth, data);
if (!SetPalette(palette).ok()) { SetPalette(palette);
std::cerr << "Error applying palette in bitmap constructor." << std::endl;
}
} }
void Bitmap::SaveSurfaceToFile(std::string_view filename) { void Bitmap::SaveSurfaceToFile(std::string_view filename) {
@@ -305,11 +302,7 @@ void Bitmap::Reformat(int format) {
SDL_Surface_Deleter()); SDL_Surface_Deleter());
surface_->pixels = pixel_data_; surface_->pixels = pixel_data_;
active_ = true; active_ = true;
auto apply_palette = SetPalette(palette_); SetPalette(palette_);
if (!apply_palette.ok()) {
SDL_Log("Failed to apply palette: %s\n", apply_palette.message().data());
active_ = false;
}
} }
void Bitmap::UpdateTexture(SDL_Renderer *renderer) { void Bitmap::UpdateTexture(SDL_Renderer *renderer) {
@@ -407,41 +400,39 @@ void Bitmap::CleanupUnusedTexture(uint64_t current_time, uint64_t timeout) {
} }
} }
absl::Status Bitmap::SetPalette(const SnesPalette &palette) { void Bitmap::SetPalette(const SnesPalette &palette) {
if (surface_ == nullptr) { if (surface_ == nullptr) {
return absl::FailedPreconditionError( throw std::runtime_error("Surface is null. Palette not applied");
"Surface is null. Palette not applied");
} }
if (surface_->format == nullptr || surface_->format->palette == nullptr) { if (surface_->format == nullptr || surface_->format->palette == nullptr) {
return absl::FailedPreconditionError( throw std::runtime_error(
"Surface format or palette is null. Palette not applied."); "Surface format or palette is null. Palette not applied.");
} }
palette_ = palette; palette_ = palette;
SDL_Palette *sdl_palette = surface_->format->palette; SDL_Palette *sdl_palette = surface_->format->palette;
if (sdl_palette == nullptr) { if (sdl_palette == nullptr) {
return absl::InternalError("Failed to get SDL palette"); throw std::runtime_error("Failed to get SDL palette");
} }
SDL_UnlockSurface(surface_.get()); SDL_UnlockSurface(surface_.get());
for (size_t i = 0; i < palette.size(); ++i) { for (size_t i = 0; i < palette.size(); ++i) {
ASSIGN_OR_RETURN(gfx::SnesColor pal_color, palette.GetColor(i)); auto pal_color = palette[i];
sdl_palette->colors[i].r = pal_color.rgb().x; sdl_palette->colors[i].r = pal_color.rgb().x;
sdl_palette->colors[i].g = pal_color.rgb().y; sdl_palette->colors[i].g = pal_color.rgb().y;
sdl_palette->colors[i].b = pal_color.rgb().z; sdl_palette->colors[i].b = pal_color.rgb().z;
sdl_palette->colors[i].a = pal_color.rgb().w; sdl_palette->colors[i].a = pal_color.rgb().w;
} }
SDL_LockSurface(surface_.get()); SDL_LockSurface(surface_.get());
return absl::OkStatus();
} }
absl::Status Bitmap::SetPaletteFromPaletteGroup(const SnesPalette &palette, void Bitmap::SetPaletteFromPaletteGroup(const SnesPalette &palette,
int palette_id) { int palette_id) {
auto start_index = palette_id * 8; auto start_index = palette_id * 8;
palette_ = palette.sub_palette(start_index, start_index + 8); palette_ = palette.sub_palette(start_index, start_index + 8);
SDL_UnlockSurface(surface_.get()); SDL_UnlockSurface(surface_.get());
for (size_t i = 0; i < palette_.size(); ++i) { for (size_t i = 0; i < palette_.size(); ++i) {
ASSIGN_OR_RETURN(auto pal_color, palette_.GetColor(i)); auto pal_color = palette_[i];
if (pal_color.is_transparent()) { if (pal_color.is_transparent()) {
surface_->format->palette->colors[i].r = 0; surface_->format->palette->colors[i].r = 0;
surface_->format->palette->colors[i].g = 0; surface_->format->palette->colors[i].g = 0;
@@ -455,26 +446,24 @@ absl::Status Bitmap::SetPaletteFromPaletteGroup(const SnesPalette &palette,
} }
} }
SDL_LockSurface(surface_.get()); SDL_LockSurface(surface_.get());
return absl::OkStatus();
} }
absl::Status Bitmap::SetPaletteWithTransparent(const SnesPalette &palette, void Bitmap::SetPaletteWithTransparent(const SnesPalette &palette, size_t index,
size_t index, int length) { int length) {
if (index < 0 || index >= palette.size()) { if (index < 0 || index >= palette.size()) {
return absl::InvalidArgumentError("Invalid palette index"); throw std::invalid_argument("Invalid palette index");
} }
if (length < 0 || length > palette.size()) { if (length < 0 || length > palette.size()) {
return absl::InvalidArgumentError("Invalid palette length"); throw std::invalid_argument("Invalid palette length");
} }
if (index + length > palette.size()) { if (index + length > palette.size()) {
return absl::InvalidArgumentError("Palette index + length exceeds size"); throw std::invalid_argument("Palette index + length exceeds size");
} }
if (surface_ == nullptr) { if (surface_ == nullptr) {
return absl::FailedPreconditionError( throw std::runtime_error("Surface is null. Palette not applied");
"Surface is null. Palette not applied");
} }
auto start_index = index * 7; auto start_index = index * 7;
@@ -482,7 +471,7 @@ absl::Status Bitmap::SetPaletteWithTransparent(const SnesPalette &palette,
std::vector<ImVec4> colors; std::vector<ImVec4> colors;
colors.push_back(ImVec4(0, 0, 0, 0)); colors.push_back(ImVec4(0, 0, 0, 0));
for (int i = start_index; i < start_index + 7; ++i) { for (int i = start_index; i < start_index + 7; ++i) {
ASSIGN_OR_RETURN(auto pal_color, palette.GetColor(i)); auto pal_color = palette[i];
colors.push_back(pal_color.rgb()); colors.push_back(pal_color.rgb());
} }
@@ -496,7 +485,6 @@ absl::Status Bitmap::SetPaletteWithTransparent(const SnesPalette &palette,
i++; i++;
} }
SDL_LockSurface(surface_.get()); SDL_LockSurface(surface_.get());
return absl::OkStatus();
} }
void Bitmap::SetPalette(const std::vector<SDL_Color> &palette) { void Bitmap::SetPalette(const std::vector<SDL_Color> &palette) {
@@ -609,38 +597,34 @@ std::vector<gfx::Bitmap> ExtractTile8Bitmaps(const gfx::Bitmap &source_bmp,
std::vector<std::future<gfx::Bitmap>> futures; std::vector<std::future<gfx::Bitmap>> futures;
for (int index = 0; index < kTileCount; ++index) { for (int index = 0; index < kTileCount; ++index) {
futures.emplace_back(std::async(std::launch::async, [&source_bmp, &palette, futures.emplace_back(std::async(
palette_index, std::launch::async, [&source_bmp, &palette, palette_index, index]() {
index]() { std::array<uint8_t, 0x40> tile_data;
std::array<uint8_t, 0x40> tile_data;
int num_columns = source_bmp.width() / kTileSize; int num_columns = source_bmp.width() / kTileSize;
for (int ty = 0; ty < kTileSize; ++ty) { for (int ty = 0; ty < kTileSize; ++ty) {
for (int tx = 0; tx < kTileSize; ++tx) { for (int tx = 0; tx < kTileSize; ++tx) {
int tile_data_pos = tx + (ty * kTileSize); int tile_data_pos = tx + (ty * kTileSize);
int src_x = (index % num_columns) * kTileSize + tx; int src_x = (index % num_columns) * kTileSize + tx;
int src_y = (index / num_columns) * kTileSize + ty; int src_y = (index / num_columns) * kTileSize + ty;
int gfx_position = src_x + (src_y * 0x100); int gfx_position = src_x + (src_y * 0x100);
uint8_t value = source_bmp.data()[gfx_position]; uint8_t value = source_bmp.data()[gfx_position];
if (value & 0x80) { if (value & 0x80) {
value -= 0x88; value -= 0x88;
}
tile_data[tile_data_pos] = value;
}
} }
tile_data[tile_data_pos] = value; gfx::Bitmap tile_bitmap;
} tile_bitmap.Create(kTileSize, kTileSize, 8, tile_data);
} tile_bitmap.SetPaletteWithTransparent(palette, palette_index);
return tile_bitmap;
gfx::Bitmap tile_bitmap; }));
tile_bitmap.Create(kTileSize, kTileSize, 8, tile_data);
if (!tile_bitmap.SetPaletteWithTransparent(palette, palette_index).ok()) {
SDL_Log("Failed to set palette for tile %d\n", index);
throw std::runtime_error("Failed to set palette for tile");
}
return tile_bitmap;
}));
} }
for (auto &future : futures) { for (auto &future : futures) {

View File

@@ -9,7 +9,6 @@
#include <string_view> #include <string_view>
#include <vector> #include <vector>
#include "absl/status/status.h"
#include "app/gfx/snes_palette.h" #include "app/gfx/snes_palette.h"
namespace yaze { namespace yaze {
@@ -68,12 +67,12 @@ class Bitmap {
public: public:
// Constructors // Constructors
Bitmap() = default; Bitmap() = default;
/** /**
* @brief Create a bitmap with the given dimensions and data * @brief Create a bitmap with the given dimensions and data
*/ */
Bitmap(int width, int height, int depth, const std::vector<uint8_t> &data); Bitmap(int width, int height, int depth, const std::vector<uint8_t> &data);
/** /**
* @brief Create a bitmap with the given dimensions, data, and palette * @brief Create a bitmap with the given dimensions, data, and palette
*/ */
@@ -89,13 +88,13 @@ class Bitmap {
* @brief Create a bitmap with the given dimensions and data * @brief Create a bitmap with the given dimensions and data
*/ */
void Create(int width, int height, int depth, std::span<uint8_t> data); void Create(int width, int height, int depth, std::span<uint8_t> data);
/** /**
* @brief Create a bitmap with the given dimensions and data * @brief Create a bitmap with the given dimensions and data
*/ */
void Create(int width, int height, int depth, void Create(int width, int height, int depth,
const std::vector<uint8_t> &data); const std::vector<uint8_t> &data);
/** /**
* @brief Create a bitmap with the given dimensions, format, and data * @brief Create a bitmap with the given dimensions, format, and data
*/ */
@@ -140,20 +139,19 @@ class Bitmap {
/** /**
* @brief Set the palette for the bitmap * @brief Set the palette for the bitmap
*/ */
absl::Status SetPalette(const SnesPalette &palette); void SetPalette(const SnesPalette &palette);
/** /**
* @brief Set the palette with a transparent color * @brief Set the palette with a transparent color
*/ */
absl::Status SetPaletteWithTransparent(const SnesPalette &palette, void SetPaletteWithTransparent(const SnesPalette &palette, size_t index,
size_t index, int length = 7); int length = 7);
/** /**
* @brief Set the palette from a palette group * @brief Set the palette from a palette group
*/ */
absl::Status SetPaletteFromPaletteGroup(const SnesPalette &palette, void SetPaletteFromPaletteGroup(const SnesPalette &palette, int palette_id);
int palette_id);
/** /**
* @brief Set the palette using SDL colors * @brief Set the palette using SDL colors
*/ */
@@ -164,7 +162,7 @@ class Bitmap {
* @brief Write a value to a pixel at the given position * @brief Write a value to a pixel at the given position
*/ */
void WriteToPixel(int position, uint8_t value); void WriteToPixel(int position, uint8_t value);
/** /**
* @brief Write a color to a pixel at the given position * @brief Write a color to a pixel at the given position
*/ */
@@ -187,23 +185,23 @@ class Bitmap {
* @brief Clean up the bitmap resources * @brief Clean up the bitmap resources
*/ */
void Cleanup(); void Cleanup();
/** /**
* @brief Clear the bitmap data * @brief Clear the bitmap data
*/ */
void Clear(); void Clear();
const SnesPalette& palette() const { return palette_; } const SnesPalette &palette() const { return palette_; }
SnesPalette* mutable_palette() { return &palette_; } SnesPalette *mutable_palette() { return &palette_; }
int width() const { return width_; } int width() const { return width_; }
int height() const { return height_; } int height() const { return height_; }
int depth() const { return depth_; } int depth() const { return depth_; }
int size() const { return data_size_; } int size() const { return data_size_; }
const uint8_t* data() const { return data_.data(); } const uint8_t *data() const { return data_.data(); }
std::vector<uint8_t>& mutable_data() { return data_; } std::vector<uint8_t> &mutable_data() { return data_; }
SDL_Surface* surface() const { return surface_.get(); } SDL_Surface *surface() const { return surface_.get(); }
SDL_Texture* texture() const { return texture_.get(); } SDL_Texture *texture() const { return texture_.get(); }
const std::vector<uint8_t>& vector() const { return data_; } const std::vector<uint8_t> &vector() const { return data_; }
uint8_t at(int i) const { return data_[i]; } uint8_t at(int i) const { return data_[i]; }
bool modified() const { return modified_; } bool modified() const { return modified_; }
bool is_active() const { return active_; } bool is_active() const { return active_; }
@@ -233,7 +231,7 @@ class Bitmap {
// Track the last time this texture was used // Track the last time this texture was used
uint64_t last_used_time_ = 0; uint64_t last_used_time_ = 0;
// Pointer to the texture pixels // Pointer to the texture pixels
void *texture_pixels = nullptr; void *texture_pixels = nullptr;
// Pointer to the pixel data // Pointer to the pixel data
@@ -244,7 +242,7 @@ class Bitmap {
// Data for the bitmap // Data for the bitmap
std::vector<uint8_t> data_; std::vector<uint8_t> data_;
// Surface for the bitmap // Surface for the bitmap
std::shared_ptr<SDL_Surface> surface_ = nullptr; std::shared_ptr<SDL_Surface> surface_ = nullptr;
@@ -271,12 +269,12 @@ Uint32 GetSnesPixelFormat(int format);
/** /**
* @brief Allocate an SDL surface with the given dimensions and format * @brief Allocate an SDL surface with the given dimensions and format
*/ */
SDL_Surface* AllocateSurface(int width, int height, int depth, Uint32 format); SDL_Surface *AllocateSurface(int width, int height, int depth, Uint32 format);
/** /**
* @brief Allocate an SDL texture with the given dimensions and format * @brief Allocate an SDL texture with the given dimensions and format
*/ */
SDL_Texture* AllocateTexture(SDL_Renderer *renderer, Uint32 format, int access, SDL_Texture *AllocateTexture(SDL_Renderer *renderer, Uint32 format, int access,
int width, int height); int width, int height);
} // namespace gfx } // namespace gfx

View File

@@ -220,52 +220,6 @@ uint32_t GetPaletteAddress(const std::string &group_name, size_t palette_index,
return address; return address;
} }
SnesPalette::SnesPalette(char *data) {
assert((sizeof(data) % 4 == 0) && (sizeof(data) <= 32));
for (unsigned i = 0; i < sizeof(data); i += 2) {
SnesColor col;
col.set_snes(static_cast<uint8_t>(data[i + 1]) << 8);
col.set_snes(col.snes() | static_cast<uint8_t>(data[i]));
snes_color mColor = ConvertSnesToRgb(col.snes());
col.set_rgb(ImVec4(mColor.red, mColor.green, mColor.blue, 1.f));
colors.push_back(col);
}
}
SnesPalette::SnesPalette(const unsigned char *snes_pal) {
assert((sizeof(snes_pal) % 4 == 0) && (sizeof(snes_pal) <= 32));
for (unsigned i = 0; i < sizeof(snes_pal); i += 2) {
SnesColor col;
col.set_snes(snes_pal[i + 1] << (uint16_t)8);
col.set_snes(col.snes() | snes_pal[i]);
snes_color mColor = ConvertSnesToRgb(col.snes());
col.set_rgb(ImVec4(mColor.red, mColor.green, mColor.blue, 1.f));
colors.push_back(col);
}
}
SnesPalette::SnesPalette(const std::vector<ImVec4> &cols) {
for (const auto &each : cols) {
SnesColor scol;
scol.set_rgb(each);
colors.push_back(scol);
}
}
SnesPalette::SnesPalette(const std::vector<snes_color> &cols) {
for (const auto &each : cols) {
SnesColor scol;
scol.set_snes(ConvertRgbToSnes(each));
colors.push_back(scol);
}
}
SnesPalette::SnesPalette(const std::vector<SnesColor> &cols) {
for (const auto &each : cols) {
colors.push_back(each);
}
}
SnesPalette ReadPaletteFromRom(int offset, int num_colors, const uint8_t *rom) { SnesPalette ReadPaletteFromRom(int offset, int num_colors, const uint8_t *rom) {
int color_offset = 0; int color_offset = 0;
std::vector<gfx::SnesColor> colors(num_colors); std::vector<gfx::SnesColor> colors(num_colors);
@@ -302,7 +256,7 @@ absl::StatusOr<PaletteGroup> CreatePaletteGroupFromColFile(
for (int i = 0; i < palette_rows.size(); i += 8) { for (int i = 0; i < palette_rows.size(); i += 8) {
SnesPalette palette; SnesPalette palette;
for (int j = 0; j < 8; j++) { for (int j = 0; j < 8; j++) {
palette.AddColor(palette_rows[i + j].rom_color()); palette.AddColor(palette_rows[i + j]);
} }
palette_group.AddPalette(palette); palette_group.AddPalette(palette);
} }

View File

@@ -1,10 +1,12 @@
#ifndef YAZE_APP_GFX_PALETTE_H #ifndef YAZE_APP_GFX_PALETTE_H
#define YAZE_APP_GFX_PALETTE_H #define YAZE_APP_GFX_PALETTE_H
#include <array>
#include <cstdint> #include <cstdint>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <string>
#include <vector> #include <vector>
#include "absl/status/status.h" #include "absl/status/status.h"
@@ -48,7 +50,7 @@ static constexpr absl::string_view kPaletteGroupNames[] = {
"sprites_aux3", "dungeon_main", "ow_mini_map", "ow_mini_map", "sprites_aux3", "dungeon_main", "ow_mini_map", "ow_mini_map",
"3d_object", "3d_object"}; "3d_object", "3d_object"};
constexpr const char *kPaletteGroupAddressesKeys[] = { constexpr const char* kPaletteGroupAddressesKeys[] = {
"ow_main", "ow_aux", "ow_animated", "hud", "ow_main", "ow_aux", "ow_animated", "hud",
"global_sprites", "armors", "swords", "shields", "global_sprites", "armors", "swords", "shields",
"sprites_aux1", "sprites_aux2", "sprites_aux3", "dungeon_main", "sprites_aux1", "sprites_aux2", "sprites_aux3", "dungeon_main",
@@ -107,7 +109,7 @@ constexpr int OverworldGrassPalettesMax = 3;
constexpr int Object3DPalettesMax = 2; constexpr int Object3DPalettesMax = 2;
constexpr int OverworldMiniMapPalettesMax = 2; constexpr int OverworldMiniMapPalettesMax = 2;
uint32_t GetPaletteAddress(const std::string &group_name, size_t palette_index, uint32_t GetPaletteAddress(const std::string& group_name, size_t palette_index,
size_t color_index); size_t color_index);
/** /**
@@ -118,94 +120,118 @@ uint32_t GetPaletteAddress(const std::string &group_name, size_t palette_index,
* colors in an SNES palette. It supports various constructors to initialize the * colors in an SNES palette. It supports various constructors to initialize the
* palette with different types of data. The palette can be modified by adding * palette with different types of data. The palette can be modified by adding
* or changing colors, and it can be cleared to remove all colors. Colors in the * or changing colors, and it can be cleared to remove all colors. Colors in the
* palette can be accessed using index-based access or through the `GetColor` * palette can be accessed using index-based access. The class also provides a
* method. The class also provides a method to create a sub-palette by selecting * method to create a sub-palette by selecting a range of colors from the
* a range of colors from the original palette. * original palette.
*/ */
class SnesPalette { class SnesPalette {
public: public:
template <typename T> static constexpr size_t kMaxColors = 256;
explicit SnesPalette(const std::vector<T> &data) { using ColorArray = std::array<SnesColor, kMaxColors>;
for (const auto &item : data) {
colors.emplace_back(SnesColor(item)); // Default constructor
SnesPalette() : size_(0) {}
// Constructor from vector of uint16_t (SNES color values)
explicit SnesPalette(const std::vector<uint16_t>& colors) : size_(0) {
for (const auto& color : colors) {
if (size_ < kMaxColors) {
colors_[size_++] = SnesColor(color);
}
} }
} }
SnesPalette() = default; // Constructor from vector of SnesColor
explicit SnesPalette(char *snesPal); explicit SnesPalette(const std::vector<SnesColor>& colors) : size_(0) {
explicit SnesPalette(const unsigned char *snes_pal); for (const auto& color : colors) {
explicit SnesPalette(const std::vector<ImVec4> &); if (size_ < kMaxColors) {
explicit SnesPalette(const std::vector<snes_color> &); colors_[size_++] = color;
explicit SnesPalette(const std::vector<SnesColor> &); }
void Create(const std::vector<SnesColor> &cols) {
for (const auto &each : cols) {
colors.emplace_back(each);
} }
} }
void Create(std::ranges::range auto &&cols) { // Constructor from raw SNES palette data
std::copy(cols.begin(), cols.end(), std::back_inserter(colors)); explicit SnesPalette(const char* data, size_t length) : size_(0) {
} for (size_t i = 0; i < length && size_ < kMaxColors; i += 2) {
uint16_t color = (static_cast<uint8_t>(data[i + 1]) << 8) |
void AddColor(const SnesColor &color) { colors.emplace_back(color); } static_cast<uint8_t>(data[i]);
void AddColor(const snes_color &color) { colors.emplace_back(color); } colors_[size_++] = SnesColor(color);
void AddColor(uint16_t color) { colors.emplace_back(color); }
absl::StatusOr<SnesColor> GetColor(int i) const {
if (i > colors.size()) {
return absl::InvalidArgumentError("SnesPalette: Index out of bounds");
} }
return colors[i];
} }
auto mutable_color(int i) { return &colors[i]; } // Constructor from ImVec4 colors
explicit SnesPalette(const std::vector<ImVec4>& colors) : size_(0) {
void clear() { colors.clear(); } for (const auto& color : colors) {
auto size() const { return colors.size(); } if (size_ < kMaxColors) {
auto empty() const { return colors.empty(); } colors_[size_++] = SnesColor(color);
auto begin() { return colors.begin(); } }
auto end() { return colors.end(); }
SnesColor &operator[](int i) {
if (i > colors.size()) {
std::cout << "SNESPalette: Index out of bounds" << std::endl;
return colors[0];
} }
return colors[i];
} }
void operator()(int i, const SnesColor &color) { const SnesColor& operator[](size_t index) const { return colors_[index]; }
if (i >= colors.size()) {
std::cout << "SNESPalette: Index out of bounds" << std::endl; SnesColor& operator[](size_t index) { return colors_[index]; }
size_t size() const { return size_; }
bool empty() const { return size_ == 0; }
// Iterators
auto begin() { return colors_.begin(); }
auto end() { return colors_.begin() + size_; }
auto begin() const { return colors_.begin(); }
auto end() const { return colors_.begin() + size_; }
// Color manipulation
void AddColor(const SnesColor& color) {
if (size_ < kMaxColors) {
colors_[size_++] = color;
} }
colors[i] = color;
} }
void operator()(int i, const ImVec4 &color) { void UpdateColor(size_t index, const SnesColor& color) {
if (i >= colors.size()) { if (index < size_) {
std::cout << "SNESPalette: Index out of bounds" << std::endl; colors_[index] = color;
return;
} }
colors[i].set_rgb(color);
colors[i].set_modified(true);
} }
SnesPalette sub_palette(int start, int end) const { void clear() { size_ = 0; }
SnesPalette pal;
for (int i = start; i < end; i++) { // Sub-palette creation
pal.AddColor(colors[i]); SnesPalette sub_palette(size_t start, size_t length) const {
SnesPalette result;
if (start >= size_) {
return result;
} }
return pal; length = std::min(length, size_ - start);
for (size_t i = 0; i < length; ++i) {
result.AddColor(colors_[start + i]);
}
return result;
} }
// Comparison operators
bool operator==(const SnesPalette& other) const {
if (size_ != other.size_) {
return false;
}
for (size_t i = 0; i < size_; ++i) {
if (colors_[i].snes() != other.colors_[i].snes()) {
return false;
}
}
return true;
}
bool operator!=(const SnesPalette& other) const { return !(*this == other); }
private: private:
std::vector<SnesColor> colors; /**< The colors in the palette. */ ColorArray colors_;
size_t size_;
}; };
SnesPalette ReadPaletteFromRom(int offset, int num_colors, const uint8_t *rom); SnesPalette ReadPaletteFromRom(int offset, int num_colors, const uint8_t* rom);
std::array<float, 4> ToFloatArray(const SnesColor &color); std::array<float, 4> ToFloatArray(const SnesColor& color);
/** /**
* @brief Represents a group of palettes. * @brief Represents a group of palettes.
@@ -215,7 +241,7 @@ std::array<float, 4> ToFloatArray(const SnesColor &color);
*/ */
struct PaletteGroup { struct PaletteGroup {
PaletteGroup() = default; PaletteGroup() = default;
PaletteGroup(const std::string &name) : name_(name) {} PaletteGroup(const std::string& name) : name_(name) {}
void AddPalette(SnesPalette pal) { palettes.emplace_back(pal); } void AddPalette(SnesPalette pal) { palettes.emplace_back(pal); }
@@ -240,7 +266,7 @@ struct PaletteGroup {
return palettes[i]; return palettes[i];
} }
const SnesPalette &operator[](int i) const { const SnesPalette& operator[](int i) const {
if (i > palettes.size()) { if (i > palettes.size()) {
std::cout << "PaletteGroup: Index out of bounds" << std::endl; std::cout << "PaletteGroup: Index out of bounds" << std::endl;
return palettes[0]; return palettes[0];
@@ -277,7 +303,7 @@ struct PaletteGroupMap {
PaletteGroup object_3d = {kPaletteGroupAddressesKeys[13]}; PaletteGroup object_3d = {kPaletteGroupAddressesKeys[13]};
PaletteGroup overworld_mini_map = {kPaletteGroupAddressesKeys[14]}; PaletteGroup overworld_mini_map = {kPaletteGroupAddressesKeys[14]};
auto get_group(const std::string &group_name) { auto get_group(const std::string& group_name) {
if (group_name == "ow_main") { if (group_name == "ow_main") {
return &overworld_main; return &overworld_main;
} else if (group_name == "ow_aux") { } else if (group_name == "ow_aux") {
@@ -314,7 +340,7 @@ struct PaletteGroupMap {
} }
template <typename Func> template <typename Func>
absl::Status for_each(Func &&func) { absl::Status for_each(Func&& func) {
RETURN_IF_ERROR(func(overworld_aux)); RETURN_IF_ERROR(func(overworld_aux));
RETURN_IF_ERROR(func(overworld_animated)); RETURN_IF_ERROR(func(overworld_animated));
RETURN_IF_ERROR(func(hud)); RETURN_IF_ERROR(func(hud));
@@ -363,13 +389,13 @@ struct PaletteGroupMap {
}; };
absl::StatusOr<PaletteGroup> CreatePaletteGroupFromColFile( absl::StatusOr<PaletteGroup> CreatePaletteGroupFromColFile(
std::vector<SnesColor> &colors); std::vector<SnesColor>& colors);
/** /**
* @brief Take a SNESPalette, divide it into palettes of 8 colors * @brief Take a SNESPalette, divide it into palettes of 8 colors
*/ */
absl::StatusOr<PaletteGroup> CreatePaletteGroupFromLargePalette( absl::StatusOr<PaletteGroup> CreatePaletteGroupFromLargePalette(
SnesPalette &palette, int num_colors = 8); SnesPalette& palette, int num_colors = 8);
/** /**
* @brief Loads all the palettes for the game. * @brief Loads all the palettes for the game.
@@ -380,8 +406,8 @@ absl::StatusOr<PaletteGroup> CreatePaletteGroupFromLargePalette(
* groups. * groups.
* *
*/ */
absl::Status LoadAllPalettes(const std::vector<uint8_t> &rom_data, absl::Status LoadAllPalettes(const std::vector<uint8_t>& rom_data,
PaletteGroupMap &groups); PaletteGroupMap& groups);
/** /**
* @brief Represents a set of palettes used in a SNES graphics system. * @brief Represents a set of palettes used in a SNES graphics system.

View File

@@ -186,8 +186,8 @@ void Canvas::DrawContextMenu() {
refresh_graphics_, *palette); refresh_graphics_, *palette);
if (refresh_graphics_) { if (refresh_graphics_) {
auto status = bitmap_->SetPaletteWithTransparent( bitmap_->SetPaletteWithTransparent(*palette,
*palette, edit_palette_sub_index_); edit_palette_sub_index_);
Renderer::GetInstance().UpdateBitmap(bitmap_); Renderer::GetInstance().UpdateBitmap(bitmap_);
refresh_graphics_ = false; refresh_graphics_ = false;
} }

View File

@@ -68,7 +68,7 @@ absl::StatusOr<std::array<gfx::Bitmap, kNumLinkSheets>> LoadLinkGraphics(
auto link_sheet_8bpp = gfx::SnesTo8bppSheet(link_sheet_data, /*bpp=*/4); auto link_sheet_8bpp = gfx::SnesTo8bppSheet(link_sheet_data, /*bpp=*/4);
link_graphics[i].Create(gfx::kTilesheetWidth, gfx::kTilesheetHeight, link_graphics[i].Create(gfx::kTilesheetWidth, gfx::kTilesheetHeight,
gfx::kTilesheetDepth, link_sheet_8bpp); gfx::kTilesheetDepth, link_sheet_8bpp);
RETURN_IF_ERROR(link_graphics[i].SetPalette(rom.palette_group().armors[0]);) link_graphics[i].SetPalette(rom.palette_group().armors[0]);
Renderer::GetInstance().RenderBitmap(&link_graphics[i]); Renderer::GetInstance().RenderBitmap(&link_graphics[i]);
} }
return link_graphics; return link_graphics;
@@ -108,11 +108,11 @@ absl::StatusOr<std::array<gfx::Bitmap, kNumGfxSheets>> LoadAllGraphicsData(
if (graphics_sheets[i].is_active()) { if (graphics_sheets[i].is_active()) {
if (i > 115) { if (i > 115) {
// Apply sprites palette // Apply sprites palette
RETURN_IF_ERROR(graphics_sheets[i].SetPaletteWithTransparent( graphics_sheets[i].SetPaletteWithTransparent(
rom.palette_group().global_sprites[0], 0)); rom.palette_group().global_sprites[0], 0);
} else { } else {
RETURN_IF_ERROR(graphics_sheets[i].SetPaletteWithTransparent( graphics_sheets[i].SetPaletteWithTransparent(
rom.palette_group().dungeon_main[0], 0)); rom.palette_group().dungeon_main[0], 0);
} }
} }

View File

@@ -142,17 +142,14 @@ void DungeonObjectRenderer::UpdateObjectBitmap() {
bitmap_.Create(256, 256, 8, tilemap_); bitmap_.Create(256, 256, 8, tilemap_);
} }
absl::Status DungeonObjectRenderer::SetPalette(const gfx::SnesPalette& palette, void DungeonObjectRenderer::SetPalette(const gfx::SnesPalette& palette,
size_t transparent_index) { size_t transparent_index) {
// Apply the palette to the bitmap // Apply the palette to the bitmap
RETURN_IF_ERROR( bitmap_.SetPaletteWithTransparent(palette, transparent_index);
bitmap_.SetPaletteWithTransparent(palette, transparent_index));
// Store the palette in the VRAM structure for future reference // Store the palette in the VRAM structure for future reference
vram_.palettes.clear(); vram_.palettes.clear();
vram_.palettes.push_back(palette); vram_.palettes.push_back(palette);
return absl::OkStatus();
} }
} // namespace zelda3 } // namespace zelda3

View File

@@ -65,9 +65,8 @@ class DungeonObjectRenderer : public SharedRom {
* *
* @param palette The palette to use for the object * @param palette The palette to use for the object
* @param transparent_index Index of the transparent color (default: 0) * @param transparent_index Index of the transparent color (default: 0)
* @return absl::Status Success or error status
*/ */
absl::Status SetPalette(const gfx::SnesPalette& palette, size_t transparent_index = 0); void SetPalette(const gfx::SnesPalette& palette, size_t transparent_index = 0);
/** /**
* @brief Gets the rendered bitmap * @brief Gets the rendered bitmap

View File

@@ -618,8 +618,8 @@ absl::Status SetColorsPalette(Rom &rom, int index, gfx::SnesPalette &current,
} }
} }
current.Create(new_palette);
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
current[i] = new_palette[i];
current[(i / 16) * 16].set_transparent(true); current[(i / 16) * 16].set_transparent(true);
} }
@@ -661,7 +661,7 @@ absl::Status OverworldMap::LoadPalette() {
(sprite_palette_[game_state_] * 2) + 1]; (sprite_palette_[game_state_] * 2) + 1];
auto grass_pal_group = rom_->palette_group().grass; auto grass_pal_group = rom_->palette_group().grass;
ASSIGN_OR_RETURN(gfx::SnesColor bgr, grass_pal_group[0].GetColor(0)); auto bgr = grass_pal_group[0][0];
auto ow_aux_pal_group = rom_->palette_group().overworld_aux; auto ow_aux_pal_group = rom_->palette_group().overworld_aux;
ASSIGN_OR_RETURN(gfx::SnesPalette aux1, ASSIGN_OR_RETURN(gfx::SnesPalette aux1,
@@ -677,14 +677,14 @@ absl::Status OverworldMap::LoadPalette() {
if (parent_ < kDarkWorldMapIdStart) { if (parent_ < kDarkWorldMapIdStart) {
pal0 = parent_ == 0x03 || parent_ == 0x05 || parent_ == 0x07 ? 2 : 0; pal0 = parent_ == 0x03 || parent_ == 0x05 || parent_ == 0x07 ? 2 : 0;
ASSIGN_OR_RETURN(bgr, grass_pal_group[0].GetColor(0)); bgr = grass_pal_group[0][0];
} else if (parent_ >= kDarkWorldMapIdStart && } else if (parent_ >= kDarkWorldMapIdStart &&
parent_ < kSpecialWorldMapIdStart) { parent_ < kSpecialWorldMapIdStart) {
pal0 = parent_ == 0x43 || parent_ == 0x45 || parent_ == 0x47 ? 3 : 1; pal0 = parent_ == 0x43 || parent_ == 0x45 || parent_ == 0x47 ? 3 : 1;
ASSIGN_OR_RETURN(bgr, grass_pal_group[0].GetColor(1)); bgr = grass_pal_group[0][1];
} else if (parent_ >= 128 && parent_ < kNumOverworldMaps) { } else if (parent_ >= 128 && parent_ < kNumOverworldMaps) {
pal0 = 0; pal0 = 0;
ASSIGN_OR_RETURN(bgr, grass_pal_group[0].GetColor(2)); bgr = grass_pal_group[0][2];
} }
if (parent_ == 0x88) { if (parent_ == 0x88) {

View File

@@ -68,7 +68,7 @@ absl::Status Inventory::Create() {
} }
bitmap_.Create(256, 256, 8, data_); bitmap_.Create(256, 256, 8, data_);
RETURN_IF_ERROR(bitmap_.SetPalette(palette_)); bitmap_.SetPalette(palette_);
Renderer::GetInstance().RenderBitmap(&bitmap_); Renderer::GetInstance().RenderBitmap(&bitmap_);
return absl::OkStatus(); return absl::OkStatus();
} }
@@ -87,7 +87,7 @@ absl::Status Inventory::BuildTileset() {
tilesheets_bmp_.Create(128, 0x130, 64, test_); tilesheets_bmp_.Create(128, 0x130, 64, test_);
auto hud_pal_group = rom()->palette_group().hud; auto hud_pal_group = rom()->palette_group().hud;
palette_ = hud_pal_group[0]; palette_ = hud_pal_group[0];
RETURN_IF_ERROR(tilesheets_bmp_.SetPalette(palette_)) tilesheets_bmp_.SetPalette(palette_);
Renderer::GetInstance().RenderBitmap(&tilesheets_bmp_); Renderer::GetInstance().RenderBitmap(&tilesheets_bmp_);
return absl::OkStatus(); return absl::OkStatus();
} }

View File

@@ -4,16 +4,16 @@
#include <memory> #include <memory>
#include <sstream> #include <sstream>
#include "app/core/platform/app_delegate.h"
#include "app/core/controller.h" #include "app/core/controller.h"
#include "app/core/platform/app_delegate.h"
#include "app/rom.h" #include "app/rom.h"
#include "app/zelda3/overworld/overworld.h" #include "app/zelda3/overworld/overworld.h"
#include "util/flag.h" #include "util/flag.h"
#include "yaze_config.h" #include "yaze_config.h"
DEFINE_FLAG( DEFINE_FLAG(std::string, rom_file, "",
std::string, rom_file, "", "Path to the ROM file to load. " "Path to the ROM file to load. "
"If not specified, the app will run without a ROM."); "If not specified, the app will run without a ROM.");
int yaze_app_main(int argc, char **argv) { int yaze_app_main(int argc, char **argv) {
yaze::util::FlagParser parser(yaze::util::global_flag_registry()); yaze::util::FlagParser parser(yaze::util::global_flag_registry());
@@ -112,7 +112,10 @@ void yaze_unload_rom(zelda3_rom *rom) {
void yaze_save_rom(zelda3_rom *rom, const char *filename) { void yaze_save_rom(zelda3_rom *rom, const char *filename) {
if (rom->impl) { if (rom->impl) {
yaze::Rom *internal_rom = static_cast<yaze::Rom *>(rom->impl); yaze::Rom *internal_rom = static_cast<yaze::Rom *>(rom->impl);
internal_rom->SaveToFile(false, false, filename); if (auto status = internal_rom->SaveToFile(false, false, filename);
!status.ok()) {
throw std::runtime_error(status.message().data());
}
} }
} }
@@ -138,12 +141,8 @@ snes_color yaze_get_color_from_paletteset(const zelda3_rom *rom,
auto get_color = auto get_color =
internal_rom->palette_group() internal_rom->palette_group()
.get_group(yaze::gfx::kPaletteGroupAddressesKeys[palette_set]) .get_group(yaze::gfx::kPaletteGroupAddressesKeys[palette_set])
->palette(palette) ->palette(palette)[color];
.GetColor(color); color_struct = get_color.rom_color();
if (!get_color.ok()) {
return color_struct;
}
color_struct = get_color.value().rom_color();
return color_struct; return color_struct;
} }