yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
overworld_graphics_context.cc
Go to the documentation of this file.
2
3#include <cstdint>
4#include <utility>
5#include <vector>
6
7#include "absl/status/status.h"
8#include "absl/status/statusor.h"
9#include "absl/strings/str_format.h"
15
16namespace yaze::editor {
17
18// Resolve the raw sheet pixel source of one Tile16 quadrant. The map must be
19// the selected, built screen: its static slots and palette already include
20// parent-area, special-world, and alternate-palette resolution. Sheet pixels
21// remain owned by GameData::sheet_store; these colors are display metadata.
22absl::StatusOr<GraphicsEditTarget> ResolveOverworldQuadrantTarget(
23 const zelda3::OverworldMap& map, const gfx::Tile16& tile16, int tile16_id,
24 int quadrant, const zelda3::GameData* owner) {
25 if (owner == nullptr || (map.game_data() && map.game_data() != owner)) {
26 return absl::FailedPreconditionError(
27 "Overworld graphics session is missing or mismatched");
28 }
29 if (quadrant < 0 || quadrant >= 4 || tile16_id < 0 ||
30 tile16_id >= zelda3::kNumTile16Individual) {
31 return absl::InvalidArgumentError("Invalid Tile16 quadrant");
32 }
33 const auto& tile = zelda3::Tile16QuadrantInfo(tile16, quadrant);
34 if (tile.id_ >= 8 * 64) {
35 return absl::UnimplementedError(
36 "This Tile16 quadrant does not address an overworld background sheet");
37 }
38 const int slot = tile.id_ / 64;
39 const int tile_index = tile.id_ % 64;
40 if (slot == 7 && tile_index < 32) {
41 return absl::UnimplementedError(
42 "Animated slot 7 tiles need an explicit frame source");
43 }
44 const uint16_t sheet = map.static_graphics(slot);
45 if (sheet == 0 || sheet >= zelda3::kGfxSheetCount ||
48 !owner->sheet_store.HasSheet(sheet)) {
49 return absl::UnimplementedError(
50 "This quadrant has no loaded editable 3bpp sheet");
51 }
52
53 // BuildTileset adds $88 to slots 0, 3, 4, and 5. BuildTiles16Gfx masks
54 // with $0F and adds the quadrant's palette row. Thus raw pixel indices 0-7
55 // resolve to the right palette half for those slots, left for the others.
56 const bool right = slot == 0 || slot == 3 || slot == 4 || slot == 5;
57 const size_t base = static_cast<size_t>(tile.palette_) * 16 + (right ? 8 : 0);
58 const auto& colors = map.current_palette();
59 if (tile.palette_ >= 8 || colors.size() < base + 8) {
60 return absl::FailedPreconditionError(
61 "Selected map palette is not resolved");
62 }
63 std::vector<gfx::SnesColor> display_colors;
64 display_colors.reserve(8);
65 for (int i = 0; i < 8; ++i) {
66 display_colors.push_back(colors[base + i]);
67 }
68 GraphicsEditTarget target{
69 .sheet_id = sheet,
70 .tile_index = static_cast<uint16_t>(tile_index),
71 .label = absl::StrFormat(
72 "Tile16 %03X / quadrant %d / tile %03X / slot %d / sheet %02X / "
73 "row %d %s",
74 tile16_id, quadrant + 1, tile.id_, slot, sheet, tile.palette_,
75 right ? "right" : "left"),
76 .palette = gfx::SnesPalette(display_colors),
77 .source_orientation_mask =
78 static_cast<uint8_t>(1 << ((tile.horizontal_mirror_ ? 1 : 0) |
79 (tile.vertical_mirror_ ? 2 : 0))),
80 };
81 if (map.game_data() == owner) {
83 tile.palette_, right ? 8 : 0);
84 }
85 return target;
86}
87
88absl::StatusOr<GraphicsEditContext> MakeOverworldGraphicsEditContext(
89 const zelda3::OverworldMap& map, const gfx::Tile16& tile16, int tile16_id,
90 int quadrant, const zelda3::GameData* owner) {
91 auto target =
92 ResolveOverworldQuadrantTarget(map, tile16, tile16_id, quadrant, owner);
93 if (!target.ok()) {
94 return target.status();
95 }
96 GraphicsEditContext context;
97 context.owner = owner;
98 context.label = absl::StrFormat(
99 "Map %02X (area %02X) / Tile16 %03X / quadrant %d / palette %02X",
100 map.index(), map.parent(), tile16_id, quadrant + 1,
101 map.render_main_palette());
102 context.limitation =
103 "Map assignments are captured on entry; reopen from the overworld "
104 "after changing assignments.";
106 context.targets.push_back(std::move(*target));
107 // Focus the requested quadrant, but keep the rest of this Tile16 available
108 // without another trip through the source editor. Each quadrant retains its
109 // own palette and orientation, even when two use the same physical tile.
110 for (int other = 0; other < 4; ++other) {
111 if (other == quadrant) {
112 continue;
113 }
114 auto neighbor =
115 ResolveOverworldQuadrantTarget(map, tile16, tile16_id, other, owner);
116 if (!neighbor.ok()) {
117 if (neighbor.status().code() != absl::StatusCode::kUnimplemented) {
118 return neighbor.status();
119 }
120 context.limitation +=
121 absl::StrFormat(" Quadrant %d is omitted: %s.", other + 1,
122 neighbor.status().message());
123 continue;
124 }
125 context.targets.push_back(std::move(*neighbor));
126 }
127 return context;
128}
129
130} // namespace yaze::editor
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
Tile composition of four 8x8 tiles.
Definition snes_tile.h:142
bool HasSheet(uint16_t sheet) const
True when the buffer holds all 4096 bytes of sheet.
Represents a single Overworld map screen.
const gfx::SnesPalette & current_palette() const
uint8_t render_main_palette() const
auto static_graphics(int i) const
const GameData * game_data() const
const PaletteAddressMap & palette_addresses() const
Locates graphics sheets in the ROM and writes edited sheets back.
Editors are the view controllers for the application.
absl::StatusOr< GraphicsEditTarget > ResolveOverworldQuadrantTarget(const zelda3::OverworldMap &map, const gfx::Tile16 &tile16, int tile16_id, int quadrant, const zelda3::GameData *owner)
void ResolveGraphicsPaletteAddressing(GraphicsEditTarget &target, const zelda3::GameData *owner, const zelda3::PaletteAddressMap &addresses, int row, int half_offset)
absl::StatusOr< GraphicsEditContext > MakeOverworldGraphicsEditContext(const zelda3::OverworldMap &map, const gfx::Tile16 &tile16, int tile16_id, int quadrant, const zelda3::GameData *owner)
constexpr int kNumTile16Individual
Definition overworld.h:243
const gfx::TileInfo & Tile16QuadrantInfo(const gfx::Tile16 &tile, int quadrant)
GfxSheetStorageKind GetGfxSheetStorageKind(uint16_t sheet_id)
constexpr size_t kGfxSheetCount
ResolvedGraphicsContext DescribeOverworldGraphicsContext(const OverworldMap &map, const GraphicsContextIdentity &identity)
zelda3::ResolvedGraphicsContext resolved
std::vector< GraphicsEditTarget > targets