yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
map_refresh_coordinator.cc
Go to the documentation of this file.
1// Related header
3
4#include "absl/status/status.h"
10#include "rom/rom.h"
11#include "util/log.h"
12#include "util/macro.h"
13#include "zelda3/common.h"
17
18namespace yaze::editor {
19
21 if (map_id < 0) {
22 // Invalidate all maps - clear both editor cache and Overworld's tileset
23 // cache
26 } else {
27 // Invalidate specific map and its siblings in the Overworld's tileset cache
28 ctx_.current_graphics_set->erase(map_id);
30 }
31}
32
34 ctx_.overworld->mutable_overworld_map(map_index)->LoadAreaGraphics();
35 *ctx_.status =
36 ctx_.overworld->mutable_overworld_map(map_index)->BuildTileset();
38 *ctx_.status =
39 ctx_.overworld->mutable_overworld_map(map_index)->BuildTiles16Gfx(
42 *ctx_.status = ctx_.overworld->mutable_overworld_map(map_index)->BuildBitmap(
44 (*ctx_.maps_bmp)[map_index].set_data(
45 ctx_.overworld->mutable_overworld_map(map_index)->bitmap_data());
46 (*ctx_.maps_bmp)[map_index].set_modified(true);
48}
49
51 // Use the new on-demand refresh system
53}
54
63 if (map_index < 0 || map_index >= zelda3::kNumOverworldMaps) {
64 return;
65 }
66
67 // Check if the map is actually visible or being edited
68 bool is_current_map = (map_index == *ctx_.current_map);
69 bool is_current_world = (map_index / 0x40 == *ctx_.current_world);
70
71 // For non-current maps in non-current worlds, defer the refresh
72 if (!is_current_map && !is_current_world) {
73 // Mark for deferred refresh - will be processed when the map becomes
74 // visible
75 (*ctx_.maps_bmp)[map_index].set_modified(true);
76 return;
77 }
78
79 // For visible maps, do immediate refresh
80 RefreshChildMapOnDemand(map_index);
81}
82
87 auto* map = ctx_.overworld->mutable_overworld_map(map_index);
88 if (!map) {
89 return; // Map not loaded yet (e.g. Overworld not fully initialized)
90 }
91
92 // Check what actually needs to be refreshed
93 bool needs_graphics_rebuild = (*ctx_.maps_bmp)[map_index].modified();
94
95 if (needs_graphics_rebuild) {
96 // Only rebuild what's actually changed
97 map->LoadAreaGraphics();
98
99 // Rebuild tileset only if graphics changed
100 auto status = map->BuildTileset();
101 if (!status.ok()) {
102 LOG_ERROR("MapRefreshCoordinator",
103 "Failed to build tileset for map %d: %s", map_index,
104 status.message().data());
105 return;
106 }
107
108 // Rebuild tiles16 graphics
109 status = map->BuildTiles16Gfx(*ctx_.overworld->mutable_tiles16(),
110 ctx_.overworld->tiles16().size());
111 if (!status.ok()) {
112 LOG_ERROR("MapRefreshCoordinator",
113 "Failed to build tiles16 graphics for map %d: %s", map_index,
114 status.message().data());
115 return;
116 }
117
118 // Rebuild bitmap
119 status = map->BuildBitmap(ctx_.overworld->GetMapTiles(*ctx_.current_world));
120 if (!status.ok()) {
121 LOG_ERROR("MapRefreshCoordinator",
122 "Failed to build bitmap for map %d: %s", map_index,
123 status.message().data());
124 return;
125 }
126
127 // Update bitmap data
128 (*ctx_.maps_bmp)[map_index].set_data(map->bitmap_data());
129 (*ctx_.maps_bmp)[map_index].set_modified(false);
130
131 // Validate surface synchronization to help debug crashes
132 if (!(*ctx_.maps_bmp)[map_index].ValidateDataSurfaceSync()) {
133 LOG_WARN("MapRefreshCoordinator",
134 "Warning: Surface synchronization issue detected for map %d",
135 map_index);
136 }
137
138 // Queue texture update to ensure changes are visible
139 if ((*ctx_.maps_bmp)[map_index].texture()) {
142 } else {
145 }
146 }
147
148 // Handle multi-area maps (large, wide, tall) with safe coordination
149 // Use centralized version detection
151 bool use_v3_area_sizes =
153
154 if (use_v3_area_sizes) {
155 // Use v3 multi-area coordination
156 RefreshMultiAreaMapsSafely(map_index, map);
157 } else {
158 // Legacy logic: only handle large maps for vanilla/v2
159 if (map->is_large_map()) {
160 RefreshMultiAreaMapsSafely(map_index, map);
161 }
162 }
163}
164
180 int map_index, zelda3::OverworldMap* map) {
182
183 auto area_size = map->area_size();
184 if (area_size == AreaSizeEnum::SmallArea) {
185 return; // No siblings to coordinate
186 }
187
188 // Always work from parent perspective for consistent coordination
189 int parent_id = map->parent();
190
191 // If we're not the parent, get the parent map to work from
192 auto* parent_map = ctx_.overworld->mutable_overworld_map(parent_id);
193 if (!parent_map) {
194 LOG_WARN("MapRefreshCoordinator",
195 "RefreshMultiAreaMapsSafely: Could not get parent map %d for "
196 "map %d",
197 parent_id, map_index);
198 return;
199 }
200
201 LOG_DEBUG("MapRefreshCoordinator",
202 "RefreshMultiAreaMapsSafely: Processing %s area from parent %d "
203 "(trigger: %d)",
204 (area_size == AreaSizeEnum::LargeArea) ? "large"
205 : (area_size == AreaSizeEnum::WideArea) ? "wide"
206 : "tall",
207 parent_id, map_index);
208
209 // Determine all maps that are part of this multi-area structure
210 // based on the parent's position and area size
211 std::vector<int> sibling_maps;
212
213 switch (area_size) {
214 case AreaSizeEnum::LargeArea:
215 // Large Area: 2x2 grid (4 maps total)
216 sibling_maps = {parent_id, parent_id + 1, parent_id + 8, parent_id + 9};
217 break;
218
219 case AreaSizeEnum::WideArea:
220 // Wide Area: 2x1 grid (2 maps total, horizontally adjacent)
221 sibling_maps = {parent_id, parent_id + 1};
222 break;
223
224 case AreaSizeEnum::TallArea:
225 // Tall Area: 1x2 grid (2 maps total, vertically adjacent)
226 sibling_maps = {parent_id, parent_id + 8};
227 break;
228
229 default:
230 LOG_WARN("MapRefreshCoordinator",
231 "RefreshMultiAreaMapsSafely: Unknown area size %d for map %d",
232 static_cast<int>(area_size), map_index);
233 return;
234 }
235
236 // Refresh all siblings (including self if different from trigger)
237 // The trigger map (map_index) was already processed by the caller,
238 // so we skip it to avoid double-processing
239 for (int sibling : sibling_maps) {
240 // Skip the trigger map - it was already processed by
241 // RefreshChildMapOnDemand
242 if (sibling == map_index) {
243 continue;
244 }
245
246 // Bounds check
247 if (sibling < 0 || sibling >= zelda3::kNumOverworldMaps) {
248 continue;
249 }
250
251 // Check visibility - only immediately refresh visible maps
252 bool is_current_map = (sibling == *ctx_.current_map);
253 bool is_current_world = (sibling / 0x40 == *ctx_.current_world);
254
255 // Always mark sibling as needing refresh to ensure consistency
256 (*ctx_.maps_bmp)[sibling].set_modified(true);
257
258 if (is_current_map || is_current_world) {
259 LOG_DEBUG("MapRefreshCoordinator",
260 "RefreshMultiAreaMapsSafely: Refreshing sibling map %d",
261 sibling);
262
263 // Direct refresh for visible siblings
264 auto* sibling_map = ctx_.overworld->mutable_overworld_map(sibling);
265 if (!sibling_map)
266 continue;
267
268 sibling_map->LoadAreaGraphics();
269
270 auto status = sibling_map->BuildTileset();
271 if (!status.ok()) {
272 LOG_ERROR("MapRefreshCoordinator",
273 "Failed to build tileset for sibling %d: %s", sibling,
274 status.message().data());
275 continue;
276 }
277
278 status = sibling_map->BuildTiles16Gfx(*ctx_.overworld->mutable_tiles16(),
279 ctx_.overworld->tiles16().size());
280 if (!status.ok()) {
281 LOG_ERROR("MapRefreshCoordinator",
282 "Failed to build tiles16 for sibling %d: %s", sibling,
283 status.message().data());
284 continue;
285 }
286
287 status = sibling_map->LoadPalette();
288 if (!status.ok()) {
289 LOG_ERROR("MapRefreshCoordinator",
290 "Failed to load palette for sibling %d: %s", sibling,
291 status.message().data());
292 continue;
293 }
294
295 status = sibling_map->BuildBitmap(
297 if (!status.ok()) {
298 LOG_ERROR("MapRefreshCoordinator",
299 "Failed to build bitmap for sibling %d: %s", sibling,
300 status.message().data());
301 continue;
302 }
303
304 // Update bitmap data
305 (*ctx_.maps_bmp)[sibling].set_data(sibling_map->bitmap_data());
306
307 // Set palette if bitmap has a valid surface
308 if ((*ctx_.maps_bmp)[sibling].is_active() &&
309 (*ctx_.maps_bmp)[sibling].surface()) {
310 (*ctx_.maps_bmp)[sibling].SetPalette(sibling_map->current_palette());
311 }
312 (*ctx_.maps_bmp)[sibling].set_modified(false);
313
314 // Queue texture update/creation
315 if ((*ctx_.maps_bmp)[sibling].texture()) {
318 } else {
320 ctx_.ensure_map_texture(sibling);
321 }
322 }
323 }
324 // Non-visible siblings remain marked as modified for deferred refresh
325 }
326}
327
329 auto* current_map = ctx_.overworld->mutable_overworld_map(*ctx_.current_map);
330 if (!current_map) {
331 return absl::FailedPreconditionError("Current overworld map not loaded");
332 }
333 RETURN_IF_ERROR(current_map->LoadPalette());
334 const auto current_map_palette = ctx_.overworld->current_area_palette();
335 *ctx_.palette = current_map_palette;
336 // Keep tile16 editor in sync with the currently active overworld palette
337 ctx_.tile16_editor->set_palette(current_map_palette);
338 // Ensure source graphics bitmap uses the refreshed palette so tile8 selector
339 // isn't blank.
345 }
346
347 // Use centralized version detection
349 bool use_v3_area_sizes =
351
352 if (use_v3_area_sizes) {
353 // Use v3 area size system
355 auto area_size = current_map->area_size();
356
357 if (area_size != AreaSizeEnum::SmallArea) {
358 // Get all sibling maps that need palette updates
359 std::vector<int> sibling_maps;
360 int parent_id = current_map->parent();
361
362 switch (area_size) {
363 case AreaSizeEnum::LargeArea:
364 // 2x2 grid: parent, parent+1, parent+8, parent+9
365 sibling_maps = {parent_id, parent_id + 1, parent_id + 8,
366 parent_id + 9};
367 break;
368 case AreaSizeEnum::WideArea:
369 // 2x1 grid: parent, parent+1
370 sibling_maps = {parent_id, parent_id + 1};
371 break;
372 case AreaSizeEnum::TallArea:
373 // 1x2 grid: parent, parent+8
374 sibling_maps = {parent_id, parent_id + 8};
375 break;
376 default:
377 break;
378 }
379
380 // Update palette for all siblings - each uses its own loaded palette
381 for (int sibling_index : sibling_maps) {
382 if (sibling_index < 0 || sibling_index >= zelda3::kNumOverworldMaps) {
383 continue;
384 }
385 auto* sibling_map =
386 ctx_.overworld->mutable_overworld_map(sibling_index);
387 if (!sibling_map) {
388 continue;
389 }
390 RETURN_IF_ERROR(sibling_map->LoadPalette());
391 (*ctx_.maps_bmp)[sibling_index].SetPalette(
392 sibling_map->current_palette());
393 }
394 } else {
395 // Small area - only update current map
396 (*ctx_.maps_bmp)[*ctx_.current_map].SetPalette(current_map_palette);
397 }
398 } else {
399 // Legacy logic for vanilla and v2 ROMs
400 if (current_map->is_large_map()) {
401 // We need to update the map and its siblings if it's a large map
402 for (int i = 1; i < 4; i++) {
403 int sibling_index = current_map->parent() + i;
404 if (i >= 2)
405 sibling_index += 6;
406 auto* sibling_map =
407 ctx_.overworld->mutable_overworld_map(sibling_index);
408 if (!sibling_map) {
409 continue;
410 }
411 RETURN_IF_ERROR(sibling_map->LoadPalette());
412
413 // SAFETY: Only set palette if bitmap has a valid surface
414 // Use sibling map's own loaded palette
415 if ((*ctx_.maps_bmp)[sibling_index].is_active() &&
416 (*ctx_.maps_bmp)[sibling_index].surface()) {
417 (*ctx_.maps_bmp)[sibling_index].SetPalette(
418 sibling_map->current_palette());
419 }
420 }
421 }
422
423 // SAFETY: Only set palette if bitmap has a valid surface
424 if ((*ctx_.maps_bmp)[*ctx_.current_map].is_active() &&
425 (*ctx_.maps_bmp)[*ctx_.current_map].surface()) {
426 (*ctx_.maps_bmp)[*ctx_.current_map].SetPalette(current_map_palette);
427 }
428 }
429
430 return absl::OkStatus();
431}
432
434 // Mark the bitmap as modified to force refresh on next update
435 if (map_index >= 0 && map_index < static_cast<int>(ctx_.maps_bmp->size())) {
436 (*ctx_.maps_bmp)[map_index].set_modified(true);
437
438 // Clear blockset cache
439 *ctx_.current_blockset = 0xFF;
440
441 // Invalidate Overworld's tileset cache for this map and siblings
442 // This ensures stale cached tilesets aren't reused after property changes
444
445 LOG_DEBUG("MapRefreshCoordinator",
446 "ForceRefreshGraphics: Map %d marked for refresh", map_index);
447 }
448}
449
451 bool include_self) {
452 if (map_index < 0 || map_index >= static_cast<int>(ctx_.maps_bmp->size())) {
453 return;
454 }
455
456 auto* map = ctx_.overworld->mutable_overworld_map(map_index);
457 if (map->area_size() == zelda3::AreaSizeEnum::SmallArea) {
458 return; // No siblings for small areas
459 }
460
461 int parent_id = map->parent();
462 std::vector<int> siblings;
463
464 switch (map->area_size()) {
466 siblings = {parent_id, parent_id + 1, parent_id + 8, parent_id + 9};
467 break;
469 siblings = {parent_id, parent_id + 1};
470 break;
472 siblings = {parent_id, parent_id + 8};
473 break;
474 default:
475 return;
476 }
477
478 for (int sibling : siblings) {
479 if (sibling >= 0 && sibling < 0xA0) {
480 // Skip self unless include_self is true
481 if (sibling == map_index && !include_self) {
482 continue;
483 }
484
485 // Mark as modified FIRST before loading
486 (*ctx_.maps_bmp)[sibling].set_modified(true);
487
488 // Load graphics from ROM
489 ctx_.overworld->mutable_overworld_map(sibling)->LoadAreaGraphics();
490
491 // CRITICAL FIX: Bypass visibility check - force immediate refresh
492 // Call RefreshChildMapOnDemand() directly instead of
493 // RefreshOverworldMapOnDemand()
495
496 LOG_DEBUG("MapRefreshCoordinator",
497 "RefreshSiblingMapGraphics: Refreshed sibling map %d", sibling);
498 }
499 }
500}
501
503 const auto& current_ow_map =
505
506 // Use centralized version detection
508 bool use_v3_area_sizes =
510
511 if (use_v3_area_sizes) {
512 // Use v3 area size system
514 auto area_size = current_ow_map.area_size();
515
516 if (area_size != AreaSizeEnum::SmallArea) {
517 // Get all sibling maps that need property updates
518 std::vector<int> sibling_maps;
519 int parent_id = current_ow_map.parent();
520
521 switch (area_size) {
522 case AreaSizeEnum::LargeArea:
523 // 2x2 grid: parent+1, parent+8, parent+9 (skip parent itself)
524 sibling_maps = {parent_id + 1, parent_id + 8, parent_id + 9};
525 break;
526 case AreaSizeEnum::WideArea:
527 // 2x1 grid: parent+1 (skip parent itself)
528 sibling_maps = {parent_id + 1};
529 break;
530 case AreaSizeEnum::TallArea:
531 // 1x2 grid: parent+8 (skip parent itself)
532 sibling_maps = {parent_id + 8};
533 break;
534 default:
535 break;
536 }
537
538 // Copy properties from parent map to all siblings
539 for (int sibling_index : sibling_maps) {
540 if (sibling_index < 0 || sibling_index >= zelda3::kNumOverworldMaps) {
541 continue;
542 }
543 auto& map = *ctx_.overworld->mutable_overworld_map(sibling_index);
544 map.set_area_graphics(current_ow_map.area_graphics());
545 map.set_area_palette(current_ow_map.area_palette());
546 map.set_sprite_graphics(
547 *ctx_.game_state, current_ow_map.sprite_graphics(*ctx_.game_state));
548 map.set_sprite_palette(*ctx_.game_state,
549 current_ow_map.sprite_palette(*ctx_.game_state));
550 map.set_message_id(current_ow_map.message_id());
551
552 // CRITICAL FIX: Reload graphics after changing properties
553 map.LoadAreaGraphics();
554 }
555 }
556 } else {
557 // Legacy logic for vanilla and v2 ROMs
558 if (current_ow_map.is_large_map()) {
559 // We need to copy the properties from the parent map to the children
560 for (int i = 1; i < 4; i++) {
561 int sibling_index = current_ow_map.parent() + i;
562 if (i >= 2) {
563 sibling_index += 6;
564 }
565 auto& map = *ctx_.overworld->mutable_overworld_map(sibling_index);
566 map.set_area_graphics(current_ow_map.area_graphics());
567 map.set_area_palette(current_ow_map.area_palette());
568 map.set_sprite_graphics(
569 *ctx_.game_state, current_ow_map.sprite_graphics(*ctx_.game_state));
570 map.set_sprite_palette(*ctx_.game_state,
571 current_ow_map.sprite_palette(*ctx_.game_state));
572 map.set_message_id(current_ow_map.message_id());
573
574 // CRITICAL FIX: Reload graphics after changing properties
575 map.LoadAreaGraphics();
576 }
577 }
578 }
579}
580
582 LOG_DEBUG("MapRefreshCoordinator", "RefreshTile16Blockset called");
583 if (*ctx_.current_blockset ==
584 ctx_.overworld->overworld_map(*ctx_.current_map)->area_graphics()) {
585 return absl::OkStatus();
586 }
588 ctx_.overworld->overworld_map(*ctx_.current_map)->area_graphics();
589
598 }
599
600 const auto tile16_data = ctx_.overworld->tile16_blockset_data();
601
604
605 // Queue texture update for the atlas
610 } else if (!ctx_.tile16_blockset->atlas.texture() &&
612 // Create texture if it doesn't exist yet
615 }
616
617 return absl::OkStatus();
618}
619
621 // Skip if blockset not loaded or no pending changes
623 return;
624 }
625
627 return;
628 }
629
630 // Validate the atlas bitmap before modifying
632 ctx_.tile16_blockset->atlas.vector().empty() ||
635 return;
636 }
637
638 // Calculate tile positions in the atlas (8 tiles per row, each 16x16)
639 constexpr int kTilesPerRow = 8;
640 constexpr int kTileSize = 16;
641 int atlas_width = ctx_.tile16_blockset->atlas.width();
642 int atlas_height = ctx_.tile16_blockset->atlas.height();
643
644 bool atlas_modified = false;
645
646 // Iterate through all possible tile IDs to check for modifications
647 // Note: This is a brute-force approach; a more efficient method would
648 // maintain a list of modified tile IDs
649 for (int tile_id = 0; tile_id < zelda3::kNumTile16Individual; ++tile_id) {
650 if (!ctx_.tile16_editor->is_tile_modified(tile_id)) {
651 continue;
652 }
653
654 // Get the pending bitmap for this tile
655 const gfx::Bitmap* pending_bmp =
657 if (!pending_bmp || !pending_bmp->is_active() ||
658 pending_bmp->vector().empty()) {
659 continue;
660 }
661
662 // Calculate position in the atlas
663 int tile_x = (tile_id % kTilesPerRow) * kTileSize;
664 int tile_y = (tile_id / kTilesPerRow) * kTileSize;
665
666 // Validate tile position is within atlas bounds
667 if (tile_x + kTileSize > atlas_width || tile_y + kTileSize > atlas_height) {
668 continue;
669 }
670
671 // Copy pending bitmap data into the atlas at the correct position
672 auto& atlas_data = ctx_.tile16_blockset->atlas.mutable_data();
673 const auto& pending_data = pending_bmp->vector();
674
675 for (int y = 0; y < kTileSize && y < pending_bmp->height(); ++y) {
676 for (int x = 0; x < kTileSize && x < pending_bmp->width(); ++x) {
677 int atlas_idx = (tile_y + y) * atlas_width + (tile_x + x);
678 int pending_idx = y * pending_bmp->width() + x;
679
680 if (atlas_idx >= 0 && atlas_idx < static_cast<int>(atlas_data.size()) &&
681 pending_idx >= 0 &&
682 pending_idx < static_cast<int>(pending_data.size())) {
683 atlas_data[atlas_idx] = pending_data[pending_idx];
684 atlas_modified = true;
685 }
686 }
687 }
688 }
689
690 // Only queue texture update if we actually modified something
691 if (atlas_modified && ctx_.tile16_blockset->atlas.texture()) {
695 }
696}
697
698} // namespace yaze::editor
void RefreshMapProperties()
Refresh map properties (copy parent properties to siblings)
void RefreshMultiAreaMapsSafely(int map_index, zelda3::OverworldMap *map)
Safely refresh multi-area maps without recursion.
void RefreshChildMapOnDemand(int map_index)
On-demand child map refresh with selective updates.
void RefreshChildMap(int map_index)
Refresh a child map's graphics pipeline (legacy full rebuild)
absl::Status RefreshMapPalette()
Refresh map palette after palette property changes.
void InvalidateGraphicsCache(int map_id=-1)
Invalidate cached graphics for a specific map or all maps.
void RefreshOverworldMap()
Refresh the current overworld map.
absl::Status RefreshTile16Blockset()
Refresh the tile16 blockset after graphics/palette changes.
void RefreshSiblingMapGraphics(int map_index, bool include_self=false)
Refresh sibling map graphics for multi-area maps.
void UpdateBlocksetWithPendingTileChanges()
Update blockset atlas with pending tile16 editor changes.
void RefreshOverworldMapOnDemand(int map_index)
On-demand map refresh that only updates what's actually needed.
void ForceRefreshGraphics(int map_index)
Force refresh graphics for a specific map.
const gfx::Bitmap * GetPendingTileBitmap(int tile_id) const
Get preview bitmap for a pending tile (nullptr if not modified)
bool has_pending_changes() const
Check if any tiles have uncommitted changes.
bool is_tile_modified(int tile_id) const
Check if a specific tile has pending changes.
void set_palette(const gfx::SnesPalette &palette)
void QueueTextureCommand(TextureCommandType type, Bitmap *bitmap)
Definition arena.cc:36
static Arena & Get()
Definition arena.cc:21
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:67
TextureHandle texture() const
Definition bitmap.h:380
const std::vector< uint8_t > & vector() const
Definition bitmap.h:381
bool is_active() const
Definition bitmap.h:384
void set_modified(bool modified)
Definition bitmap.h:388
int height() const
Definition bitmap.h:374
void SetPalette(const SnesPalette &palette)
Set the palette for the bitmap using SNES palette format.
Definition bitmap.cc:384
int width() const
Definition bitmap.h:373
std::vector< uint8_t > & mutable_data()
Definition bitmap.h:378
Represents a single Overworld map screen.
static OverworldVersion GetVersion(const Rom &rom)
Detect ROM version from ASM marker byte.
static bool SupportsAreaEnum(OverworldVersion version)
Check if ROM supports area enum system (v3+ only)
auto tile16_blockset_data() const
Definition overworld.h:575
auto current_area_palette() const
Definition overworld.h:567
void ClearGraphicsConfigCache()
Clear entire graphics config cache Call when palette or graphics settings change globally.
Definition overworld.h:317
std::vector< gfx::Tile16 > tiles16() const
Definition overworld.h:542
void InvalidateSiblingMapCaches(int map_index)
Invalidate cached tilesets for a map and all its siblings.
auto overworld_map(int i) const
Definition overworld.h:528
void set_current_map(int i)
Definition overworld.h:589
auto mutable_overworld_map(int i)
Definition overworld.h:534
OverworldBlockset & GetMapTiles(int world_type)
Definition overworld.h:514
#define LOG_DEBUG(category, format,...)
Definition log.h:103
#define LOG_ERROR(category, format,...)
Definition log.h:109
#define LOG_WARN(category, format,...)
Definition log.h:107
#define PRINT_IF_ERROR(expression)
Definition macro.h:28
Editors are the view controllers for the application.
void UpdateTilemap(IRenderer *renderer, Tilemap &tilemap, const std::vector< uint8_t > &data)
Definition tilemap.cc:34
constexpr int kNumTile16Individual
Definition overworld.h:239
constexpr int kNumOverworldMaps
Definition common.h:85
AreaSizeEnum
Area size enumeration for v3+ ROMs.
#define RETURN_IF_ERROR(expr)
Definition snes.cc:22
std::function< void(int map_index)> ensure_map_texture
Callback to ensure a map texture is created (stays in OverworldEditor)
std::array< gfx::Bitmap, zelda3::kNumOverworldMaps > * maps_bmp
Bitmap atlas
Master bitmap containing all tiles.
Definition tilemap.h:119