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