yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
snes_palette.cc
Go to the documentation of this file.
2
4
5#include <array>
6#include <cstdint>
7#include <cstdlib>
8#include <cstring>
9#include <stdexcept>
10#include <string_view>
11#include <utility>
12#include <vector>
13
14#include "absl/status/status.h"
15#include "absl/status/statusor.h"
16#include "absl/strings/str_format.h"
18#include "imgui/imgui.h"
19#include "util/macro.h"
20
21namespace yaze::gfx {
22
24 assert((sizeof(data) % 4 == 0) && (sizeof(data) <= 32));
25 for (unsigned i = 0; i < sizeof(data); i += 2) {
26 SnesColor col;
27 col.set_snes(static_cast<uint8_t>(data[i + 1]) << 8);
28 col.set_snes(col.snes() | static_cast<uint8_t>(data[i]));
29 colors_[size_++] = col;
30 }
31}
32
33SnesPalette::SnesPalette(const unsigned char* snes_pal) {
34 assert((sizeof(snes_pal) % 4 == 0) && (sizeof(snes_pal) <= 32));
35 for (unsigned i = 0; i < sizeof(snes_pal); i += 2) {
36 SnesColor col;
37 col.set_snes(snes_pal[i + 1] << (uint16_t)8);
38 col.set_snes(col.snes() | snes_pal[i]);
39 colors_[size_++] = col;
40 }
41}
42
43SnesPalette::SnesPalette(const char* data, size_t length) : size_(0) {
44 for (size_t i = 0; i < length && size_ < kMaxColors; i += 2) {
45 uint16_t color = (static_cast<uint8_t>(data[i + 1]) << 8) |
46 static_cast<uint8_t>(data[i]);
47 colors_[size_++] = SnesColor(color);
48 }
49}
50
51SnesPalette::SnesPalette(const std::vector<uint16_t>& colors) : size_(0) {
52 for (const auto& color : colors) {
53 if (size_ < kMaxColors) {
54 colors_[size_++] = SnesColor(color);
55 }
56 }
57}
58
59SnesPalette::SnesPalette(const std::vector<SnesColor>& colors) : size_(0) {
60 for (const auto& color : colors) {
61 if (size_ < kMaxColors) {
62 colors_[size_++] = color;
63 }
64 }
65}
66
67SnesPalette::SnesPalette(const std::vector<ImVec4>& colors) : size_(0) {
68 for (const auto& color : colors) {
69 if (size_ < kMaxColors) {
70 colors_[size_++] = SnesColor(color);
71 }
72 }
73}
74
79namespace palette_group_internal {
80absl::Status LoadOverworldMainPalettes(const std::vector<uint8_t>& rom_data,
81 gfx::PaletteGroupMap& palette_groups) {
82 auto data = rom_data.data();
83 size_t rom_size = rom_data.size();
84 for (int i = 0; i < 6; i++) {
85 int offset = kOverworldPaletteMain + (i * (35 * 2));
86 int num_colors = 35;
87 // Bounds check: each color is 2 bytes, so we need offset + (num_colors * 2) bytes
88 if (offset < 0 || offset + (num_colors * 2) > static_cast<int>(rom_size)) {
89 return absl::OutOfRangeError(absl::StrFormat(
90 "Overworld main palette %d out of bounds: offset %d, size %zu", i,
91 offset, rom_size));
92 }
93 palette_groups.overworld_main.AddPalette(
94 gfx::ReadPaletteFromRom(offset, num_colors, data));
95 }
96 return absl::OkStatus();
97}
98
100 const std::vector<uint8_t>& rom_data,
101 gfx::PaletteGroupMap& palette_groups) {
102 auto data = rom_data.data();
103 size_t rom_size = rom_data.size();
104 for (int i = 0; i < 20; i++) {
105 int offset = kOverworldPaletteAux + (i * (21 * 2));
106 int num_colors = 21;
107 if (offset < 0 || offset + (num_colors * 2) > static_cast<int>(rom_size)) {
108 return absl::OutOfRangeError(absl::StrFormat(
109 "Overworld aux palette %d out of bounds: offset %d, size %zu", i,
110 offset, rom_size));
111 }
112 palette_groups.overworld_aux.AddPalette(
113 gfx::ReadPaletteFromRom(offset, num_colors, data));
114 }
115 return absl::OkStatus();
116}
117
119 const std::vector<uint8_t>& rom_data,
120 gfx::PaletteGroupMap& palette_groups) {
121 auto data = rom_data.data();
122 size_t rom_size = rom_data.size();
123 for (int i = 0; i < 14; i++) {
124 int offset = kOverworldPaletteAnimated + (i * (7 * 2));
125 int num_colors = 7;
126 if (offset < 0 || offset + (num_colors * 2) > static_cast<int>(rom_size)) {
127 return absl::OutOfRangeError(absl::StrFormat(
128 "Overworld animated palette %d out of bounds: offset %d, size %zu", i,
129 offset, rom_size));
130 }
131 palette_groups.overworld_animated.AddPalette(
132 gfx::ReadPaletteFromRom(offset, num_colors, data));
133 }
134 return absl::OkStatus();
135}
136
137absl::Status LoadHUDPalettes(const std::vector<uint8_t>& rom_data,
138 gfx::PaletteGroupMap& palette_groups) {
139 auto data = rom_data.data();
140 size_t rom_size = rom_data.size();
141 for (int i = 0; i < 2; i++) {
142 int offset = kHudPalettes + (i * 64);
143 int num_colors = 32;
144 if (offset < 0 || offset + (num_colors * 2) > static_cast<int>(rom_size)) {
145 return absl::OutOfRangeError(
146 absl::StrFormat("HUD palette %d out of bounds: offset %d, size %zu",
147 i, offset, rom_size));
148 }
149 palette_groups.hud.AddPalette(
150 gfx::ReadPaletteFromRom(offset, num_colors, data));
151 }
152 return absl::OkStatus();
153}
154
155absl::Status LoadGlobalSpritePalettes(const std::vector<uint8_t>& rom_data,
156 gfx::PaletteGroupMap& palette_groups) {
157 auto data = rom_data.data();
158 size_t rom_size = rom_data.size();
159
160 // Check first palette
161 int offset1 = kGlobalSpritesLW;
162 int num_colors1 = 60;
163 if (offset1 < 0 || offset1 + (num_colors1 * 2) > static_cast<int>(rom_size)) {
164 return absl::OutOfRangeError(absl::StrFormat(
165 "Global sprite LW palette out of bounds: offset %d, size %zu", offset1,
166 rom_size));
167 }
168 palette_groups.global_sprites.AddPalette(
169 gfx::ReadPaletteFromRom(offset1, num_colors1, data));
170
171 // Check second palette
172 int offset2 = kGlobalSpritePalettesDW;
173 int num_colors2 = 60;
174 if (offset2 < 0 || offset2 + (num_colors2 * 2) > static_cast<int>(rom_size)) {
175 return absl::OutOfRangeError(absl::StrFormat(
176 "Global sprite DW palette out of bounds: offset %d, size %zu", offset2,
177 rom_size));
178 }
179 palette_groups.global_sprites.AddPalette(
180 gfx::ReadPaletteFromRom(offset2, num_colors2, data));
181 return absl::OkStatus();
182}
183
184absl::Status LoadArmorPalettes(const std::vector<uint8_t>& rom_data,
185 gfx::PaletteGroupMap& palette_groups) {
186 auto data = rom_data.data();
187 size_t rom_size = rom_data.size();
188 for (int i = 0; i < 5; i++) {
189 int offset = kArmorPalettes + (i * 30);
190 int num_colors = 15;
191 if (offset < 0 || offset + (num_colors * 2) > static_cast<int>(rom_size)) {
192 return absl::OutOfRangeError(
193 absl::StrFormat("Armor palette %d out of bounds: offset %d, size %zu",
194 i, offset, rom_size));
195 }
196 palette_groups.armors.AddPalette(
197 gfx::ReadPaletteFromRom(offset, num_colors, data));
198 }
199 return absl::OkStatus();
200}
201
202absl::Status LoadSwordPalettes(const std::vector<uint8_t>& rom_data,
203 gfx::PaletteGroupMap& palette_groups) {
204 auto data = rom_data.data();
205 size_t rom_size = rom_data.size();
206 for (int i = 0; i < 4; i++) {
207 int offset = kSwordPalettes + (i * 6);
208 int num_colors = 3;
209 if (offset < 0 || offset + (num_colors * 2) > static_cast<int>(rom_size)) {
210 return absl::OutOfRangeError(
211 absl::StrFormat("Sword palette %d out of bounds: offset %d, size %zu",
212 i, offset, rom_size));
213 }
214 palette_groups.swords.AddPalette(
215 gfx::ReadPaletteFromRom(offset, num_colors, data));
216 }
217 return absl::OkStatus();
218}
219
220absl::Status LoadShieldPalettes(const std::vector<uint8_t>& rom_data,
221 gfx::PaletteGroupMap& palette_groups) {
222 auto data = rom_data.data();
223 size_t rom_size = rom_data.size();
224 for (int i = 0; i < 3; i++) {
225 int offset = kShieldPalettes + (i * 8);
226 int num_colors = 4;
227 if (offset < 0 || offset + (num_colors * 2) > static_cast<int>(rom_size)) {
228 return absl::OutOfRangeError(absl::StrFormat(
229 "Shield palette %d out of bounds: offset %d, size %zu", i, offset,
230 rom_size));
231 }
232 palette_groups.shields.AddPalette(
233 gfx::ReadPaletteFromRom(offset, num_colors, data));
234 }
235 return absl::OkStatus();
236}
237
238absl::Status LoadSpriteAux1Palettes(const std::vector<uint8_t>& rom_data,
239 gfx::PaletteGroupMap& palette_groups) {
240 auto data = rom_data.data();
241 size_t rom_size = rom_data.size();
242 for (int i = 0; i < 12; i++) {
243 int offset = kSpritesPalettesAux1 + (i * 14);
244 int num_colors = 7;
245 if (offset < 0 || offset + (num_colors * 2) > static_cast<int>(rom_size)) {
246 return absl::OutOfRangeError(absl::StrFormat(
247 "Sprite aux1 palette %d out of bounds: offset %d, size %zu", i,
248 offset, rom_size));
249 }
250 palette_groups.sprites_aux1.AddPalette(
251 gfx::ReadPaletteFromRom(offset, num_colors, data));
252 }
253 return absl::OkStatus();
254}
255
256absl::Status LoadSpriteAux2Palettes(const std::vector<uint8_t>& rom_data,
257 gfx::PaletteGroupMap& palette_groups) {
258 auto data = rom_data.data();
259 size_t rom_size = rom_data.size();
260 for (int i = 0; i < 11; i++) {
261 int offset = kSpritesPalettesAux2 + (i * 14);
262 int num_colors = 7;
263 if (offset < 0 || offset + (num_colors * 2) > static_cast<int>(rom_size)) {
264 return absl::OutOfRangeError(absl::StrFormat(
265 "Sprite aux2 palette %d out of bounds: offset %d, size %zu", i,
266 offset, rom_size));
267 }
268 palette_groups.sprites_aux2.AddPalette(
269 gfx::ReadPaletteFromRom(offset, num_colors, data));
270 }
271 return absl::OkStatus();
272}
273
274absl::Status LoadSpriteAux3Palettes(const std::vector<uint8_t>& rom_data,
275 gfx::PaletteGroupMap& palette_groups) {
276 auto data = rom_data.data();
277 size_t rom_size = rom_data.size();
278 for (int i = 0; i < 24; i++) {
279 int offset = kSpritesPalettesAux3 + (i * 14);
280 int num_colors = 7;
281 if (offset < 0 || offset + (num_colors * 2) > static_cast<int>(rom_size)) {
282 return absl::OutOfRangeError(absl::StrFormat(
283 "Sprite aux3 palette %d out of bounds: offset %d, size %zu", i,
284 offset, rom_size));
285 }
286 palette_groups.sprites_aux3.AddPalette(
287 gfx::ReadPaletteFromRom(offset, num_colors, data));
288 }
289 return absl::OkStatus();
290}
291
292absl::Status LoadDungeonMainPalettes(const std::vector<uint8_t>& rom_data,
293 gfx::PaletteGroupMap& palette_groups) {
294 auto data = rom_data.data();
295 size_t rom_size = rom_data.size();
296 for (int i = 0; i < 20; i++) {
297 int offset = kDungeonMainPalettes + (i * 180);
298 int num_colors = 90;
299 if (offset < 0 || offset + (num_colors * 2) > static_cast<int>(rom_size)) {
300 return absl::OutOfRangeError(absl::StrFormat(
301 "Dungeon main palette %d out of bounds: offset %d, size %zu", i,
302 offset, rom_size));
303 }
304 palette_groups.dungeon_main.AddPalette(
305 gfx::ReadPaletteFromRom(offset, num_colors, data));
306 }
307 return absl::OkStatus();
308}
309
310absl::Status LoadGrassColors(const std::vector<uint8_t>& rom_data,
311 gfx::PaletteGroupMap& palette_groups) {
312 size_t rom_size = rom_data.size();
313
314 // Each color is 2 bytes
315 if (kHardcodedGrassLW < 0 ||
316 kHardcodedGrassLW + 2 > static_cast<int>(rom_size)) {
317 return absl::OutOfRangeError(
318 absl::StrFormat("Grass LW color out of bounds: offset %d, size %zu",
319 kHardcodedGrassLW, rom_size));
320 }
321 palette_groups.grass.AddColor(
322 gfx::ReadColorFromRom(kHardcodedGrassLW, rom_data.data()));
323
324 if (kHardcodedGrassDW < 0 ||
325 kHardcodedGrassDW + 2 > static_cast<int>(rom_size)) {
326 return absl::OutOfRangeError(
327 absl::StrFormat("Grass DW color out of bounds: offset %d, size %zu",
328 kHardcodedGrassDW, rom_size));
329 }
330 palette_groups.grass.AddColor(
331 gfx::ReadColorFromRom(kHardcodedGrassDW, rom_data.data()));
332
333 if (kHardcodedGrassSpecial < 0 ||
334 kHardcodedGrassSpecial + 2 > static_cast<int>(rom_size)) {
335 return absl::OutOfRangeError(absl::StrFormat(
336 "Grass special color out of bounds: offset %d, size %zu",
337 kHardcodedGrassSpecial, rom_size));
338 }
339 palette_groups.grass.AddColor(
341 return absl::OkStatus();
342}
343
344absl::Status Load3DObjectPalettes(const std::vector<uint8_t>& rom_data,
345 gfx::PaletteGroupMap& palette_groups) {
346 auto data = rom_data.data();
347 size_t rom_size = rom_data.size();
348
349 int offset1 = kTriforcePalette;
350 int num_colors1 = 8;
351 if (offset1 < 0 || offset1 + (num_colors1 * 2) > static_cast<int>(rom_size)) {
352 return absl::OutOfRangeError(
353 absl::StrFormat("Triforce palette out of bounds: offset %d, size %zu",
354 offset1, rom_size));
355 }
356 palette_groups.object_3d.AddPalette(
357 gfx::ReadPaletteFromRom(offset1, num_colors1, data));
358
359 int offset2 = kCrystalPalette;
360 int num_colors2 = 8;
361 if (offset2 < 0 || offset2 + (num_colors2 * 2) > static_cast<int>(rom_size)) {
362 return absl::OutOfRangeError(
363 absl::StrFormat("Crystal palette out of bounds: offset %d, size %zu",
364 offset2, rom_size));
365 }
366 palette_groups.object_3d.AddPalette(
367 gfx::ReadPaletteFromRom(offset2, num_colors2, data));
368 return absl::OkStatus();
369}
370
372 const std::vector<uint8_t>& rom_data,
373 gfx::PaletteGroupMap& palette_groups) {
374 auto data = rom_data.data();
375 size_t rom_size = rom_data.size();
376 for (int i = 0; i < 2; i++) {
377 int offset = kOverworldMiniMapPalettes + (i * 256);
378 int num_colors = 128;
379 if (offset < 0 || offset + (num_colors * 2) > static_cast<int>(rom_size)) {
380 return absl::OutOfRangeError(absl::StrFormat(
381 "Overworld minimap palette %d out of bounds: offset %d, size %zu", i,
382 offset, rom_size));
383 }
384 palette_groups.overworld_mini_map.AddPalette(
385 gfx::ReadPaletteFromRom(offset, num_colors, data));
386 }
387 return absl::OkStatus();
388}
389} // namespace palette_group_internal
390
391constexpr std::array<std::pair<absl::string_view, uint32_t>, 15>
393 {"ow_main", kOverworldPaletteMain},
394 {"ow_aux", kOverworldPaletteAux},
395 {"ow_animated", kOverworldPaletteAnimated},
396 {"hud", kHudPalettes},
397 {"global_sprites", kGlobalSpritesLW},
398 {"armors", kArmorPalettes},
399 {"swords", kSwordPalettes},
400 {"shields", kShieldPalettes},
401 {"sprites_aux1", kSpritesPalettesAux1},
402 {"sprites_aux2", kSpritesPalettesAux2},
403 {"sprites_aux3", kSpritesPalettesAux3},
404 {"dungeon_main", kDungeonMainPalettes},
405 {"grass", kHardcodedGrassLW},
406 {"3d_object", kTriforcePalette},
407 {"ow_mini_map", kOverworldMiniMapPalettes},
408 }};
409
410constexpr std::array<std::pair<absl::string_view, uint32_t>, 15>
412 {"ow_main", 35},
413 {"ow_aux", 21},
414 {"ow_animated", 7},
415 {"hud", 32},
416 {"global_sprites", 60},
417 {"armors", 15},
418 {"swords", 3},
419 {"shields", 4},
420 {"sprites_aux1", 7},
421 {"sprites_aux2", 7},
422 {"sprites_aux3", 7},
423 {"dungeon_main", 90},
424 {"grass", 1},
425 {"3d_object", 8},
426 {"ow_mini_map", 128},
427 }};
428
429template <size_t N>
431 absl::string_view group_name,
432 const std::array<std::pair<absl::string_view, uint32_t>, N>& table) {
433 for (const auto& [name, value] : table) {
434 if (name == group_name) {
435 return value;
436 }
437 }
438 throw std::out_of_range(
439 absl::StrFormat("Unknown palette group: %s", group_name));
440}
441
442uint32_t GetPaletteAddress(const std::string& group_name, size_t palette_index,
443 size_t color_index) {
444 // Retrieve the base address and palette width for the palette group.
445 const uint32_t base_address =
447 const uint32_t colors_per_palette =
449
450 // Calculate the address for thes specified color in the ROM
451 uint32_t address = base_address + (palette_index * colors_per_palette * 2) +
452 (color_index * 2);
453
454 return address;
455}
456
483SnesPalette ReadPaletteFromRom(int offset, int num_colors, const uint8_t* rom) {
484 int color_offset = 0;
485 std::vector<gfx::SnesColor> colors(num_colors);
486
487 while (color_offset < num_colors) {
488 // Bounds check before accessing ROM data
489 // Each color is 2 bytes, so we need at least offset + 1 bytes available
490 // Note: We can't check full bounds here without ROM size, but we can at least
491 // validate the immediate access. Full bounds should be checked by caller.
492
493 // Read SNES 15-bit color (little endian)
494 uint16_t snes_color_word = (uint16_t)((rom[offset + 1]) << 8) | rom[offset];
495
496 // Extract RGB components (5-bit each) and expand to 8-bit (0-255)
497 snes_color new_color;
498 new_color.red = (snes_color_word & 0x1F) * 8; // Bits 0-4
499 new_color.green = ((snes_color_word >> 5) & 0x1F) * 8; // Bits 5-9
500 new_color.blue = ((snes_color_word >> 10) & 0x1F) * 8; // Bits 10-14
501
502 // Create SnesColor by converting RGB back to SNES format
503 // (This ensures all internal representations are consistent)
504 colors[color_offset].set_snes(ConvertRgbToSnes(new_color));
505
506 // DO NOT mark as transparent - preserve actual ROM color data!
507 // Transparency is handled at render time, not in the data
508
509 color_offset++;
510 offset += 2; // SNES colors are 2 bytes each
511 }
512
513 return gfx::SnesPalette(colors);
514}
515
516std::array<float, 4> ToFloatArray(const SnesColor& color) {
517 std::array<float, 4> colorArray;
518 colorArray[0] = color.rgb().x / 255.0f;
519 colorArray[1] = color.rgb().y / 255.0f;
520 colorArray[2] = color.rgb().z / 255.0f;
521 colorArray[3] = color.rgb().w;
522 return colorArray;
523}
524
525absl::StatusOr<PaletteGroup> CreatePaletteGroupFromColFile(
526 std::vector<SnesColor>& palette_rows) {
527 PaletteGroup palette_group;
528 for (int i = 0; i < palette_rows.size(); i += 8) {
529 SnesPalette palette;
530 for (int j = 0; j < 8; j++) {
531 palette.AddColor(palette_rows[i + j]);
532 }
533 palette_group.AddPalette(palette);
534 }
535 return palette_group;
536}
537
553absl::StatusOr<PaletteGroup> CreatePaletteGroupFromLargePalette(
554 SnesPalette& palette, int num_colors) {
555 PaletteGroup palette_group;
556 for (int i = 0; i < palette.size(); i += num_colors) {
557 SnesPalette new_palette;
558 if (i + num_colors <= palette.size()) {
559 for (int j = 0; j < num_colors; j++) {
560 auto color = palette[i + j];
561 // DO NOT mark as transparent - preserve actual color data!
562 // Transparency is handled at render time, not in the data
563 new_palette.AddColor(color);
564 }
565 }
566 palette_group.AddPalette(new_palette);
567 }
568 return palette_group;
569}
570
571using namespace palette_group_internal;
572
573// TODO: Refactor LoadAllPalettes to use group names, move to zelda3 namespace
574absl::Status LoadAllPalettes(const std::vector<uint8_t>& rom_data,
575 PaletteGroupMap& groups) {
579 RETURN_IF_ERROR(LoadHUDPalettes(rom_data, groups))
581 RETURN_IF_ERROR(LoadArmorPalettes(rom_data, groups))
582 RETURN_IF_ERROR(LoadSwordPalettes(rom_data, groups))
583 RETURN_IF_ERROR(LoadShieldPalettes(rom_data, groups))
584 RETURN_IF_ERROR(LoadSpriteAux1Palettes(rom_data, groups))
585 RETURN_IF_ERROR(LoadSpriteAux2Palettes(rom_data, groups))
586 RETURN_IF_ERROR(LoadSpriteAux3Palettes(rom_data, groups))
588 RETURN_IF_ERROR(LoadGrassColors(rom_data, groups))
589 RETURN_IF_ERROR(Load3DObjectPalettes(rom_data, groups))
591 return absl::OkStatus();
592}
593
594std::unordered_map<uint8_t, gfx::Paletteset> GfxContext::palettesets_;
595
596} // namespace yaze::gfx
static std::unordered_map< uint8_t, gfx::Paletteset > palettesets_
SNES Color container.
Definition snes_color.h:110
constexpr ImVec4 rgb() const
Get RGB values (WARNING: stored as 0-255 in ImVec4)
Definition snes_color.h:183
void set_snes(uint16_t val)
Set color from SNES 15-bit format.
constexpr uint16_t snes() const
Get SNES 15-bit color.
Definition snes_color.h:193
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
void AddColor(const SnesColor &color)
static constexpr size_t kMaxColors
absl::Status LoadDungeonMainPalettes(const std::vector< uint8_t > &rom_data, gfx::PaletteGroupMap &palette_groups)
absl::Status LoadOverworldMiniMapPalettes(const std::vector< uint8_t > &rom_data, gfx::PaletteGroupMap &palette_groups)
absl::Status LoadSpriteAux2Palettes(const std::vector< uint8_t > &rom_data, gfx::PaletteGroupMap &palette_groups)
absl::Status LoadOverworldMainPalettes(const std::vector< uint8_t > &rom_data, gfx::PaletteGroupMap &palette_groups)
absl::Status LoadSpriteAux1Palettes(const std::vector< uint8_t > &rom_data, gfx::PaletteGroupMap &palette_groups)
absl::Status LoadGlobalSpritePalettes(const std::vector< uint8_t > &rom_data, gfx::PaletteGroupMap &palette_groups)
absl::Status LoadOverworldAnimatedPalettes(const std::vector< uint8_t > &rom_data, gfx::PaletteGroupMap &palette_groups)
absl::Status LoadArmorPalettes(const std::vector< uint8_t > &rom_data, gfx::PaletteGroupMap &palette_groups)
absl::Status LoadGrassColors(const std::vector< uint8_t > &rom_data, gfx::PaletteGroupMap &palette_groups)
absl::Status LoadSpriteAux3Palettes(const std::vector< uint8_t > &rom_data, gfx::PaletteGroupMap &palette_groups)
absl::Status LoadHUDPalettes(const std::vector< uint8_t > &rom_data, gfx::PaletteGroupMap &palette_groups)
absl::Status LoadShieldPalettes(const std::vector< uint8_t > &rom_data, gfx::PaletteGroupMap &palette_groups)
absl::Status LoadOverworldAuxiliaryPalettes(const std::vector< uint8_t > &rom_data, gfx::PaletteGroupMap &palette_groups)
absl::Status Load3DObjectPalettes(const std::vector< uint8_t > &rom_data, gfx::PaletteGroupMap &palette_groups)
absl::Status LoadSwordPalettes(const std::vector< uint8_t > &rom_data, gfx::PaletteGroupMap &palette_groups)
Contains classes for handling graphical data.
Definition editor.h:27
constexpr int kHardcodedGrassSpecial
constexpr int kHudPalettes
constexpr int kOverworldPaletteAux
SnesPalette ReadPaletteFromRom(int offset, int num_colors, const uint8_t *rom)
Read a palette from ROM data.
uint32_t LookupPaletteGroupValue(absl::string_view group_name, const std::array< std::pair< absl::string_view, uint32_t >, N > &table)
absl::StatusOr< PaletteGroup > CreatePaletteGroupFromLargePalette(SnesPalette &palette, int num_colors)
Create a PaletteGroup by dividing a large palette into sub-palettes.
constexpr int kHardcodedGrassLW
constexpr int kArmorPalettes
constexpr std::array< std::pair< absl::string_view, uint32_t >, 15 > kPaletteGroupAddressMap
constexpr int kCrystalPalette
uint16_t ConvertRgbToSnes(const snes_color &color)
Convert RGB (0-255) to SNES 15-bit color.
Definition snes_color.cc:33
constexpr int kShieldPalettes
constexpr int kSpritesPalettesAux2
constexpr int kOverworldPaletteAnimated
SnesColor ReadColorFromRom(int offset, const uint8_t *rom)
Definition snes_color.cc:48
constexpr int kOverworldMiniMapPalettes
constexpr int kOverworldPaletteMain
constexpr int kSwordPalettes
constexpr int kHardcodedGrassDW
constexpr int kGlobalSpritesLW
constexpr int kSpritesPalettesAux1
constexpr std::array< std::pair< absl::string_view, uint32_t >, 15 > kPaletteGroupColorCounts
std::array< float, 4 > ToFloatArray(const SnesColor &color)
constexpr int kGlobalSpritePalettesDW
constexpr int kSpritesPalettesAux3
constexpr int kDungeonMainPalettes
uint32_t GetPaletteAddress(const std::string &group_name, size_t palette_index, size_t color_index)
constexpr int kTriforcePalette
absl::Status LoadAllPalettes(const std::vector< uint8_t > &rom_data, PaletteGroupMap &groups)
Loads all the palettes for the game.
absl::StatusOr< PaletteGroup > CreatePaletteGroupFromColFile(std::vector< SnesColor > &palette_rows)
SDL2/SDL3 compatibility layer.
#define RETURN_IF_ERROR(expr)
Definition snes.cc:22
SNES color in 15-bit RGB format (BGR555)
uint16_t green
uint16_t red
uint16_t blue
Represents a mapping of palette groups.
Represents a group of palettes.
void AddColor(SnesColor color)
void AddPalette(SnesPalette pal)