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_),
134 : width_(other.width_),
135 height_(other.height_),
136 depth_(other.depth_),
137 active_(other.active_),
138 modified_(other.modified_),
139 generation_(other.generation_),
140 texture_pixels(other.texture_pixels),
141 pixel_data_(other.pixel_data_),
142 palette_(std::move(other.palette_)),
143 data_(std::move(other.data_)),
144 surface_(other.surface_),
145 texture_(other.texture_) {
150 other.active_ =
false;
151 other.modified_ =
false;
152 other.generation_ = 0;
153 other.texture_pixels =
nullptr;
154 other.pixel_data_ =
nullptr;
155 other.surface_ =
nullptr;
156 other.texture_ =
nullptr;
160 if (
this != &other) {
171 width_ = other.width_;
172 height_ = other.height_;
173 depth_ = other.depth_;
174 active_ = other.active_;
175 modified_ = other.modified_;
176 generation_ = other.generation_;
177 texture_pixels = other.texture_pixels;
178 pixel_data_ = other.pixel_data_;
179 palette_ = std::move(other.palette_);
180 data_ = std::move(other.data_);
181 surface_ = other.surface_;
182 texture_ = other.texture_;
188 other.active_ =
false;
189 other.modified_ =
false;
190 other.generation_ = 0;
191 other.texture_pixels =
nullptr;
192 other.pixel_data_ =
nullptr;
193 other.surface_ =
nullptr;
194 other.texture_ =
nullptr;
205 const std::vector<uint8_t>& data) {
224 const std::vector<uint8_t>& data) {
226 SDL_Log(
"Bitmap data is empty\n");
237 SDL_Log(
"Data provided to Bitmap is empty.\n");
246 SDL_Log(
"Bitmap::Create.SDL_CreateRGBSurfaceWithFormat failed: %s\n",
327 SDL_Log(
"Warning: Bitmap surface has no palette (non-indexed format?)\n");
376 std::min(
data_.size(),
411 int sub_palette_index) {
466 throw std::invalid_argument(
"Invalid palette index");
470 throw std::invalid_argument(
471 "Invalid palette length (must be 0-15 for SNES palettes)");
475 throw std::invalid_argument(
"Palette index + length exceeds size");
479 std::vector<ImVec4> colors;
482 colors.push_back(
ImVec4(0, 0, 0, 0));
498 while (colors.size() <
static_cast<size_t>(length + 1)) {
499 colors.push_back(
ImVec4(0, 0, 0, 1.0f));
509 SDL_Log(
"Warning: Bitmap surface has no palette (non-indexed format?)\n");
513 const int num_colors =
static_cast<int>(colors.size());
514 for (
int color_index = 0; color_index <
num_colors; ++color_index) {
517 static_cast<Uint8>(colors[color_index].x * 255.0f);
519 static_cast<Uint8>(colors[color_index].y * 255.0f);
521 static_cast<Uint8>(colors[color_index].z * 255.0f);
523 static_cast<Uint8>(colors[color_index].w * 255.0f);
546 SDL_Log(
"Warning: SetPalette - surface has no palette!");
555 SDL_Log(
"Warning: SetPalette - SDL palette has %d colors, trying to set %d. "
556 "Colors above %d may not display correctly.",
582 SDL_Log(
"ERROR: WriteToPixel - position %d out of bounds (size: %zu)",
583 position,
data_.size());
590 "ERROR: WriteToPixel - bitmap not active or data empty (active=%s, "
603 "ERROR: WriteToPixel - surface or pixels are null (surface=%p, "
611 SDL_Log(
"ERROR: WriteToPixel - pixel_data_ is null after assignment");
616 data_[position] = value;
675 std::vector<uint8_t>& tile_data,
676 int& tile_data_offset) {
680 for (
int i = 0; i < 8; i++) {
681 for (
int j = 0;
j < 8;
j++) {
691 std::vector<uint8_t>& tile_data,
692 int& tile_data_offset) {
693 for (
int ty = 0;
ty < 16;
ty++) {
694 for (
int tx = 0;
tx < 16;
tx++) {
729 int position = y *
width_ + x;
730 if (position >= 0 && position <
static_cast<int>(
data_.size())) {
732 data_[position] = color_index;
760 if (!
data_.empty()) {
774 data_ = std::move(new_data);
810 return (r << 24) | (g << 16) | (b << 8) | a;
854 SDL_Log(
"Warning: set_data called with empty data vector");
874 SDL_Log(
"ValidateDataSurfaceSync: surface or data is null/empty");
880 size_t data_size =
data_.size();
884 SDL_Log(
"ValidateDataSurfaceSync: invalid sizes - surface: %zu, data: %zu",
891 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)