5#include "absl/status/status.h"
6#include "absl/strings/str_format.h"
30 std::vector<gfx::SnesColor> grayscale;
33 const uint8_t value =
static_cast<uint8_t
>(i);
34 grayscale.emplace_back(value, value, value);
36 if (!grayscale.empty()) {
37 grayscale[0].set_transparent(
true);
97 std::array<uint8_t, 0x200>& all_tiles_types) {
117 return absl::OkStatus();
126 "Tile16 editor received complete overworld palette with %zu colors",
129 util::logf(
"Warning: Received incomplete palette with %zu colors",
137 util::logf(
"Failed to load tile8 graphics with new palette: %s",
138 status.message().data());
141 "Successfully loaded tile8 graphics with complete overworld "
146 util::logf(
"Tile16 editor palette coordination complete");
150 if (!
rom_ || current_tile16_ < 0 || current_tile16_ >= kTile16Count) {
158 return absl::FailedPreconditionError(
159 "Use document Save or Undo for the shared Tile16 document");
164 return absl::FailedPreconditionError(
"Cannot access current tile16 data");
172 return absl::OkStatus();
177 return absl::FailedPreconditionError(
"Tile16 blockset not available");
190 util::logf(
"Tile16 blockset refreshed and regenerated");
191 return absl::OkStatus();
224 return absl::FailedPreconditionError(
"Tile16 blockset not initialized");
227 if (current_tile16_ < 0 || current_tile16_ >= kTile16Count) {
228 return absl::OutOfRangeError(
"Current tile16 ID out of range");
232 return absl::FailedPreconditionError(
"Current tile16 bitmap is not active");
246 return absl::OkStatus();
254 return absl::FailedPreconditionError(
"Cannot access current tile16 data");
261 return absl::FailedPreconditionError(
"Tile8 source bitmap not active");
276 util::logf(
"Regenerated Tile16 bitmap for tile %d from ROM data",
278 return absl::OkStatus();
281absl::StatusOr<std::vector<zelda3::Tile16StampMutation>>
286 return absl::OutOfRangeError(
291 return absl::FailedPreconditionError(
"Target tile16 bitmap not active");
295 return absl::FailedPreconditionError(
"Tile8 source bitmap not active");
298 const int tile8_count =
300 const int max_tile8_id = std::max(0, tile8_count - 1);
301 const int tile8_row_stride =
303 const int quadrant_x = (pos.
x >=
kTile8Size) ? 1 : 0;
304 const int quadrant_y = (pos.
y >=
kTile8Size) ? 1 : 0;
305 const int quadrant_index = quadrant_x + (quadrant_y * 2);
312 stamp_request.quadrant_index = quadrant_index;
314 stamp_request.x_flip =
x_flip_;
315 stamp_request.y_flip =
y_flip_;
317 stamp_request.tile8_row_stride = tile8_row_stride;
319 stamp_request.max_tile8_id = max_tile8_id;
320 stamp_request.max_tile16_id =
331 return absl::InvalidArgumentError(
"Stamp preview bitmap is null");
335 std::vector<uint8_t> pixels(size * size, 0);
336 for (
const auto& mutation : mutations) {
342 for (
int row = 0; row < 16 && y + row < size; ++row) {
343 std::copy_n(tile.begin() + row * 16, 16,
344 pixels.begin() + (y + row) * size + x);
347 output->
Create(size, size, 8, pixels);
349 return absl::OkStatus();
358 for (
const auto& mutation : staged_tiles) {
359 const int tile16_id = mutation.tile16_id;
402 staged_tiles.size());
404 return absl::OkStatus();
408 Tile16LocalPos tile_position,
bool left_click,
bool right_click) {
409 if (!left_click && !right_click) {
410 return absl::OkStatus();
415 util::logf(
"Picked tile8 from tile16 at (%d, %d)",
416 static_cast<int>(tile_position.
x),
417 static_cast<int>(tile_position.
y));
418 return absl::OkStatus();
434 return absl::OkStatus();
440 display_position.
y / kTile16PreviewDisplayScale};
444 return absl::FailedPreconditionError(
445 "Current graphics bitmap not initialized");
455 const int total_tiles = tiles_per_row * total_rows;
460 for (
int tile_y = 0; tile_y < total_rows; ++tile_y) {
461 for (
int tile_x = 0; tile_x < tiles_per_row; ++tile_x) {
466 for (
int py = 0; py < 8; ++py) {
467 for (
int px = 0; px < 8; ++px) {
468 int src_x = tile_x * 8 + px;
469 int src_y = tile_y * 8 + py;
471 int dst_index = py * 8 + px;
481 tile_data[dst_index] = pixel_value;
495 if (display_palette && !display_palette->
empty()) {
499 "LoadTile8: display palette not available yet; deferring refresh");
510 util::logf(
"Loaded %zu individual tile8 graphics",
512 return absl::OkStatus();
516 if (tile_id < 0 || tile_id >= kTile16Count) {
517 return absl::OutOfRangeError(
518 absl::StrFormat(
"Invalid tile16 id: %d", tile_id));
522 return absl::FailedPreconditionError(
523 "Tile16 blockset or ROM not initialized");
530 const bool loaded_pending_metadata =
document_edits_.contains(tile_id);
535 if (loaded_pending_metadata) {
539 util::logf(
"SetCurrentTile: loaded tile %d successfully", tile_id);
547 return absl::OkStatus();
554 "RequestTileSwitch: Editor not initialized (blockset=%p, rom=%p)",
560 if (target_tile_id < 0 || target_tile_id >= kTile16Count) {
561 util::logf(
"RequestTileSwitch: Invalid target tile ID %d", target_tile_id);
572 util::logf(
"Tile selection failed: %s", status.message().data());
576 if (tile_id < 0 || tile_id >= kTile16Count) {
577 return absl::InvalidArgumentError(
"Invalid tile ID");
580 return absl::FailedPreconditionError(
"ROM not available");
593 bool bitmap_copied =
false;
599 bitmap_copied =
true;
601 pending_bitmap_it->second.is_active()) {
603 pending_bitmap_it->second.vector());
605 bitmap_copied =
true;
608 if (!tile_pixels.empty()) {
611 bitmap_copied =
true;
621 return absl::OkStatus();
626 return absl::FailedPreconditionError(
"Clipboard is empty");
648 return absl::OkStatus();
653 return absl::InvalidArgumentError(
"Invalid scratch space slot");
656 return absl::FailedPreconditionError(
"No active tile16 to save");
669 return absl::OkStatus();
674 return absl::InvalidArgumentError(
"Invalid scratch space slot");
678 return absl::FailedPreconditionError(
"Scratch space slot is empty");
700 return absl::OkStatus();
705 return absl::InvalidArgumentError(
"Invalid scratch space slot");
709 return absl::OkStatus();
715 return absl::FailedPreconditionError(
"No active tile16 to flip");
729 return absl::OkStatus();
734 return absl::FailedPreconditionError(
"No active tile16 to flip");
748 return absl::OkStatus();
753 return absl::FailedPreconditionError(
"No active tile16 to rotate");
769 return absl::OkStatus();
775 return absl::FailedPreconditionError(
"Source tile8 bitmap not active");
782 return absl::InvalidArgumentError(
"Invalid tile8 ID");
785 const gfx::TileInfo fill_info(
static_cast<uint16_t
>(tile8_id),
788 for (
int quadrant = 0; quadrant < 4; ++quadrant) {
802 return absl::OkStatus();
807 return absl::FailedPreconditionError(
"No active tile16 to clear");
811 for (
int quadrant = 0; quadrant < 4; ++quadrant) {
825 return absl::OkStatus();
833 new_palette = (new_palette + 1) % 8;
835 new_palette = (new_palette == 0) ? 7 : new_palette - 1;
844 return absl::OkStatus();
849 return absl::OkStatus();
852 if (palette_id >= 8) {
853 return absl::InvalidArgumentError(
"Invalid palette ID");
865 if (!display_palette || display_palette->
empty()) {
866 return absl::OkStatus();
869 const bool use_sub_palette_view =
871 if (use_sub_palette_view) {
873 const int palette_slot =
875 if (palette_slot >= 0 &&
876 static_cast<size_t>(palette_slot + 16) <= display_palette->
size()) {
878 *display_palette,
static_cast<size_t>(palette_slot + 1), 15);
891 return absl::OkStatus();
895 if (palette_id >= 8) {
896 return absl::InvalidArgumentError(
"Invalid palette ID");
901 return absl::FailedPreconditionError(
"No current tile16 data");
921 util::logf(
"Applied palette %d to all quadrants of tile %d", palette_id,
923 return absl::OkStatus();
927 uint8_t palette_id) {
928 if (palette_id >= 8) {
929 return absl::InvalidArgumentError(
"Invalid palette ID");
931 if (quadrant < 0 || quadrant > 3) {
932 return absl::InvalidArgumentError(
"Invalid quadrant index");
937 return absl::FailedPreconditionError(
"No current tile16 data");
941 return absl::InvalidArgumentError(
"Invalid quadrant index");
952 util::logf(
"Applied palette %d to quadrant %d of tile %d", palette_id,
954 return absl::OkStatus();
972 return absl::FailedPreconditionError(
"Tile16 blockset not initialized");
975 if (current_tile16_ < 0 || current_tile16_ >= kTile16Count) {
976 return absl::OutOfRangeError(
"Current tile16 ID out of range");
980 return absl::OutOfRangeError(
"Current palette ID out of range");
983 return absl::OkStatus();
987 return tile16_blockset_ !=
nullptr && tile_id >= 0 && tile_id < kTile16Count;
993 return absl::FailedPreconditionError(
994 "Use document Save or Undo for the shared Tile16 document");
998 return absl::FailedPreconditionError(
"ROM not available");
1002 return absl::FailedPreconditionError(
"No active tile16 to save");
1025 return absl::OkStatus();
1030 return absl::FailedPreconditionError(
"Tile16 blockset not initialized");
1033 if (current_tile16_ < 0 || current_tile16_ >= kTile16Count) {
1034 return absl::OutOfRangeError(
"Current tile16 ID out of range");
1040 return absl::OkStatus();
1045 return absl::FailedPreconditionError(
"Tile16 blockset not initialized");
1060 return absl::OkStatus();
1065 return absl::FailedPreconditionError(
1066 "Use document Save or Undo for the shared Tile16 document");
1069 std::vector<Tile16Commit> commits;
1094 util::logf(
"Committed Tile16 %d changes to overworld system",
1096 return absl::OkStatus();
1101 return absl::FailedPreconditionError(
1102 "Use document Save or Undo for the shared Tile16 document");
1115 return absl::OkStatus();
1120 return absl::FailedPreconditionError(
1121 "Use document Save or Undo for the shared Tile16 document");
1125 return absl::OkStatus();
1129 std::vector<Tile16Commit> commits;
1131 util::logf(
"Committing %zu pending tile16 changes to ROM",
1138 util::logf(
"Failed to write tile16 %d: %s", tile_id,
1139 status.message().data());
1142 commits.push_back({tile_id, tile_data});
1162 util::logf(
"All pending tile16 changes committed successfully");
1163 return absl::OkStatus();
1183 util::logf(
"Failed to reload tile after discard: %s",
1184 status.message().data());
1203 util::logf(
"Failed to reload tile after discard: %s",
1204 status.message().data());
1209 if (current_tile16_ < 0 || current_tile16_ >= kTile16Count) {
1225 return absl::FailedPreconditionError(
"ROM not available for usage cache");
1229 auto tile_provider = [
this](
int tile_id) -> absl::StatusOr<gfx::Tile16> {
1232 return pending_it->second;
1241 return absl::OkStatus();
1244 if (!
rom_ || current_tile16_ < 0 || current_tile16_ >= kTile16Count) {
1245 return absl::InvalidArgumentError(
"Invalid tile16 or ROM not set");
1249 int quad_x = (position.
x < 8) ? 0 : 1;
1250 int quad_y = (position.
y < 8) ? 0 : 1;
1251 int quadrant = quad_x + (quad_y * 2);
1257 return absl::FailedPreconditionError(
"Failed to get tile16 data");
1276 util::logf(
"Picked tile8 %d with palette %d from quadrant %d of tile16 %d",
1279 return absl::OkStatus();
1288 int sheet_index)
const {
1290 const int clamped_button = std::clamp(palette_button, 0, 7);
1291 return clamped_button * 16;
1298 constexpr int kTile8sPerGraphicsChunk = 64;
1299 int sheet_index = tile8_id / kTile8sPerGraphicsChunk;
1301 return std::min(15, std::max(0, sheet_index));
1328 const int actual_target_row = std::clamp(target_row, 0, 7);
1330 for (
int i = 0; i < 256; ++i) {
1331 int low_nibble = i & 0x0F;
1332 int target_index = (actual_target_row * 16) + low_nibble;
1335 if (low_nibble == 0) {
1338 remapped.
AddColor(transparent_color);
1339 }
else if (target_index <
static_cast<int>(source.
size())) {
1340 remapped.
AddColor(source[target_index]);
1360 return pixel_value / 16;
1382 for (
size_t i = 0; i < bitmap.
size(); ++i) {
1383 if ((bitmap.
data()[i] & 0xF0) != 0) {
1397 if (!display_palette || display_palette->
empty()) {
1398 fallback_palette = BuildFallbackDisplayPalette();
1399 display_palette = &fallback_palette;
1409 if (palette_slot >= 0 &&
1410 static_cast<size_t>(palette_slot + 16) <= display_palette->
size()) {
1412 *display_palette,
static_cast<size_t>(palette_slot + 1), 15);
1429 return absl::InvalidArgumentError(
"Invalid tile8 ID");
1433 return absl::FailedPreconditionError(
"ROM not set");
1437 if (!display_palette || display_palette->
empty()) {
1438 return absl::FailedPreconditionError(
"No overworld palette available");
1442 if (current_palette_ < 0 || current_palette_ >= 8) {
1448 const int palette_slot =
1459 util::logf(
"Updated tile8 %d with palette slot %d (palette size: %zu colors)",
1460 tile8_id, palette_slot, display_palette->
size());
1462 return absl::OkStatus();
1467 return absl::FailedPreconditionError(
"ROM not set");
1471 if (current_palette_ < 0 || current_palette_ >= 8) {
1478 if (!display_palette || display_palette->
empty()) {
1479 fallback_palette = BuildFallbackDisplayPalette();
1480 display_palette = &fallback_palette;
1481 util::logf(
"Display palette unavailable; using fallback grayscale palette");
1483 util::logf(
"Using resolved display palette with %zu colors",
1484 display_palette->
size());
1506 if (!regen_status.ok()) {
1516 "Successfully refreshed all palettes in tile16 editor with palette %d",
1518 return absl::OkStatus();
1522 util::logf(
"=== TILE8 SOURCE DATA ANALYSIS ===");
1536 std::map<uint8_t, int> pixel_counts;
1537 for (
size_t i = 0; i < 64; ++i) {
1539 pixel_counts[val]++;
1541 util::logf(
" - First tile8 (Sheet 0) pixel distribution:");
1542 for (
const auto& [val, count] : pixel_counts) {
1544 int col = val & 0x0F;
1545 util::logf(
" Value 0x%02X (%3d) = Row %d, Col %d: %d pixels", val, val,
1550 bool all_4bpp =
true;
1551 for (
const auto& [val, count] : pixel_counts) {
1557 util::logf(
" - Values in raw 4bpp range (0-15): %s",
1558 all_4bpp ?
"yes" :
"NO (pre-encoded)");
1561 util::logf(
" - Palette remapping for viewing:");
1564 util::logf(
" Pixels are remapped: (value & 0x0F) + (selected_row * 16)");
1576 std::map<uint8_t, int> pixel_counts;
1577 for (uint8_t val : first_tile) {
1578 pixel_counts[val]++;
1581 for (
const auto& [val, count] : pixel_counts) {
1582 util::logf(
" Value 0x%02X (%3d): %d pixels", val, val, count);
1596 util::logf(
" - Expected palette offset for SetPaletteWithTransparent: %d",
1601 util::logf(
" - First 16 palette colors (row 0):");
1602 for (
int i = 0; i < 16; ++i) {
1604 util::logf(
" [%2d] SNES: 0x%04X RGB: (%d,%d,%d)", i, color.snes(),
1605 static_cast<int>(color.rgb().x),
1606 static_cast<int>(color.rgb().y),
1607 static_cast<int>(color.rgb().z));
1613 util::logf(
" - Colors at palette slot %d (row %d):", palette_slot,
1615 for (
int i = 0; i < 16; ++i) {
1617 util::logf(
" [%2d] SNES: 0x%04X RGB: (%d,%d,%d)", i, color.snes(),
1618 static_cast<int>(color.rgb().x),
1619 static_cast<int>(color.rgb().y),
1620 static_cast<int>(color.rgb().z));
1627 if (slot < 0 || slot >= 4) {
1628 return absl::InvalidArgumentError(
"Invalid scratch slot");
1632 if (total_tiles <= 0) {
1633 return absl::FailedPreconditionError(
"Tile16 blockset is not available");
1636 const int start_tile = std::clamp(
current_tile16_, 0, total_tiles - 1);
1637 for (
int y = 0; y < 8; ++y) {
1638 for (
int x = 0; x < 8; ++x) {
1639 const int tile_id = start_tile + (y * 8) + x;
1641 (tile_id < total_tiles) ? tile_id : -1;
1647 absl::StrFormat(
"From %03X",
static_cast<uint16_t
>(start_tile));
1649 return absl::OkStatus();
1653 if (slot < 0 || slot >= 4) {
1654 return absl::InvalidArgumentError(
"Invalid scratch slot");
1658 return absl::FailedPreconditionError(
"Scratch slot is empty");
1662 if (first_tile < 0) {
1663 return absl::FailedPreconditionError(
"Scratch slot has no valid tile data");
1669 return absl::OkStatus();
1674 return absl::OkStatus();
1679 return absl::OkStatus();
1685 return absl::OkStatus();
1698 if (display_palette && !display_palette->
empty()) {
1699 const bool use_sub_palette_view =
1701 if (use_sub_palette_view) {
1703 const int palette_slot =
1705 if (palette_slot >= 0 &&
1706 static_cast<size_t>(palette_slot + 16) <= display_palette->
size()) {
1708 *display_palette,
static_cast<size_t>(palette_slot + 1), 15);
1724 return absl::OkStatus();
absl::Status WriteTile16(int tile16_id, uint32_t tile16_ptr, const gfx::Tile16 &tile)
void set_dirty(bool dirty)
absl::Status UpdateROMTile16Data()
gfx::Tile16 current_tile16_data_
gfx::Tile16 * GetCurrentTile16Data()
absl::Status SetCurrentTile(int id)
absl::Status ValidateTile16Data()
gfx::SnesPalette CreateRemappedPaletteForTile8(const gfx::SnesPalette &source, int target_row, int tile8_id) const
absl::Status ApplyPaletteToAllImpl(uint8_t palette_id)
absl::Status CommitChangesToBlockset()
int GetActualPaletteSlot(int palette_button, int sheet_index) const
absl::Status ClearTile16Impl()
gfx::SnesPalette CreateRemappedPaletteForViewing(const gfx::SnesPalette &source, int target_row) const
gfx::Bitmap * tile16_blockset_bmp()
std::array< Tile16ScratchData, 4 > scratch_space_
bool IsTile16Valid(int tile_id) const
absl::Status RegenerateTile16BitmapFromROM()
bool HasCurrentGfxBitmap() const
absl::Status HandleTile16CanvasClick(Tile16LocalPos tile_position, bool left_click, bool right_click)
gfx::SnesPalette overworld_palette_
absl::Status SaveTile16ToROM()
Tile16EditMode edit_mode_
absl::Status CommitChangesToOverworld()
absl::Status RunEdit(const std::function< absl::Status()> &operation)
absl::Status ApplyPaletteToQuadrantImpl(int quadrant, uint8_t palette_id)
zelda3::GameData * game_data() const
Tile16ClipboardData clipboard_tile16_
absl::StatusOr< gfx::Tile16 > ReadDocumentTile(int id) const
absl::Status FillTile16WithTile8Impl(int tile8_id)
bool live_preview_enabled_
bool show_palette_preview_
std::function< void()> before_edit_
void CopyTileBitmapToBlockset(int tile_id, const gfx::Bitmap &tile_bitmap)
absl::Status DiscardChanges()
void set_palette(const gfx::SnesPalette &palette)
const std::array< uint8_t, 0x200 > & all_tiles_types() const
std::map< int, gfx::Bitmap > edited_tile_bitmaps_
absl::Status CyclePalette(bool forward=true)
void AnalyzeTile8SourceData() const
absl::Status InitializeBitmaps(gfx::Bitmap &tile16_blockset_bmp, gfx::Bitmap ¤t_gfx_bmp, std::array< uint8_t, 0x200 > &all_tiles_types)
absl::Status FlipTile16Vertical()
absl::Status PickTile8FromTile16(Tile16LocalPos position)
absl::Status ApplyPaletteToAll(uint8_t palette_id)
static constexpr int kTilesPerRow
std::array< uint8_t, 0x200 > all_tiles_types_
gfx::Bitmap * tile16_blockset_bmp_
absl::Status BuildStampPreview(Tile16LocalPos pos, gfx::Bitmap *output) const
absl::Status UpdateBlocksetBitmap()
int last_rom_write_count_
void ApplyPaletteToCurrentTile16Bitmap()
absl::Status DrawToCurrentTile16Impl(Tile16LocalPos pos, const gfx::Bitmap *source_tile)
absl::Status DrawToCurrentTile16(Tile16LocalPos pos, const gfx::Bitmap *source_tile=nullptr)
std::function< void(int)> on_tile_selection_changed_
bool has_rom_write_history_
gfx::Tilemap * tile16_blockset_
absl::Status LoadLayoutFromScratch(int slot)
std::function< void(int)> on_current_tile_changed_
absl::Status CopyTile16ToClipboard(int tile_id)
absl::Status PasteTile16FromClipboard()
gfx::Bitmap * current_gfx_bmp()
std::chrono::steady_clock::time_point last_rom_write_time_
void CopyTile16ToAtlas(int tile_id)
absl::Status RebuildTile8UsageCache()
gfx::Bitmap preview_tile16_
absl::Status UpdateLivePreview()
std::map< int, gfx::Tile16 > document_edits_
absl::Status PreviewPaletteChange(uint8_t palette_id)
int GetActualPaletteSlotForCurrentTile16() const
absl::Status ClearTile16()
void DiscardCurrentTileChanges()
absl::Status BuildTile16BitmapFromData(const gfx::Tile16 &tile_data, gfx::Bitmap *output_bitmap) const
absl::Status RefreshAllPalettes()
gfx::SnesPalette palette_
gfx::Bitmap current_tile16_bmp_
absl::Status SaveLayoutToScratch(int slot)
bool HasTile16BlocksetBitmap() const
absl::Status RotateTile16()
absl::Status FillTile16WithTile8(int tile8_id)
absl::Status ApplyPaletteToQuadrant(int quadrant, uint8_t palette_id)
void MarkCurrentTileModified()
bool tile8_usage_cache_dirty_
gfx::Bitmap * current_gfx_bmp_
std::function< void(float, float)> on_tile8_sheet_resized_
absl::Status LoadTile16FromScratchSpace(int slot)
std::array< Tile16LayoutScratch, 4 > layout_scratch_
zelda3::Tile8UsageIndex tile8_usage_cache_
absl::Status RotateTile16Impl()
absl::Status FlipTile16Horizontal()
void RequestTileSwitch(int target_tile_id)
UndoManager undo_manager_
absl::Status SaveTile16ToScratchSpace(int slot)
absl::Status FlipTile16HorizontalImpl()
std::function< absl::Status(const std::vector< Tile16Commit > &) on_changes_committed_)
absl::Status UpdateTile8Palette(int tile8_id)
absl::Status UpdateOverworldTilemap()
bool map_blockset_loaded_
absl::Status CommitAllChanges()
int GetEncodedPaletteRow(uint8_t pixel_value) const
const gfx::SnesPalette & palette() const
const gfx::SnesPalette * ResolveDisplayPalette() const
absl::Status FlipTile16VerticalImpl()
bool auto_normalize_pixels_
int GetSheetIndexForTile8(int tile8_id) const
static Tile16LocalPos Tile16PreviewDisplayPixelToTilePosition(Tile16LocalPos display_position)
bool BitmapHasEncodedPaletteRows(const gfx::Bitmap &bitmap) const
uint8_t palette_normalization_mask_
absl::Status LoadTile16FromScratchSpaceImpl(int slot)
std::vector< gfx::Tile16 > * document_definitions_
absl::StatusOr< std::vector< zelda3::Tile16StampMutation > > BuildStampMutations(Tile16LocalPos pos) const
absl::Status PasteTile16FromClipboardImpl()
std::vector< zelda3::Tile8PixelData > current_gfx_individual_
absl::Status RefreshTile16Blockset()
absl::Status ClearScratchSpace(int slot)
float tile8_source_display_scale_
absl::Status Redo()
Redo the top action. Returns error if stack is empty.
absl::Status Undo()
Undo the top action. Returns error if stack is empty.
void QueueTextureCommand(TextureCommandType type, Bitmap *bitmap)
Represents a bitmap image optimized for SNES ROM hacking.
const uint8_t * data() const
const SnesPalette & palette() const
void Create(int width, int height, int depth, std::span< uint8_t > data)
Create a bitmap with the given dimensions and data.
const std::vector< uint8_t > & vector() const
void set_modified(bool modified)
void SetPalette(const SnesPalette &palette)
Set the palette for the bitmap using SNES palette format.
void SetPaletteWithTransparent(const SnesPalette &palette, size_t index, int length=7)
Set the palette with a transparent color.
RAII timer for automatic timing management.
constexpr void set_transparent(bool t)
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
void AddColor(const SnesColor &color)
static constexpr size_t kMaxColors
Tile composition of four 8x8 tiles.
SNES 16-bit tile metadata container.
#define ASSIGN_OR_RETURN(type_variable_name, expression)
gfx::TileInfo & TileInfoForQuadrant(gfx::Tile16 *tile, int quadrant)
void SyncTilesInfoArray(gfx::Tile16 *tile)
constexpr float kTile16PreviewDisplayScale
constexpr int kTile16Count
gfx::SnesPalette BuildFallbackDisplayPalette()
constexpr int kTile16PixelCount
constexpr int kTile16Size
constexpr int kNumScratchSlots
std::vector< uint8_t > GetTilemapData(Tilemap &tilemap, int tile_id)
void logf(const absl::FormatSpec< Args... > &format, Args &&... args)
gfx::Tile16 HorizontalFlipTile16(gfx::Tile16 tile)
gfx::TileInfo & MutableTile16QuadrantInfo(gfx::Tile16 &tile, int quadrant)
void SetTile16AllQuadrantPalettes(gfx::Tile16 *tile, uint8_t palette_id)
absl::Status RenderTile16BitmapFromMetadata(const gfx::Tile16 &tile_data, const std::vector< Tile8PixelData > &tile8_pixels, gfx::Bitmap *output_bitmap)
void SyncTile16TilesInfo(gfx::Tile16 *tile)
constexpr int kNumTile16Individual
gfx::Tile16 VerticalFlipTile16(gfx::Tile16 tile)
gfx::Tile16 RotateTile16Clockwise(gfx::Tile16 tile)
constexpr uint32_t kTile16Ptr
int ComputeTile16Count(const gfx::Tilemap *tile16_blockset)
absl::StatusOr< std::vector< Tile16StampMutation > > BuildTile16StampMutations(const Tile16StampRequest &request)
std::vector< uint8_t > RenderTile16PixelsFromMetadata(const gfx::Tile16 &tile_data, const std::vector< Tile8PixelData > &tile8_pixels)
const gfx::TileInfo & Tile16QuadrantInfo(const gfx::Tile16 &tile, int quadrant)
absl::Status BuildTile8UsageIndex(int total_tiles, const std::function< absl::StatusOr< gfx::Tile16 >(int)> &tile_provider, Tile8UsageIndex *usage_index)
void BlitTile16BitmapToAtlas(gfx::Bitmap *destination, int tile_id, const gfx::Bitmap &source_bitmap)
bool SetTile16QuadrantPalette(gfx::Tile16 *tile, int quadrant, uint8_t palette_id)
std::array< uint8_t, 64 > Tile8PixelData
#define RETURN_IF_ERROR(expr)
PaletteGroup overworld_main
const SnesPalette & palette_ref(int i) const
Bitmap atlas
Master bitmap containing all tiles.
gfx::PaletteGroupMap palette_groups
gfx::Tile16 current_tile16