10#include "absl/container/flat_hash_map.h"
11#include "absl/status/status.h"
12#include "absl/status/statusor.h"
13#include "absl/strings/str_format.h"
15#include "imgui/imgui.h"
21 assert((
sizeof(data) % 4 == 0) && (
sizeof(data) <= 32));
22 for (
unsigned i = 0; i <
sizeof(data); i += 2) {
24 col.
set_snes(
static_cast<uint8_t
>(data[i + 1]) << 8);
25 col.
set_snes(col.
snes() |
static_cast<uint8_t
>(data[i]));
31 assert((
sizeof(snes_pal) % 4 == 0) && (
sizeof(snes_pal) <= 32));
32 for (
unsigned i = 0; i <
sizeof(snes_pal); i += 2) {
34 col.
set_snes(snes_pal[i + 1] << (uint16_t)8);
42 uint16_t color = (
static_cast<uint8_t
>(data[i + 1]) << 8) |
43 static_cast<uint8_t
>(data[i]);
49 for (
const auto& color : colors) {
57 for (
const auto& color : colors) {
65 for (
const auto& color : colors) {
76namespace palette_group_internal {
79 auto data = rom_data.data();
80 size_t rom_size = rom_data.size();
81 for (
int i = 0; i < 6; i++) {
85 if (offset < 0 || offset + (num_colors * 2) >
static_cast<int>(rom_size)) {
86 return absl::OutOfRangeError(absl::StrFormat(
87 "Overworld main palette %d out of bounds: offset %d, size %zu", i,
93 return absl::OkStatus();
97 const std::vector<uint8_t>& rom_data,
99 auto data = rom_data.data();
100 size_t rom_size = rom_data.size();
101 for (
int i = 0; i < 20; i++) {
104 if (offset < 0 || offset + (num_colors * 2) >
static_cast<int>(rom_size)) {
105 return absl::OutOfRangeError(absl::StrFormat(
106 "Overworld aux palette %d out of bounds: offset %d, size %zu", i,
112 return absl::OkStatus();
116 const std::vector<uint8_t>& rom_data,
118 auto data = rom_data.data();
119 size_t rom_size = rom_data.size();
120 for (
int i = 0; i < 14; i++) {
123 if (offset < 0 || offset + (num_colors * 2) >
static_cast<int>(rom_size)) {
124 return absl::OutOfRangeError(absl::StrFormat(
125 "Overworld animated palette %d out of bounds: offset %d, size %zu", i,
131 return absl::OkStatus();
136 auto data = rom_data.data();
137 size_t rom_size = rom_data.size();
138 for (
int i = 0; i < 2; i++) {
141 if (offset < 0 || offset + (num_colors * 2) >
static_cast<int>(rom_size)) {
142 return absl::OutOfRangeError(
143 absl::StrFormat(
"HUD palette %d out of bounds: offset %d, size %zu",
144 i, offset, rom_size));
149 return absl::OkStatus();
154 auto data = rom_data.data();
155 size_t rom_size = rom_data.size();
159 int num_colors1 = 60;
160 if (offset1 < 0 || offset1 + (num_colors1 * 2) >
static_cast<int>(rom_size)) {
161 return absl::OutOfRangeError(absl::StrFormat(
162 "Global sprite LW palette out of bounds: offset %d, size %zu", offset1,
170 int num_colors2 = 60;
171 if (offset2 < 0 || offset2 + (num_colors2 * 2) >
static_cast<int>(rom_size)) {
172 return absl::OutOfRangeError(absl::StrFormat(
173 "Global sprite DW palette out of bounds: offset %d, size %zu", offset2,
178 return absl::OkStatus();
183 auto data = rom_data.data();
184 size_t rom_size = rom_data.size();
185 for (
int i = 0; i < 5; i++) {
188 if (offset < 0 || offset + (num_colors * 2) >
static_cast<int>(rom_size)) {
189 return absl::OutOfRangeError(
190 absl::StrFormat(
"Armor palette %d out of bounds: offset %d, size %zu",
191 i, offset, rom_size));
196 return absl::OkStatus();
201 auto data = rom_data.data();
202 size_t rom_size = rom_data.size();
203 for (
int i = 0; i < 4; i++) {
206 if (offset < 0 || offset + (num_colors * 2) >
static_cast<int>(rom_size)) {
207 return absl::OutOfRangeError(
208 absl::StrFormat(
"Sword palette %d out of bounds: offset %d, size %zu",
209 i, offset, rom_size));
214 return absl::OkStatus();
219 auto data = rom_data.data();
220 size_t rom_size = rom_data.size();
221 for (
int i = 0; i < 3; i++) {
224 if (offset < 0 || offset + (num_colors * 2) >
static_cast<int>(rom_size)) {
225 return absl::OutOfRangeError(absl::StrFormat(
226 "Shield palette %d out of bounds: offset %d, size %zu", i, offset,
232 return absl::OkStatus();
237 auto data = rom_data.data();
238 size_t rom_size = rom_data.size();
239 for (
int i = 0; i < 12; i++) {
242 if (offset < 0 || offset + (num_colors * 2) >
static_cast<int>(rom_size)) {
243 return absl::OutOfRangeError(absl::StrFormat(
244 "Sprite aux1 palette %d out of bounds: offset %d, size %zu", i,
250 return absl::OkStatus();
255 auto data = rom_data.data();
256 size_t rom_size = rom_data.size();
257 for (
int i = 0; i < 11; i++) {
260 if (offset < 0 || offset + (num_colors * 2) >
static_cast<int>(rom_size)) {
261 return absl::OutOfRangeError(absl::StrFormat(
262 "Sprite aux2 palette %d out of bounds: offset %d, size %zu", i,
268 return absl::OkStatus();
273 auto data = rom_data.data();
274 size_t rom_size = rom_data.size();
275 for (
int i = 0; i < 24; i++) {
278 if (offset < 0 || offset + (num_colors * 2) >
static_cast<int>(rom_size)) {
279 return absl::OutOfRangeError(absl::StrFormat(
280 "Sprite aux3 palette %d out of bounds: offset %d, size %zu", i,
286 return absl::OkStatus();
291 auto data = rom_data.data();
292 size_t rom_size = rom_data.size();
293 for (
int i = 0; i < 20; i++) {
296 if (offset < 0 || offset + (num_colors * 2) >
static_cast<int>(rom_size)) {
297 return absl::OutOfRangeError(absl::StrFormat(
298 "Dungeon main palette %d out of bounds: offset %d, size %zu", i,
304 return absl::OkStatus();
309 size_t rom_size = rom_data.size();
314 return absl::OutOfRangeError(
315 absl::StrFormat(
"Grass LW color out of bounds: offset %d, size %zu",
323 return absl::OutOfRangeError(
324 absl::StrFormat(
"Grass DW color out of bounds: offset %d, size %zu",
332 return absl::OutOfRangeError(absl::StrFormat(
333 "Grass special color out of bounds: offset %d, size %zu",
338 return absl::OkStatus();
343 auto data = rom_data.data();
344 size_t rom_size = rom_data.size();
348 if (offset1 < 0 || offset1 + (num_colors1 * 2) >
static_cast<int>(rom_size)) {
349 return absl::OutOfRangeError(
350 absl::StrFormat(
"Triforce palette out of bounds: offset %d, size %zu",
358 if (offset2 < 0 || offset2 + (num_colors2 * 2) >
static_cast<int>(rom_size)) {
359 return absl::OutOfRangeError(
360 absl::StrFormat(
"Crystal palette out of bounds: offset %d, size %zu",
365 return absl::OkStatus();
369 const std::vector<uint8_t>& rom_data,
371 auto data = rom_data.data();
372 size_t rom_size = rom_data.size();
373 for (
int i = 0; i < 2; i++) {
375 int num_colors = 128;
376 if (offset < 0 || offset + (num_colors * 2) >
static_cast<int>(rom_size)) {
377 return absl::OutOfRangeError(absl::StrFormat(
378 "Overworld minimap palette %d out of bounds: offset %d, size %zu", i,
384 return absl::OkStatus();
407 {
"ow_main", 35}, {
"ow_aux", 21}, {
"ow_animated", 7},
408 {
"hud", 32}, {
"global_sprites", 60}, {
"armors", 15},
409 {
"swords", 3}, {
"shields", 4}, {
"sprites_aux1", 7},
410 {
"sprites_aux2", 7}, {
"sprites_aux3", 7}, {
"dungeon_main", 90},
411 {
"grass", 1}, {
"3d_object", 8}, {
"ow_mini_map", 128},
415 size_t color_index) {
423 uint32_t address = base_address + (palette_index * colors_per_palette * 2) +
456 int color_offset = 0;
457 std::vector<gfx::SnesColor> colors(num_colors);
459 while (color_offset < num_colors) {
466 uint16_t snes_color_word = (uint16_t)((rom[offset + 1]) << 8) | rom[offset];
470 new_color.
red = (snes_color_word & 0x1F) * 8;
471 new_color.
green = ((snes_color_word >> 5) & 0x1F) * 8;
472 new_color.
blue = ((snes_color_word >> 10) & 0x1F) * 8;
489 std::array<float, 4> colorArray;
490 colorArray[0] = color.
rgb().x / 255.0f;
491 colorArray[1] = color.
rgb().y / 255.0f;
492 colorArray[2] = color.
rgb().z / 255.0f;
493 colorArray[3] = color.
rgb().w;
498 std::vector<SnesColor>& palette_rows) {
500 for (
int i = 0; i < palette_rows.size(); i += 8) {
502 for (
int j = 0; j < 8; j++) {
503 palette.
AddColor(palette_rows[i + j]);
507 return palette_group;
528 for (
int i = 0; i < palette.
size(); i += num_colors) {
530 if (i + num_colors <= palette.
size()) {
531 for (
int j = 0; j < num_colors; j++) {
532 auto color = palette[i + j];
540 return palette_group;
543using namespace palette_group_internal;
563 return absl::OkStatus();
static std::unordered_map< uint8_t, gfx::Paletteset > palettesets_
constexpr ImVec4 rgb() const
Get RGB values (WARNING: stored as 0-255 in ImVec4)
void set_snes(uint16_t val)
Set color from SNES 15-bit format.
constexpr uint16_t snes() const
Get SNES 15-bit color.
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.
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.
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 int kCrystalPalette
const absl::flat_hash_map< std::string, uint32_t > kPaletteGroupAddressMap
uint16_t ConvertRgbToSnes(const snes_color &color)
Convert RGB (0-255) to SNES 15-bit color.
constexpr int kShieldPalettes
constexpr int kSpritesPalettesAux2
constexpr int kOverworldPaletteAnimated
SnesColor ReadColorFromRom(int offset, const uint8_t *rom)
constexpr int kOverworldMiniMapPalettes
constexpr int kOverworldPaletteMain
constexpr int kSwordPalettes
constexpr int kHardcodedGrassDW
constexpr int kGlobalSpritesLW
const absl::flat_hash_map< std::string, uint32_t > kPaletteGroupColorCounts
constexpr int kSpritesPalettesAux1
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)
SNES color in 15-bit RGB format (BGR555)
Represents a mapping of palette groups.
PaletteGroup overworld_main
PaletteGroup overworld_aux
PaletteGroup overworld_mini_map
PaletteGroup sprites_aux1
PaletteGroup sprites_aux2
PaletteGroup overworld_animated
PaletteGroup sprites_aux3
PaletteGroup dungeon_main
PaletteGroup global_sprites
Represents a group of palettes.
void AddColor(SnesColor color)
void AddPalette(SnesPalette pal)