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