20 using std::runtime_error::runtime_error;
36 return SDL_PIXELFORMAT_INDEX8;
42 return SDL_PIXELFORMAT_INDEX8;
47 const std::vector<uint8_t>& data)
48 : width_(width), height_(height), depth_(depth), data_(data) {
53 const std::vector<uint8_t>& data,
const SnesPalette& palette)
64 : width_(other.width_),
65 height_(other.height_),
67 active_(other.active_),
68 modified_(other.modified_),
69 palette_(other.palette_),
136 : width_(other.width_),
137 height_(other.height_),
138 depth_(other.depth_),
139 active_(other.active_),
140 modified_(other.modified_),
141 generation_(other.generation_),
142 texture_pixels(other.texture_pixels),
143 pixel_data_(other.pixel_data_),
144 palette_(std::move(other.palette_)),
145 data_(std::move(other.data_)),
146 surface_(other.surface_),
147 texture_(other.texture_) {
152 other.active_ =
false;
153 other.modified_ =
false;
154 other.generation_ = 0;
155 other.texture_pixels =
nullptr;
156 other.pixel_data_ =
nullptr;
157 other.surface_ =
nullptr;
158 other.texture_ =
nullptr;
162 if (
this != &other) {
173 width_ = other.width_;
174 height_ = other.height_;
175 depth_ = other.depth_;
176 active_ = other.active_;
177 modified_ = other.modified_;
178 generation_ = other.generation_;
179 texture_pixels = other.texture_pixels;
180 pixel_data_ = other.pixel_data_;
181 palette_ = std::move(other.palette_);
182 data_ = std::move(other.data_);
183 surface_ = other.surface_;
184 texture_ = other.texture_;
190 other.active_ =
false;
191 other.modified_ =
false;
192 other.generation_ = 0;
193 other.texture_pixels =
nullptr;
194 other.pixel_data_ =
nullptr;
195 other.surface_ =
nullptr;
196 other.texture_ =
nullptr;
207 const std::vector<uint8_t>& data) {
226 const std::vector<uint8_t>& data) {
228 SDL_Log(
"Bitmap data is empty\n");
239 SDL_Log(
"Data provided to Bitmap is empty.\n");
248 SDL_Log(
"Bitmap::Create.SDL_CreateRGBSurfaceWithFormat failed: %s\n",
329 SDL_Log(
"Warning: Bitmap surface has no palette (non-indexed format?)\n");
378 std::min(
data_.size(),
413 int sub_palette_index) {
468 throw std::invalid_argument(
"Invalid palette index");
472 throw std::invalid_argument(
473 "Invalid palette length (must be 0-15 for SNES palettes)");
477 throw std::invalid_argument(
"Palette index + length exceeds size");
481 std::vector<ImVec4> colors;
484 colors.push_back(
ImVec4(0, 0, 0, 0));
500 while (colors.size() <
static_cast<size_t>(length + 1)) {
501 colors.push_back(
ImVec4(0, 0, 0, 1.0f));
511 SDL_Log(
"Warning: Bitmap surface has no palette (non-indexed format?)\n");
515 const int num_colors =
static_cast<int>(colors.size());
516 for (
int color_index = 0; color_index <
num_colors; ++color_index) {
519 static_cast<Uint8>(colors[color_index].x * 255.0f);
521 static_cast<Uint8>(colors[color_index].y * 255.0f);
523 static_cast<Uint8>(colors[color_index].z * 255.0f);
525 static_cast<Uint8>(colors[color_index].w * 255.0f);
548 SDL_Log(
"Warning: SetPalette - surface has no palette!");
557 SDL_Log(
"Warning: SetPalette - SDL palette has %d colors, trying to set %d. "
558 "Colors above %d may not display correctly.",
584 SDL_Log(
"ERROR: WriteToPixel - position %d out of bounds (size: %zu)",
585 position,
data_.size());
592 "ERROR: WriteToPixel - bitmap not active or data empty (active=%s, "
605 "ERROR: WriteToPixel - surface or pixels are null (surface=%p, "
613 SDL_Log(
"ERROR: WriteToPixel - pixel_data_ is null after assignment");
618 data_[position] = value;
677 std::vector<uint8_t>& tile_data,
678 int& tile_data_offset) {
682 for (
int i = 0; i < 8; i++) {
683 for (
int j = 0;
j < 8;
j++) {
693 std::vector<uint8_t>& tile_data,
694 int& tile_data_offset) {
695 for (
int ty = 0;
ty < 16;
ty++) {
696 for (
int tx = 0;
tx < 16;
tx++) {
731 int position = y *
width_ + x;
732 if (position >= 0 && position <
static_cast<int>(
data_.size())) {
734 data_[position] = color_index;
762 if (!
data_.empty()) {
776 data_ = std::move(new_data);
812 return (r << 24) | (g << 16) | (b << 8) | a;
856 SDL_Log(
"Warning: set_data called with empty data vector");
876 SDL_Log(
"ValidateDataSurfaceSync: surface or data is null/empty");
882 size_t data_size =
data_.size();
886 SDL_Log(
"ValidateDataSurfaceSync: invalid sizes - surface: %zu, data: %zu",
893 SDL_Log(
"ValidateDataSurfaceSync: data and surface are not synchronized");
SDL_Surface * AllocateSurface(int width, int height, int depth, int format)
void QueueTextureCommand(TextureCommandType type, Bitmap *bitmap)
void FreeSurface(SDL_Surface *surface)
Represents a bitmap image optimized for SNES ROM hacking.
const uint8_t * data() const
const SnesPalette & palette() const
SDL_Surface * surface_
SDL surface for rendering (contains the authoritative palette)
Bitmap & operator=(const Bitmap &other)
Copy assignment operator.
void WriteToPixel(int position, uint8_t value)
Write a value to a pixel at the given position.
void Create(int width, int height, int depth, std::span< uint8_t > data)
Create a bitmap with the given dimensions and data.
bool ValidateDataSurfaceSync()
Validate that bitmap data and surface pixels are synchronized.
const std::vector< uint8_t > & vector() const
void UpdateSurfacePixels()
Update SDL surface with current pixel data from data_ vector Call this after modifying pixel data via...
std::unordered_map< uint32_t, uint8_t > color_to_index_cache_
void Reformat(int format)
Reformat the bitmap to use a different pixel format.
static uint32_t HashColor(const ImVec4 &color)
Hash a color for cache lookup.
void Get8x8Tile(int tile_index, int x, int y, std::vector< uint8_t > &tile_data, int &tile_data_offset)
Extract an 8x8 tile from the bitmap (SNES standard tile size)
void CreateTexture()
Creates the underlying SDL_Texture to be displayed.
void WriteColor(int position, const ImVec4 &color)
Write a color to a pixel at the given position.
void set_data(const std::vector< uint8_t > &data)
void Resize(int new_width, int new_height)
Resize the bitmap to new dimensions (preserves existing data)
static uint32_t next_generation_
void SetPixel(int x, int y, const SnesColor &color)
Set a pixel at the given x,y coordinates with SNES color.
void SetPalette(const SnesPalette &palette)
Set the palette for the bitmap using SNES palette format.
void ApplyStoredPalette()
Apply the stored palette to the surface (internal helper)
std::vector< uint8_t > data_
void InvalidatePaletteCache()
Invalidate the palette lookup cache (call when palette changes)
void SetPaletteWithTransparent(const SnesPalette &palette, size_t index, int length=7)
Set the palette with a transparent color.
struct yaze::gfx::Bitmap::DirtyRegion dirty_region_
void ApplyPaletteByMetadata(const SnesPalette &palette, int sub_palette_index=0)
Apply palette using metadata-driven strategy Chooses between SetPalette and SetPaletteWithTransparent...
void Get16x16Tile(int tile_x, int tile_y, std::vector< uint8_t > &tile_data, int &tile_data_offset)
Extract a 16x16 tile from the bitmap (SNES metatile size)
uint8_t FindColorIndex(const SnesColor &color)
Find color index in palette using optimized hash map lookup.
void UpdateTexture()
Updates the underlying SDL_Texture when it already exists.
gfx::SnesPalette palette_
Internal SNES palette storage (may be empty!)
RAII timer for automatic timing management.
constexpr ImVec4 rgb() const
Get RGB values (WARNING: stored as 0-255 in ImVec4)
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
uint16_t ConvertRgbToSnes(const snes_color &color)
Convert RGB (0-255) to SNES 15-bit color.
constexpr Uint32 SNES_PIXELFORMAT_8BPP
constexpr Uint32 SNES_PIXELFORMAT_4BPP
Uint32 GetSnesPixelFormat(int format)
Convert bitmap format enum to SDL pixel format.
SDL2/SDL3 compatibility layer.
void AddPoint(int x, int y)