yaze 0.2.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
snes_palette.cc
Go to the documentation of this file.
1#include "snes_palette.h"
2
3#include <SDL.h>
4
5#include <cstdint>
6#include <cstdlib>
7#include <cstring>
8#include <vector>
9
10#include "absl/container/flat_hash_map.h"
11#include "absl/status/status.h"
12#include "absl/status/statusor.h"
13#include "app/gfx/snes_color.h"
14#include "imgui/imgui.h"
15#include "util/macro.h"
16
17namespace yaze {
18namespace gfx {
19
21 assert((sizeof(data) % 4 == 0) && (sizeof(data) <= 32));
22 for (unsigned i = 0; i < sizeof(data); i += 2) {
23 SnesColor col;
24 col.set_snes(static_cast<uint8_t>(data[i + 1]) << 8);
25 col.set_snes(col.snes() | static_cast<uint8_t>(data[i]));
26 snes_color mColor = ConvertSnesToRgb(col.snes());
27 col.set_rgb(ImVec4(mColor.red, mColor.green, mColor.blue, 1.f));
28 colors_[size_++] = col;
29 }
30}
31
32SnesPalette::SnesPalette(const unsigned char *snes_pal) {
33 assert((sizeof(snes_pal) % 4 == 0) && (sizeof(snes_pal) <= 32));
34 for (unsigned i = 0; i < sizeof(snes_pal); i += 2) {
35 SnesColor col;
36 col.set_snes(snes_pal[i + 1] << (uint16_t)8);
37 col.set_snes(col.snes() | snes_pal[i]);
38 snes_color mColor = ConvertSnesToRgb(col.snes());
39 col.set_rgb(ImVec4(mColor.red, mColor.green, mColor.blue, 1.f));
40 colors_[size_++] = col;
41 }
42}
43
44SnesPalette::SnesPalette(const char *data, size_t length) : size_(0) {
45 for (size_t i = 0; i < length && size_ < kMaxColors; i += 2) {
46 uint16_t color = (static_cast<uint8_t>(data[i + 1]) << 8) |
47 static_cast<uint8_t>(data[i]);
48 colors_[size_++] = SnesColor(color);
49 }
50}
51
52SnesPalette::SnesPalette(const std::vector<uint16_t> &colors) : size_(0) {
53 for (const auto &color : colors) {
54 if (size_ < kMaxColors) {
55 colors_[size_++] = SnesColor(color);
56 }
57 }
58}
59
60SnesPalette::SnesPalette(const std::vector<SnesColor> &colors) : size_(0) {
61 for (const auto &color : colors) {
62 if (size_ < kMaxColors) {
63 colors_[size_++] = color;
64 }
65 }
66}
67
68SnesPalette::SnesPalette(const std::vector<ImVec4> &colors) : size_(0) {
69 for (const auto &color : colors) {
70 if (size_ < kMaxColors) {
71 colors_[size_++] = SnesColor(color);
72 }
73 }
74}
75
80namespace palette_group_internal {
81absl::Status LoadOverworldMainPalettes(const std::vector<uint8_t> &rom_data,
82 gfx::PaletteGroupMap &palette_groups) {
83 auto data = rom_data.data();
84 for (int i = 0; i < 6; i++) {
85 palette_groups.overworld_main.AddPalette(
87 /*num_colors=*/35, data));
88 }
89 return absl::OkStatus();
90}
91
93 const std::vector<uint8_t> &rom_data,
94 gfx::PaletteGroupMap &palette_groups) {
95 auto data = rom_data.data();
96 for (int i = 0; i < 20; i++) {
97 palette_groups.overworld_aux.AddPalette(
99 /*num_colors=*/21, data));
100 }
101 return absl::OkStatus();
102}
103
105 const std::vector<uint8_t> &rom_data,
106 gfx::PaletteGroupMap &palette_groups) {
107 auto data = rom_data.data();
108 for (int i = 0; i < 14; i++) {
110 kOverworldPaletteAnimated + (i * (7 * 2)), /*num_colors=*/7, data));
111 }
112 return absl::OkStatus();
113}
114
115absl::Status LoadHUDPalettes(const std::vector<uint8_t> &rom_data,
116 gfx::PaletteGroupMap &palette_groups) {
117 auto data = rom_data.data();
118 for (int i = 0; i < 2; i++) {
120 kHudPalettes + (i * 64), /*num_colors=*/32, data));
121 }
122 return absl::OkStatus();
123}
124
125absl::Status LoadGlobalSpritePalettes(const std::vector<uint8_t> &rom_data,
126 gfx::PaletteGroupMap &palette_groups) {
127 auto data = rom_data.data();
128 palette_groups.global_sprites.AddPalette(
129 gfx::ReadPaletteFromRom(kGlobalSpritesLW, /*num_colors=*/60, data));
131 kGlobalSpritePalettesDW, /*num_colors=*/60, data));
132 return absl::OkStatus();
133}
134
135absl::Status LoadArmorPalettes(const std::vector<uint8_t> &rom_data,
136 gfx::PaletteGroupMap &palette_groups) {
137 auto data = rom_data.data();
138 for (int i = 0; i < 5; i++) {
140 kArmorPalettes + (i * 30), /*num_colors=*/15, data));
141 }
142 return absl::OkStatus();
143}
144
145absl::Status LoadSwordPalettes(const std::vector<uint8_t> &rom_data,
146 gfx::PaletteGroupMap &palette_groups) {
147 auto data = rom_data.data();
148 for (int i = 0; i < 4; i++) {
150 kSwordPalettes + (i * 6), /*num_colors=*/3, data));
151 }
152 return absl::OkStatus();
153}
154
155absl::Status LoadShieldPalettes(const std::vector<uint8_t> &rom_data,
156 gfx::PaletteGroupMap &palette_groups) {
157 auto data = rom_data.data();
158 for (int i = 0; i < 3; i++) {
160 kShieldPalettes + (i * 8), /*num_colors=*/4, data));
161 }
162 return absl::OkStatus();
163}
164
165absl::Status LoadSpriteAux1Palettes(const std::vector<uint8_t> &rom_data,
166 gfx::PaletteGroupMap &palette_groups) {
167 auto data = rom_data.data();
168 for (int i = 0; i < 12; i++) {
170 kSpritesPalettesAux1 + (i * 14), /*num_colors=*/7, data));
171 }
172 return absl::OkStatus();
173}
174
175absl::Status LoadSpriteAux2Palettes(const std::vector<uint8_t> &rom_data,
176 gfx::PaletteGroupMap &palette_groups) {
177 auto data = rom_data.data();
178 for (int i = 0; i < 11; i++) {
180 kSpritesPalettesAux2 + (i * 14), /*num_colors=*/7, data));
181 }
182 return absl::OkStatus();
183}
184
185absl::Status LoadSpriteAux3Palettes(const std::vector<uint8_t> &rom_data,
186 gfx::PaletteGroupMap &palette_groups) {
187 auto data = rom_data.data();
188 for (int i = 0; i < 24; i++) {
190 kSpritesPalettesAux3 + (i * 14), /*num_colors=*/7, data));
191 }
192 return absl::OkStatus();
193}
194
195absl::Status LoadDungeonMainPalettes(const std::vector<uint8_t> &rom_data,
196 gfx::PaletteGroupMap &palette_groups) {
197 auto data = rom_data.data();
198 for (int i = 0; i < 20; i++) {
200 kDungeonMainPalettes + (i * 180), /*num_colors=*/90, data));
201 }
202 return absl::OkStatus();
203}
204
205absl::Status LoadGrassColors(const std::vector<uint8_t> &rom_data,
206 gfx::PaletteGroupMap &palette_groups) {
207 palette_groups.grass.AddColor(
208 gfx::ReadColorFromRom(kHardcodedGrassLW, rom_data.data()));
209 palette_groups.grass.AddColor(
210 gfx::ReadColorFromRom(kHardcodedGrassDW, rom_data.data()));
211 palette_groups.grass.AddColor(
213 return absl::OkStatus();
214}
215
216absl::Status Load3DObjectPalettes(const std::vector<uint8_t> &rom_data,
217 gfx::PaletteGroupMap &palette_groups) {
218 auto data = rom_data.data();
219 palette_groups.object_3d.AddPalette(
221 palette_groups.object_3d.AddPalette(
223 return absl::OkStatus();
224}
225
227 const std::vector<uint8_t> &rom_data,
228 gfx::PaletteGroupMap &palette_groups) {
229 auto data = rom_data.data();
230 for (int i = 0; i < 2; i++) {
232 kOverworldMiniMapPalettes + (i * 256), /*num_colors=*/128, data));
233 }
234 return absl::OkStatus();
235}
236} // namespace palette_group_internal
237
238const absl::flat_hash_map<std::string, uint32_t> kPaletteGroupAddressMap = {
239 {"ow_main", kOverworldPaletteMain},
240 {"ow_aux", kOverworldPaletteAux},
241 {"ow_animated", kOverworldPaletteAnimated},
242 {"hud", kHudPalettes},
243 {"global_sprites", kGlobalSpritesLW},
244 {"armors", kArmorPalettes},
245 {"swords", kSwordPalettes},
246 {"shields", kShieldPalettes},
247 {"sprites_aux1", kSpritesPalettesAux1},
248 {"sprites_aux2", kSpritesPalettesAux2},
249 {"sprites_aux3", kSpritesPalettesAux3},
250 {"dungeon_main", kDungeonMainPalettes},
251 {"grass", kHardcodedGrassLW},
252 {"3d_object", kTriforcePalette},
253 {"ow_mini_map", kOverworldMiniMapPalettes},
254};
255
256const absl::flat_hash_map<std::string, uint32_t> kPaletteGroupColorCounts = {
257 {"ow_main", 35}, {"ow_aux", 21}, {"ow_animated", 7},
258 {"hud", 32}, {"global_sprites", 60}, {"armors", 15},
259 {"swords", 3}, {"shields", 4}, {"sprites_aux1", 7},
260 {"sprites_aux2", 7}, {"sprites_aux3", 7}, {"dungeon_main", 90},
261 {"grass", 1}, {"3d_object", 8}, {"ow_mini_map", 128},
262};
263
264uint32_t GetPaletteAddress(const std::string &group_name, size_t palette_index,
265 size_t color_index) {
266 // Retrieve the base address for the palette group
267 uint32_t base_address = kPaletteGroupAddressMap.at(group_name);
268
269 // Retrieve the number of colors for each palette in the group
270 uint32_t colors_per_palette = kPaletteGroupColorCounts.at(group_name);
271
272 // Calculate the address for thes specified color in the ROM
273 uint32_t address = base_address + (palette_index * colors_per_palette * 2) +
274 (color_index * 2);
275
276 return address;
277}
278
279SnesPalette ReadPaletteFromRom(int offset, int num_colors, const uint8_t *rom) {
280 int color_offset = 0;
281 std::vector<gfx::SnesColor> colors(num_colors);
282
283 while (color_offset < num_colors) {
284 short color = (uint16_t)((rom[offset + 1]) << 8) | rom[offset];
285 snes_color new_color;
286 new_color.red = (color & 0x1F) * 8;
287 new_color.green = ((color >> 5) & 0x1F) * 8;
288 new_color.blue = ((color >> 10) & 0x1F) * 8;
289 colors[color_offset].set_snes(ConvertRgbToSnes(new_color));
290 if (color_offset == 0) {
291 colors[color_offset].set_transparent(true);
292 }
293 color_offset++;
294 offset += 2;
295 }
296
297 return gfx::SnesPalette(colors);
298}
299
300std::array<float, 4> ToFloatArray(const SnesColor &color) {
301 std::array<float, 4> colorArray;
302 colorArray[0] = color.rgb().x / 255.0f;
303 colorArray[1] = color.rgb().y / 255.0f;
304 colorArray[2] = color.rgb().z / 255.0f;
305 colorArray[3] = color.rgb().w;
306 return colorArray;
307}
308
309absl::StatusOr<PaletteGroup> CreatePaletteGroupFromColFile(
310 std::vector<SnesColor> &palette_rows) {
311 PaletteGroup palette_group;
312 for (int i = 0; i < palette_rows.size(); i += 8) {
313 SnesPalette palette;
314 for (int j = 0; j < 8; j++) {
315 palette.AddColor(palette_rows[i + j]);
316 }
317 palette_group.AddPalette(palette);
318 }
319 return palette_group;
320}
321
322absl::StatusOr<PaletteGroup> CreatePaletteGroupFromLargePalette(
323 SnesPalette &palette, int num_colors) {
324 PaletteGroup palette_group;
325 for (int i = 0; i < palette.size(); i += num_colors) {
326 SnesPalette new_palette;
327 if (i + num_colors < palette.size()) {
328 for (int j = 0; j < num_colors; j++) {
329 new_palette.AddColor(palette[i + j]);
330 }
331 }
332 palette_group.AddPalette(new_palette);
333 }
334 return palette_group;
335}
336
337using namespace palette_group_internal;
338
339// TODO: Refactor LoadAllPalettes to use group names, move to zelda3 namespace
340absl::Status LoadAllPalettes(const std::vector<uint8_t> &rom_data,
341 PaletteGroupMap &groups) {
345 RETURN_IF_ERROR(LoadHUDPalettes(rom_data, groups))
347 RETURN_IF_ERROR(LoadArmorPalettes(rom_data, groups))
348 RETURN_IF_ERROR(LoadSwordPalettes(rom_data, groups))
349 RETURN_IF_ERROR(LoadShieldPalettes(rom_data, groups))
350 RETURN_IF_ERROR(LoadSpriteAux1Palettes(rom_data, groups))
351 RETURN_IF_ERROR(LoadSpriteAux2Palettes(rom_data, groups))
352 RETURN_IF_ERROR(LoadSpriteAux3Palettes(rom_data, groups))
354 RETURN_IF_ERROR(LoadGrassColors(rom_data, groups))
355 RETURN_IF_ERROR(Load3DObjectPalettes(rom_data, groups))
357 return absl::OkStatus();
358}
359
360std::unordered_map<uint8_t, gfx::Paletteset> GfxContext::palettesets_;
361
362} // namespace gfx
363} // namespace yaze
static std::unordered_map< uint8_t, gfx::Paletteset > palettesets_
SNES Color container.
Definition snes_color.h:38
constexpr ImVec4 rgb() const
Definition snes_color.h:74
void set_snes(uint16_t val)
constexpr uint16_t snes() const
Definition snes_color.h:76
void set_rgb(const ImVec4 val)
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
void AddColor(const SnesColor &color)
static constexpr size_t kMaxColors
#define RETURN_IF_ERROR(expression)
Definition macro.h:51
Internal functions for loading palettes by group.
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 bitmap.cc:18
constexpr int kHardcodedGrassSpecial
constexpr int kHudPalettes
constexpr int kOverworldPaletteAux
SnesPalette ReadPaletteFromRom(int offset, int num_colors, const uint8_t *rom)
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)
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
snes_color ConvertSnesToRgb(uint16_t color_snes)
Definition snes_color.cc:19
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 > CreatePaletteGroupFromLargePalette(SnesPalette &palette, int num_colors)
Take a SNESPalette, divide it into palettes of 8 colors.
absl::StatusOr< PaletteGroup > CreatePaletteGroupFromColFile(std::vector< SnesColor > &palette_rows)
Main namespace for the application.
Definition controller.cc:18
Primitive of 16-bit RGB SNES color.
Definition snes.h:14
uint16_t green
Definition snes.h:17
uint16_t red
Definition snes.h:15
uint16_t blue
Definition snes.h:16
Represents a mapping of palette groups.
Represents a group of palettes.
void AddColor(SnesColor color)
void AddPalette(SnesPalette pal)