yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
snes_palette.h
Go to the documentation of this file.
1#ifndef YAZE_APP_GFX_PALETTE_H
2#define YAZE_APP_GFX_PALETTE_H
3
4#include <array>
5#include <cstdint>
6#include <cstdlib>
7#include <cstring>
8#include <iostream>
9#include <string>
10#include <vector>
11
12#include "absl/status/status.h"
13#include "absl/status/statusor.h"
15#include "imgui/imgui.h"
16#include "snes_color.h"
17#include "util/macro.h"
18
19namespace yaze {
20namespace gfx {
21
22constexpr int kNumPalettes = 14;
23
40
41static constexpr absl::string_view kPaletteCategoryNames[] = {
42 "Sword", "Shield", "Clothes", "World Colors",
43 "Area Colors", "Global Sprites", "Sprites Aux1", "Sprites Aux2",
44 "Sprites Aux3", "Dungeons", "World Map", "Dungeon Map",
45 "Triforce", "Crystal"};
46
47static constexpr absl::string_view kPaletteGroupNames[] = {
48 "swords", "shields", "armors", "ow_main",
49 "ow_aux", "global_sprites", "sprites_aux1", "sprites_aux2",
50 "sprites_aux3", "dungeon_main", "ow_mini_map", "ow_mini_map",
51 "3d_object", "3d_object"};
52
53constexpr const char* kPaletteGroupAddressesKeys[] = {
54 "ow_main", "ow_aux", "ow_animated", "hud",
55 "global_sprites", "armors", "swords", "shields",
56 "sprites_aux1", "sprites_aux2", "sprites_aux3", "dungeon_main",
57 "grass", "3d_object", "ow_mini_map",
58};
59
60constexpr int kOverworldPaletteMain = 0xDE6C8;
61constexpr int kOverworldPaletteAux = 0xDE86C;
62constexpr int kOverworldPaletteAnimated = 0xDE604;
63constexpr int kGlobalSpritesLW = 0xDD218;
64constexpr int kGlobalSpritePalettesDW = 0xDD290;
65
67constexpr int kArmorPalettes = 0xDD308;
68constexpr int kSpritesPalettesAux1 = 0xDD39E; // 7 colors each
69constexpr int kSpritesPalettesAux2 = 0xDD446; // 7 colors each
70constexpr int kSpritesPalettesAux3 = 0xDD4E0; // 7 colors each
71constexpr int kSwordPalettes = 0xDD630; // 3 colors each - 4 entries
72constexpr int kShieldPalettes = 0xDD648; // 4 colors each - 3 entries
73constexpr int kHudPalettes = 0xDD660;
74constexpr int kDungeonMapPalettes = 0xDD70A; // 21 colors
75
76// (15*6) colors each - 20 entries
77constexpr int kDungeonMainPalettes = 0xDD734;
78constexpr int kDungeonMapBgPalettes = 0xDE544; // 16*6
79
80// Mirrored Value at 0x75645 : 0x75625
81constexpr int kHardcodedGrassLW = 0x5FEA9;
82constexpr int kHardcodedGrassDW = 0x05FEB3; // 0x7564F
83constexpr int kHardcodedGrassSpecial = 0x75640;
84constexpr int kOverworldMiniMapPalettes = 0x55B27;
85constexpr int kTriforcePalette = 0x64425;
86constexpr int kCrystalPalette = 0xF4CD3;
87
89constexpr int CustomAreaSpecificBGPalette = 0x140000;
90constexpr int CustomAreaSpecificBGASM = 0x140150;
91
92// 1 byte, not 0 if enabled
93constexpr int kCustomAreaSpecificBGEnabled = 0x140140;
94
95constexpr int HudPalettesMax = 2;
96constexpr int OverworldMainPalettesMax = 6;
97constexpr int OverworldAuxPalettesMax = 20;
99constexpr int GlobalSpritePalettesMax = 2;
100constexpr int ArmorPalettesMax = 5;
101constexpr int SwordsPalettesMax = 4;
102constexpr int SpritesAux1PalettesMax = 12;
103constexpr int SpritesAux2PalettesMax = 11;
104constexpr int SpritesAux3PalettesMax = 24;
105constexpr int ShieldsPalettesMax = 3;
106constexpr int DungeonsMainPalettesMax = 20;
109constexpr int Object3DPalettesMax = 2;
111
112uint32_t GetPaletteAddress(const std::string& group_name, size_t palette_index,
113 size_t color_index);
114
128 public:
129 static constexpr size_t kMaxColors = 256;
130 using ColorArray = std::array<SnesColor, kMaxColors>;
131
133 SnesPalette(char* data);
134 SnesPalette(const unsigned char* snes_pal);
135 SnesPalette(const char* data, size_t length);
136 SnesPalette(const std::vector<uint16_t>& colors);
137 SnesPalette(const std::vector<SnesColor>& colors);
138 SnesPalette(const std::vector<ImVec4>& colors);
139
140 const SnesColor& operator[](size_t index) const { return colors_[index]; }
141 SnesColor& operator[](size_t index) { return colors_[index]; }
142
143 void set_size(size_t size) { size_ = size; }
144 size_t size() const { return size_; }
145 bool empty() const { return size_ == 0; }
146
147 // Resize
148 void Resize(size_t size) { size_ = size; }
149
150 auto begin() { return colors_.begin(); }
151 auto end() { return colors_.begin() + size_; }
152 auto begin() const { return colors_.begin(); }
153 auto end() const { return colors_.begin() + size_; }
154
155 void AddColor(const SnesColor& color) {
156 if (size_ < kMaxColors) {
157 colors_[size_++] = color;
158 }
159 }
160
161 void UpdateColor(size_t index, const SnesColor& color) {
162 if (index < size_) {
163 colors_[index] = color;
164 }
165 }
166
167 void clear() { size_ = 0; }
168
169 SnesPalette sub_palette(size_t start, size_t length) const {
170 SnesPalette result;
171 if (start >= size_) {
172 return result;
173 }
174 length = std::min(length, size_ - start);
175 for (size_t i = 0; i < length; ++i) {
176 result.AddColor(colors_[start + i]);
177 }
178 return result;
179 }
180
181 bool operator==(const SnesPalette& other) const {
182 if (size_ != other.size_) {
183 return false;
184 }
185 for (size_t i = 0; i < size_; ++i) {
186 if (colors_[i].snes() != other.colors_[i].snes()) {
187 return false;
188 }
189 }
190 return true;
191 }
192
193 bool operator!=(const SnesPalette& other) const { return !(*this == other); }
194
195 private:
197 size_t size_;
198};
199
200SnesPalette ReadPaletteFromRom(int offset, int num_colors, const uint8_t* rom);
201
202std::array<float, 4> ToFloatArray(const SnesColor& color);
203
211 PaletteGroup() = default;
212 PaletteGroup(const std::string& name) : name_(name) {}
213
214 // ========== Basic Operations ==========
215
216 void AddPalette(SnesPalette pal) { palettes.emplace_back(pal); }
217
218 void AddColor(SnesColor color) {
219 if (palettes.empty()) {
220 palettes.emplace_back();
221 }
222 palettes[0].AddColor(color);
223 }
224
225 void clear() { palettes.clear(); }
226 void resize(size_t new_size) { palettes.resize(new_size); }
227
228 // ========== Accessors ==========
229
230 auto name() const { return name_; }
231 auto size() const { return palettes.size(); }
232 bool empty() const { return palettes.empty(); }
233
234 // Const access
235 auto palette(int i) const { return palettes[i]; }
236 const SnesPalette& palette_ref(int i) const { return palettes[i]; }
237
238 // Mutable access
239 auto mutable_palette(int i) { return &palettes[i]; }
240 SnesPalette& palette_ref(int i) { return palettes[i]; }
241
242 // ========== Color Operations ==========
243
250 SnesColor GetColor(int palette_index, int color_index) const {
251 if (palette_index >= 0 && palette_index < palettes.size()) {
252 const auto& pal = palettes[palette_index];
253 if (color_index >= 0 && color_index < pal.size()) {
254 return pal[color_index];
255 }
256 }
257 return SnesColor();
258 }
259
267 bool SetColor(int palette_index, int color_index, const SnesColor& color) {
268 if (palette_index >= 0 && palette_index < palettes.size()) {
269 auto& pal = palettes[palette_index];
270 if (color_index >= 0 && color_index < pal.size()) {
271 pal[color_index] = color;
272 return true;
273 }
274 }
275 return false;
276 }
277
278 // ========== Operator Overloads ==========
279
281 if (i < 0 || i >= static_cast<int>(palettes.size())) {
282 std::cout << "PaletteGroup: Index " << i
283 << " out of bounds (size: " << palettes.size() << ")"
284 << std::endl;
285 return SnesPalette();
286 }
287 return palettes[i];
288 }
289
290 const SnesPalette& operator[](int i) const {
291 if (i < 0 || i >= static_cast<int>(palettes.size())) {
292 std::cout << "PaletteGroup: Index " << i
293 << " out of bounds (size: " << palettes.size() << ")"
294 << std::endl;
295 static const SnesPalette empty_palette;
296 return empty_palette;
297 }
298 return palettes[i];
299 }
300
301 private:
302 std::string name_;
303 std::vector<SnesPalette> palettes;
304};
305
314 PaletteGroup overworld_main = {kPaletteGroupAddressesKeys[0]};
315 PaletteGroup overworld_aux = {kPaletteGroupAddressesKeys[1]};
316 PaletteGroup overworld_animated = {kPaletteGroupAddressesKeys[2]};
317 PaletteGroup hud = {kPaletteGroupAddressesKeys[3]};
318 PaletteGroup global_sprites = {kPaletteGroupAddressesKeys[4]};
319 PaletteGroup armors = {kPaletteGroupAddressesKeys[5]};
320 PaletteGroup swords = {kPaletteGroupAddressesKeys[6]};
321 PaletteGroup shields = {kPaletteGroupAddressesKeys[7]};
322 PaletteGroup sprites_aux1 = {kPaletteGroupAddressesKeys[8]};
323 PaletteGroup sprites_aux2 = {kPaletteGroupAddressesKeys[9]};
324 PaletteGroup sprites_aux3 = {kPaletteGroupAddressesKeys[10]};
325 PaletteGroup dungeon_main = {kPaletteGroupAddressesKeys[11]};
326 PaletteGroup grass = {kPaletteGroupAddressesKeys[12]};
327 PaletteGroup object_3d = {kPaletteGroupAddressesKeys[13]};
328 PaletteGroup overworld_mini_map = {kPaletteGroupAddressesKeys[14]};
329
330 PaletteGroup* get_group(const std::string& group_name) {
331 if (group_name == "ow_main") {
332 return &overworld_main;
333 } else if (group_name == "ow_aux") {
334 return &overworld_aux;
335 } else if (group_name == "ow_animated") {
336 return &overworld_animated;
337 } else if (group_name == "hud") {
338 return &hud;
339 } else if (group_name == "global_sprites") {
340 return &global_sprites;
341 } else if (group_name == "armors") {
342 return &armors;
343 } else if (group_name == "swords") {
344 return &swords;
345 } else if (group_name == "shields") {
346 return &shields;
347 } else if (group_name == "sprites_aux1") {
348 return &sprites_aux1;
349 } else if (group_name == "sprites_aux2") {
350 return &sprites_aux2;
351 } else if (group_name == "sprites_aux3") {
352 return &sprites_aux3;
353 } else if (group_name == "dungeon_main") {
354 return &dungeon_main;
355 } else if (group_name == "grass") {
356 return &grass;
357 } else if (group_name == "3d_object") {
358 return &object_3d;
359 } else if (group_name == "ow_mini_map") {
360 return &overworld_mini_map;
361 } else {
362 return nullptr;
363 }
364 }
365
366 const PaletteGroup* get_group(const std::string& group_name) const {
367 if (group_name == "ow_main") {
368 return &overworld_main;
369 } else if (group_name == "ow_aux") {
370 return &overworld_aux;
371 } else if (group_name == "ow_animated") {
372 return &overworld_animated;
373 } else if (group_name == "hud") {
374 return &hud;
375 } else if (group_name == "global_sprites") {
376 return &global_sprites;
377 } else if (group_name == "armors") {
378 return &armors;
379 } else if (group_name == "swords") {
380 return &swords;
381 } else if (group_name == "shields") {
382 return &shields;
383 } else if (group_name == "sprites_aux1") {
384 return &sprites_aux1;
385 } else if (group_name == "sprites_aux2") {
386 return &sprites_aux2;
387 } else if (group_name == "sprites_aux3") {
388 return &sprites_aux3;
389 } else if (group_name == "dungeon_main") {
390 return &dungeon_main;
391 } else if (group_name == "grass") {
392 return &grass;
393 } else if (group_name == "3d_object") {
394 return &object_3d;
395 } else if (group_name == "ow_mini_map") {
396 return &overworld_mini_map;
397 } else {
398 return nullptr;
399 }
400 }
401
402 template <typename Func>
403 absl::Status for_each(Func&& func) {
406 RETURN_IF_ERROR(func(hud));
408 RETURN_IF_ERROR(func(armors));
409 RETURN_IF_ERROR(func(swords));
415 RETURN_IF_ERROR(func(grass));
418 return absl::OkStatus();
419 }
420
438
439 bool empty() const {
440 return overworld_main.size() == 0 && overworld_aux.size() == 0 &&
441 overworld_animated.size() == 0 && hud.size() == 0 &&
442 global_sprites.size() == 0 && armors.size() == 0 &&
443 swords.size() == 0 && shields.size() == 0 &&
444 sprites_aux1.size() == 0 && sprites_aux2.size() == 0 &&
445 sprites_aux3.size() == 0 && dungeon_main.size() == 0 &&
446 grass.size() == 0 && object_3d.size() == 0 &&
448 }
449};
450
451absl::StatusOr<PaletteGroup> CreatePaletteGroupFromColFile(
452 std::vector<SnesColor>& colors);
453
457absl::StatusOr<PaletteGroup> CreatePaletteGroupFromLargePalette(
458 SnesPalette& palette, int num_colors = 8);
459
469absl::Status LoadAllPalettes(const std::vector<uint8_t>& rom_data,
470 PaletteGroupMap& groups);
471
518
523 protected:
524 // Palettesets for the tile16 individual tiles
525 static std::unordered_map<uint8_t, gfx::Paletteset> palettesets_;
526};
527
528} // namespace gfx
529} // namespace yaze
530
531#endif // YAZE_APP_GFX_PALETTE_H
Shared graphical context across editors.
static std::unordered_map< uint8_t, gfx::Paletteset > palettesets_
SNES Color container.
Definition snes_color.h:110
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
void Resize(size_t size)
void AddColor(const SnesColor &color)
static constexpr size_t kMaxColors
std::array< SnesColor, kMaxColors > ColorArray
SnesPalette sub_palette(size_t start, size_t length) const
void set_size(size_t size)
SnesColor & operator[](size_t index)
bool operator!=(const SnesPalette &other) const
void UpdateColor(size_t index, const SnesColor &color)
const SnesColor & operator[](size_t index) const
bool operator==(const SnesPalette &other) const
int main(int argc, char **argv)
Definition emu.cc:39
constexpr int kHardcodedGrassSpecial
constexpr int kHudPalettes
constexpr int kOverworldPaletteAux
constexpr int Object3DPalettesMax
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
constexpr int HudPalettesMax
constexpr int OverworldAnimatedPalettesMax
constexpr int SpritesAux3PalettesMax
constexpr int SpritesAux1PalettesMax
constexpr int DungeonsMainPalettesMax
constexpr int OverworldGrassPalettesMax
constexpr int OverworldMiniMapPalettesMax
constexpr int SpritesAux2PalettesMax
constexpr int kShieldPalettes
constexpr int kSpritesPalettesAux2
constexpr int kOverworldPaletteAnimated
constexpr int CustomAreaSpecificBGPalette
constexpr int kOverworldMiniMapPalettes
constexpr int kOverworldPaletteMain
constexpr int kDungeonMapPalettes
constexpr int kSwordPalettes
constexpr int kHardcodedGrassDW
constexpr int ShieldsPalettesMax
constexpr int ArmorPalettesMax
constexpr int kGlobalSpritesLW
constexpr int kSpritesPalettesAux1
constexpr int OverworldAuxPalettesMax
std::array< float, 4 > ToFloatArray(const SnesColor &color)
constexpr int kNumPalettes
constexpr int kCustomAreaSpecificBGEnabled
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 kDungeonMapBgPalettes
constexpr int kTriforcePalette
absl::Status LoadAllPalettes(const std::vector< uint8_t > &rom_data, PaletteGroupMap &groups)
Loads all the palettes for the game.
constexpr int SwordsPalettesMax
constexpr int OverworldBackgroundPaletteMax
constexpr int CustomAreaSpecificBGASM
constexpr int OverworldMainPalettesMax
absl::StatusOr< PaletteGroup > CreatePaletteGroupFromColFile(std::vector< SnesColor > &palette_rows)
constexpr int GlobalSpritePalettesMax
#define RETURN_IF_ERROR(expr)
Definition snes.cc:22
Represents a mapping of palette groups.
absl::Status for_each(Func &&func)
const PaletteGroup * get_group(const std::string &group_name) const
PaletteGroup * get_group(const std::string &group_name)
Represents a group of palettes.
std::vector< SnesPalette > palettes
bool SetColor(int palette_index, int color_index, const SnesColor &color)
Set a specific color in a palette.
auto palette(int i) const
SnesPalette & palette_ref(int i)
void AddColor(SnesColor color)
void resize(size_t new_size)
const SnesPalette & palette_ref(int i) const
const SnesPalette & operator[](int i) const
SnesColor GetColor(int palette_index, int color_index) const
Get a specific color from a palette.
SnesPalette operator[](int i)
void AddPalette(SnesPalette pal)
PaletteGroup(const std::string &name)
Represents a set of palettes used in a SNES graphics system.
gfx::SnesPalette spr
gfx::SnesPalette main_
Paletteset(const gfx::SnesPalette &main, const gfx::SnesPalette &animated, const gfx::SnesPalette &aux1, const gfx::SnesPalette &aux2, const gfx::SnesColor &background, const gfx::SnesPalette &hud, const gfx::SnesPalette &spr, const gfx::SnesPalette &spr2, const gfx::SnesPalette &comp)
Constructor for Paletteset.
gfx::SnesPalette animated
gfx::SnesPalette composite
gfx::SnesPalette hud
gfx::SnesPalette aux1
gfx::SnesPalette spr2
gfx::SnesColor background
gfx::SnesPalette aux2
Paletteset()=default
Default constructor for Paletteset.