From 8cc9adf41ab486fcb23c27b0ca203de8185dc5d3 Mon Sep 17 00:00:00 2001 From: Justin Scofield <47263509+scawful@users.noreply.github.com> Date: Sat, 10 Sep 2022 09:51:40 -0500 Subject: [PATCH] palette stuff --- src/app/core/constants.h | 8 + src/app/editor/overworld_editor.cc | 2 + src/app/gfx/bitmap.cc | 5 +- src/app/gfx/bitmap.h | 3 +- src/app/gfx/snes_palette.cc | 25 +- src/app/gfx/snes_palette.h | 28 +++ src/app/rom.cc | 98 +++++++- src/app/rom.h | 4 +- src/app/zelda3/overworld.h | 3 + src/app/zelda3/overworld_map.cc | 388 ++++++++++++++++++++--------- src/app/zelda3/overworld_map.h | 11 +- src/app/zelda3/palettes.h | 45 ++++ 12 files changed, 495 insertions(+), 125 deletions(-) create mode 100644 src/app/zelda3/palettes.h diff --git a/src/app/core/constants.h b/src/app/core/constants.h index 888aa682..5a55c95d 100644 --- a/src/app/core/constants.h +++ b/src/app/core/constants.h @@ -466,6 +466,14 @@ constexpr int dungeonMapBgPalettes = 0xDE544; // 16*6 constexpr int hardcodedGrassLW = 0x5FEA9; constexpr int hardcodedGrassDW = 0x05FEB3; // 0x7564F constexpr int hardcodedGrassSpecial = 0x75640; +constexpr int overworldMiniMapPalettes = 0x55B27; +constexpr int triforcePalette = 0x64425; +constexpr int crystalPalette = 0xF4CD3; +constexpr int customAreaSpecificBGPalette = + 0x140000; // 2 bytes for each overworld area (320) +constexpr int customAreaSpecificBGASM = 0x140150; +constexpr int customAreaSpecificBGEnabled = + 0x140140; // 1 byte, not 0 if enabled // ============================================================================ // Dungeon Map Related Variables diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index e359d6e9..94f4852e 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -53,7 +53,9 @@ absl::Status OverworldEditor::Update() { for (int i = 0; i < core::kNumOverworldMaps; ++i) { overworld_.SetCurrentMap(i); + auto palette = overworld_.GetCurrentPalette(); maps_bmp_[i].Create(512, 512, 512, overworld_.GetCurrentBitmapData()); + maps_bmp_[i].ApplyPalette(palette); rom_.RenderBitmap(&(maps_bmp_[i])); } } diff --git a/src/app/gfx/bitmap.cc b/src/app/gfx/bitmap.cc index db385954..e23c02eb 100644 --- a/src/app/gfx/bitmap.cc +++ b/src/app/gfx/bitmap.cc @@ -103,8 +103,9 @@ void Bitmap::CreateTexture(std::shared_ptr renderer) { } // Convert SNESPalette to SDL_Palette for surface. -void Bitmap::ApplyPalette(SNESPalette &palette) { - surface_->format->palette = palette.GetSDL_Palette(); +void Bitmap::ApplyPalette(SNESPalette palette) { + palette_ = palette; + surface_->format->palette = palette_.GetSDL_Palette(); } void Bitmap::SetPaletteColor(int id, gfx::snes_color color) { diff --git a/src/app/gfx/bitmap.h b/src/app/gfx/bitmap.h index 5ca40a6c..4448b74f 100644 --- a/src/app/gfx/bitmap.h +++ b/src/app/gfx/bitmap.h @@ -30,7 +30,7 @@ class Bitmap { void CreateTexture(std::shared_ptr renderer); - void ApplyPalette(SNESPalette &palette); + void ApplyPalette(SNESPalette palette); void SetPaletteColor(int id, gfx::snes_color color); absl::StatusOr> CreateTiles(); @@ -72,6 +72,7 @@ class Bitmap { bool freed_ = false; uchar *pixel_data_; Bytes data_; + gfx::SNESPalette palette_; std::shared_ptr texture_ = nullptr; std::shared_ptr surface_ = nullptr; }; diff --git a/src/app/gfx/snes_palette.cc b/src/app/gfx/snes_palette.cc index 625e1918..64ac407e 100644 --- a/src/app/gfx/snes_palette.cc +++ b/src/app/gfx/snes_palette.cc @@ -64,6 +64,8 @@ char* Convert(const snes_palette pal) { SNESColor::SNESColor() : rgb(ImVec4(0.f, 0.f, 0.f, 0.f)) {} +SNESColor::SNESColor(snes_color val) { snes = ConvertRGBtoSNES(val); } + SNESColor::SNESColor(ImVec4 val) : rgb(val) { snes_color col; col.red = (uchar)val.x; @@ -81,9 +83,7 @@ void SNESColor::setRgb(ImVec4 val) { snes = ConvertRGBtoSNES(col); } -void SNESColor::setRgb(snes_color val) { - snes = ConvertRGBtoSNES(val); -} +void SNESColor::setRgb(snes_color val) { snes = ConvertRGBtoSNES(val); } void SNESColor::setSNES(uint16_t val) { snes = val; @@ -143,6 +143,20 @@ SNESPalette::SNESPalette(const std::vector& cols) { size_ = cols.size(); } +SNESPalette::SNESPalette(const std::vector& cols) { + for (const auto& each : cols) { + colors.push_back(each); + } + size_ = cols.size(); +} + +void SNESPalette::Create(const std::vector& cols) { + for (const auto& each : cols) { + colors.push_back(each); + } + size_ = cols.size(); +} + char* SNESPalette::encode() { auto data = new char[size_ * 2]; for (unsigned int i = 0; i < size_; i++) { @@ -169,6 +183,11 @@ SDL_Palette* SNESPalette::GetSDL_Palette() { return sdl_palette.get(); } +PaletteGroup::PaletteGroup(uint8_t mSize) { + size = mSize; + palettes.reserve(size); +} + } // namespace gfx } // namespace app } // namespace yaze \ No newline at end of file diff --git a/src/app/gfx/snes_palette.h b/src/app/gfx/snes_palette.h index bd0cdf71..8bd4332b 100644 --- a/src/app/gfx/snes_palette.h +++ b/src/app/gfx/snes_palette.h @@ -40,6 +40,7 @@ char* Convert(const snes_palette pal); struct SNESColor { SNESColor(); explicit SNESColor(ImVec4); + explicit SNESColor(snes_color); uint16_t snes = 0; ImVec4 rgb; void setRgb(ImVec4); @@ -55,6 +56,19 @@ class SNESPalette { explicit SNESPalette(const unsigned char* snes_pal); explicit SNESPalette(const std::vector&); explicit SNESPalette(const std::vector&); + explicit SNESPalette(const std::vector&); + + void Create(const std::vector&); + + auto GetColor(int i) const { return colors[i]; } + + SNESColor operator[](int i) { + if (i > size_) { + std::cout << "SNESPalette: Index out of bounds" << std::endl; + return colors[0]; + } + return colors[i]; + } char* encode(); SDL_Palette* GetSDL_Palette(); @@ -63,6 +77,20 @@ class SNESPalette { std::vector colors; }; +struct PaletteGroup { + PaletteGroup() = default; + explicit PaletteGroup(uint8_t mSize); + SNESPalette operator[](int i) { + if (i > size) { + std::cout << "PaletteGroup: Index out of bounds" << std::endl; + return palettes[0]; + } + return palettes[i]; + } + int size = 0; + std::vector palettes; +}; + } // namespace gfx } // namespace app } // namespace yaze diff --git a/src/app/rom.cc b/src/app/rom.cc index 34c8f918..36992d92 100644 --- a/src/app/rom.cc +++ b/src/app/rom.cc @@ -19,6 +19,7 @@ #include "app/core/common.h" #include "app/core/constants.h" #include "app/gfx/bitmap.h" +#include "app/zelda3/palettes.h" #define COMPRESSION_STRING_MOD 7 << 5 @@ -646,6 +647,7 @@ absl::Status ROM::LoadFromFile(const absl::string_view& filename) { memcpy(title, rom_data_.data() + kTitleStringOffset, kTitleStringLength); file.close(); + LoadAllPalettes(); is_loaded_ = true; return absl::OkStatus(); } @@ -685,13 +687,14 @@ void ROM::RenderBitmap(gfx::Bitmap* bitmap) const { bitmap->CreateTexture(renderer_); } -gfx::snes_color ROM::ReadColor(int offset) { +gfx::SNESColor ROM::ReadColor(int offset) { short color = (short)((rom_data_[offset + 1] << 8) + rom_data_[offset]); gfx::snes_color new_color; new_color.red = (color & 0x1F) * 8; new_color.green = ((color >> 5) & 0x1F) * 8; new_color.blue = ((color >> 10) & 0x1F) * 8; - return new_color; + gfx::SNESColor snes_color(new_color); + return snes_color; } gfx::SNESPalette ROM::ReadPalette(int offset, int num_colors) { @@ -713,5 +716,96 @@ gfx::SNESPalette ROM::ReadPalette(int offset, int num_colors) { return palette; } +void ROM::LoadAllPalettes() { + // 35 colors each, 7x5 (0,2 on grid) + for (int i = 0; i < 6; i++) { + zelda3::overworld_MainPalettes[i] = + ReadPalette(core::overworldPaletteMain + (i * (35 * 2)), 35); + } + // 21 colors each, 7x3 (8,2 and 8,5 on grid) + for (int i = 0; i < 20; i++) { + zelda3::overworld_AuxPalettes[i] = + ReadPalette(core::overworldPaletteAuxialiary + (i * (21 * 2)), 21); + } + // 7 colors each 7x1 (0,7 on grid) + for (int i = 0; i < 14; i++) { + zelda3::overworld_AnimatedPalettes[i] = + ReadPalette(core::overworldPaletteAnimated + (i * (7 * 2)), 7); + } + // 32 colors each 16x2 (0,0 on grid) + for (int i = 0; i < 2; i++) { + zelda3::HudPalettes[i] = ReadPalette(core::hudPalettes + (i * 64), 32); + } + + zelda3::globalSprite_Palettes[0] = + ReadPalette(core::globalSpritePalettesLW, 60); + zelda3::globalSprite_Palettes[1] = + ReadPalette(core::globalSpritePalettesDW, 60); + for (int i = 0; i < 5; i++) { + zelda3::armors_Palettes[i] = + ReadPalette(core::armorPalettes + (i * 30), 15); + } + for (int i = 0; i < 4; i++) { + zelda3::swords_Palettes[i] = ReadPalette(core::swordPalettes + (i * 6), 3); + } + for (int i = 0; i < 3; i++) { + zelda3::shields_Palettes[i] = + ReadPalette(core::shieldPalettes + (i * 8), 4); + } + for (int i = 0; i < 12; i++) { + zelda3::spritesAux1_Palettes[i] = + ReadPalette(core::spritePalettesAux1 + (i * 14), 7); + } + for (int i = 0; i < 11; i++) { + zelda3::spritesAux2_Palettes[i] = + ReadPalette(core::spritePalettesAux2 + (i * 14), 7); + } + for (int i = 0; i < 24; i++) { + zelda3::spritesAux3_Palettes[i] = + ReadPalette(core::spritePalettesAux3 + (i * 14), 7); + } + for (int i = 0; i < 20; i++) { + zelda3::dungeonsMain_Palettes[i] = + ReadPalette(core::dungeonMainPalettes + (i * 180), 90); + } + + zelda3::overworld_GrassPalettes[0] = ReadColor(core::hardcodedGrassLW); + zelda3::overworld_GrassPalettes[1] = ReadColor(core::hardcodedGrassDW); + zelda3::overworld_GrassPalettes[2] = ReadColor(core::hardcodedGrassSpecial); + + zelda3::object3D_Palettes[0] = ReadPalette(core::triforcePalette, 8); + zelda3::object3D_Palettes[1] = ReadPalette(core::crystalPalette, 8); + + for (int i = 0; i < 2; i++) { + zelda3::overworld_Mini_Map_Palettes[i] = + ReadPalette(core::overworldMiniMapPalettes + (i * 256), 128); + } + + // TODO: check for the paletts in the empty bank space that kan will allocate + // and read them in here + // TODO magic colors + // LW + // int j = 0; + // while (j < 64) { + // zelda3::overworld_BackgroundPalette[j++] = + // Color.FromArgb(0xFF, 0x48, 0x98, 0x48); + // } + + // // DW + // while (j < 128) { + // zelda3::overworld_BackgroundPalette[j++] = + // Color.FromArgb(0xFF, 0x90, 0x88, 0x50); + // } + + // // SP + // while (j < core::kNumOverworldMaps) { + // zelda3::overworld_BackgroundPalette[j++] = + // Color.FromArgb(0xFF, 0x48, 0x98, 0x48); + // } + + // zelda3::overworld_BackgroundPalette = + // ReadPalette(core::customAreaSpecificBGPalette, 160); +} + } // namespace app } // namespace yaze \ No newline at end of file diff --git a/src/app/rom.h b/src/app/rom.h index 41aaebe9..aa490797 100644 --- a/src/app/rom.h +++ b/src/app/rom.h @@ -20,6 +20,7 @@ #include "app/core/common.h" #include "app/core/constants.h" #include "app/gfx/bitmap.h" +#include "app/zelda3/palettes.h" #define BUILD_HEADER(command, length) (command << 5) + (length - 1) @@ -80,10 +81,11 @@ class ROM { absl::Status LoadFromFile(const absl::string_view& filename); absl::Status LoadFromPointer(uchar* data, size_t length); absl::Status LoadFromBytes(const Bytes& data); + void LoadAllPalettes(); absl::Status SaveToFile(); - gfx::snes_color ReadColor(int offset); + gfx::SNESColor ReadColor(int offset); gfx::SNESPalette ReadPalette(int offset, int num_colors); void RenderBitmap(gfx::Bitmap* bitmap) const; diff --git a/src/app/zelda3/overworld.h b/src/app/zelda3/overworld.h index 16652172..5ea21356 100644 --- a/src/app/zelda3/overworld.h +++ b/src/app/zelda3/overworld.h @@ -33,6 +33,9 @@ class Overworld { auto GetCurrentBitmapData() const { return overworld_maps_[current_map_].GetBitmapData(); } + auto GetCurrentPalette() const { + return overworld_maps_[current_map_].GetCurrentPalette(); + } auto isLoaded() const { return is_loaded_; } void SetCurrentMap(int i) { current_map_ = i; } diff --git a/src/app/zelda3/overworld_map.cc b/src/app/zelda3/overworld_map.cc index 7927e5df..6a91bb88 100644 --- a/src/app/zelda3/overworld_map.cc +++ b/src/app/zelda3/overworld_map.cc @@ -19,64 +19,6 @@ namespace zelda3 { namespace { -void CopyTile(int x, int y, int xx, int yy, int offset, gfx::TileInfo tile, - Bytes& ow_blockset, Bytes& current_gfx) { - int mx = x; - int my = y; - uchar r = 0x00; - - if (tile.horizontal_mirror_ != 0) { - mx = 0x03 - x; - r = 0x01; - } - - if (tile.vertical_mirror_ != 0) { - my = 0x07 - y; - } - - int tx = ((tile.id_ / 0x10) * 0x200) + - ((tile.id_ - ((tile.id_ / 0x10) * 0x10)) * 0x04); - auto index = xx + yy + offset + (mx * 0x02) + (my * 0x80); - auto pixel = current_gfx[tx + (y * 0x40) + x]; - - auto p1 = index + r ^ 1; - ow_blockset[p1] = (uchar)((pixel & 0x0F) + tile.palette_ * 0x10); - auto p2 = index + r; - ow_blockset[p2] = (uchar)(((pixel >> 0x04) & 0x0F) + tile.palette_ * 0x10); -} - -void CopyTile8bpp8(int x, int y, int xx, int yy, int tid, gfx::TileInfo tile, - Bytes& ow_blockset, Bytes& current_gfx) { - const int offsets[] = {0x00, 0x08, 0x400, 0x408}; - int offset = offsets[tid]; - int mx = x; - int my = y; - - if (tile.horizontal_mirror_ != 0) { - mx = 0x07 - x; - } - - if (tile.vertical_mirror_ != 0) { - my = 0x07 - y; - } - - // int tx = ((tile.id_ - ((tile.id_ / 0x20) * 0x20)) * 0x10) + - // ((tile.id_ / 0x20) * 0x800); - // auto gfx_src_pos = tx + (y * 0x200) + x; - // auto pixel = current_gfx[gfx_src_pos]; - - // auto index = xx + yy + offset + mx + (my * 0x100); - // auto to_assign = (pixel + (tile.palette_ * 0x10)); - // ow_blockset[index] = to_assign; - // TILE ID ONLY - // int tx = ((tile.id_ - ((tile.id_ / 0x20) * 0x20)) * 0x10) + - // ((tile.id_ / 0x20) * 0x800); - - auto index = xx + yy + offset + mx + (my * 0x80); - int tx = (tile.id_ * 0x40); - ow_blockset[index] = current_gfx[tx + (y * 0x80) + x]; -} - void CopyTile8bpp16(int x, int y, int tile, Bytes& bitmap, Bytes& blockset) { int src_pos = ((tile - ((tile / 0x08) * 0x08)) * 0x10) + ((tile / 0x08) * 2048); @@ -89,6 +31,120 @@ void CopyTile8bpp16(int x, int y, int tile, Bytes& bitmap, Bytes& blockset) { } } +void SetColorsPalette(int index, gfx::SNESPalette& current, gfx::SNESPalette main, + gfx::SNESPalette animated, gfx::SNESPalette aux1, + gfx::SNESPalette aux2, gfx::SNESPalette hud, + gfx::SNESColor bgrcolor, gfx::SNESPalette spr, + gfx::SNESPalette spr2) { + // Palettes infos, color 0 of a palette is always transparent (the arrays + // contains 7 colors width wide) There is 16 color per line so 16*Y + + // Left side of the palette - Main, Animated + std::vector new_palette(256); + + // Main Palette, Location 0,2 : 35 colors [7x5] + int k = 0; + for (int y = 2; y < 7; y++) { + for (int x = 1; x < 8; x++) { + new_palette[x + (16 * y)] = main[k++]; + } + } + + // Animated Palette, Location 0,7 : 7colors + for (int x = 1; x < 8; x++) { + new_palette[(16 * 7) + (x)] = animated[(x - 1)]; + } + + // Right side of the palette - Aux1, Aux2 + + // Aux1 Palette, Location 8,2 : 21 colors [7x3] + k = 0; + for (int y = 2; y < 5; y++) { + for (int x = 9; x < 16; x++) { + new_palette[x + (16 * y)] = aux1[k++]; + } + } + + // Aux2 Palette, Location 8,5 : 21 colors [7x3] + k = 0; + for (int y = 5; y < 8; y++) { + for (int x = 9; x < 16; x++) { + new_palette[x + (16 * y)] = aux2[k++]; + } + } + + // Hud Palette, Location 0,0 : 32 colors [16x2] + for (int i = 0; i < 32; i++) { + new_palette[i] = hud[i]; + } + + // Hardcoded grass color (that might change to become invisible instead) + for (int i = 0; i < 8; i++) { + new_palette[(i * 16)] = bgrcolor; + new_palette[(i * 16) + 8] = bgrcolor; + } + + // Sprite Palettes + k = 0; + for (int y = 8; y < 9; y++) { + for (int x = 1; x < 8; x++) { + new_palette[x + (16 * y)] = spritesAux1_Palettes[1][k++]; + } + } + + // Sprite Palettes + k = 0; + for (int y = 8; y < 9; y++) { + for (int x = 9; x < 16; x++) { + new_palette[x + (16 * y)] = spritesAux3_Palettes[0][k++]; + } + } + + // Sprite Palettes + k = 0; + for (int y = 9; y < 13; y++) { + for (int x = 1; x < 16; x++) { + new_palette[x + (16 * y)] = globalSprite_Palettes[0][k++]; + } + } + + // Sprite Palettes + k = 0; + for (int y = 13; y < 14; y++) { + for (int x = 1; x < 8; x++) { + new_palette[x + (16 * y)] = spr[k++]; + } + } + + // Sprite Palettes + k = 0; + for (int y = 14; y < 15; y++) { + for (int x = 1; x < 8; x++) { + new_palette[x + (16 * y)] = spr2[k++]; + } + } + + // Sprite Palettes + k = 0; + for (int y = 15; y < 16; y++) { + for (int x = 1; x < 16; x++) { + new_palette[x + (16 * y)] = armors_Palettes[0][k++]; + } + } + + current.Create(new_palette); + // ColorPalette pal = GFX.editort16Bitmap.Palette; + // for (int i = 0; i < 256; i++) { + // pal.Entries[i] = new_palette[i]; + // pal.Entries[(i / 16) * 16] = Color.Transparent; + // } + + // GFX.mapgfx16Bitmap.Palette = pal; + // GFX.mapblockset16Bitmap.Palette = pal; + + // gfxBitmap.Palette = pal; +} + } // namespace OverworldMap::OverworldMap(int index, ROM& rom, @@ -109,8 +165,8 @@ absl::Status OverworldMap::BuildMap(int count, int game_state, int world, rom_[core::overworldSpecialGFXGroup + (parent_ - 0x80)]; area_palette_ = rom_[core::overworldSpecialPALGroup + 1]; } else if (index_ == 0x88) { - area_graphics_ = 81; - area_palette_ = 0; + area_graphics_ = 0x51; + area_palette_ = 0x00; } else { area_graphics_ = rom_[core::mapGfx + parent_]; area_palette_ = rom_[core::overworldMapPalette + parent_]; @@ -126,12 +182,13 @@ absl::Status OverworldMap::BuildMap(int count, int game_state, int world, } else if (parent_ >= 0x40 && parent_ < 0x80) { world_index = 0x21; } else if (parent_ == 0x88) { - world_index = 36; + world_index = 0x24; } LoadAreaGraphics(game_state, world_index); RETURN_IF_ERROR(BuildTileset()) - RETURN_IF_ERROR(BuildTiles16GfxV2(count)) + RETURN_IF_ERROR(BuildTiles16Gfx(count)) + LoadPalette(); RETURN_IF_ERROR(BuildBitmap(world_blockset)) built_ = true; return absl::OkStatus(); @@ -152,11 +209,11 @@ void OverworldMap::LoadAreaInfo() { area_music_[3] = rom_[core::overworldMusicAgahim + parent_]; sprite_graphics_[0] = rom_[core::overworldSpriteset + parent_]; - sprite_graphics_[1] = rom_[core::overworldSpriteset + parent_ + 64]; + sprite_graphics_[1] = rom_[core::overworldSpriteset + parent_ + 0x40]; sprite_graphics_[2] = rom_[core::overworldSpriteset + parent_ + 0x80]; sprite_palette_[0] = rom_[core::overworldSpritePalette + parent_]; - sprite_palette_[1] = rom_[core::overworldSpritePalette + parent_ + 64]; + sprite_palette_[1] = rom_[core::overworldSpritePalette + parent_ + 0x40]; sprite_palette_[2] = rom_[core::overworldSpritePalette + parent_ + 0x80]; } else if (index_ < 0x80) { area_graphics_ = rom_[core::mapGfx + parent_]; @@ -218,14 +275,14 @@ void OverworldMap::LoadAreaInfo() { void OverworldMap::LoadAreaGraphics(int game_state, int world_index) { // Sprites Blocksets - static_graphics_[8] = 115 + 0; - static_graphics_[9] = 115 + 1; - static_graphics_[10] = 115 + 6; - static_graphics_[11] = 115 + 7; + static_graphics_[8] = 0x73 + 0x00; + static_graphics_[9] = 0x73 + 0x01; + static_graphics_[10] = 0x73 + 0x06; + static_graphics_[11] = 0x73 + 0x07; for (int i = 0; i < 4; i++) { static_graphics_[12 + i] = (rom_[core::kSpriteBlocksetPointer + (sprite_graphics_[game_state] * 4) + i] + - 115); + 0x73); } // Main Blocksets @@ -253,66 +310,171 @@ void OverworldMap::LoadAreaGraphics(int game_state, int world_index) { // Hardcoded overworld GFX Values, for death mountain if ((parent_ >= 0x03 && parent_ <= 0x07) || (parent_ >= 0x0B && parent_ <= 0x0E)) { - static_graphics_[7] = 89; + static_graphics_[7] = 0x59; } else if ((parent_ >= 0x43 && parent_ <= 0x47) || (parent_ >= 0x4B && parent_ <= 0x4E)) { - static_graphics_[7] = 89; + static_graphics_[7] = 0x59; } else { - static_graphics_[7] = 91; + static_graphics_[7] = 0x5B; } } -absl::Status OverworldMap::BuildTileset() { - for (int i = 0; i < 16; i++) { - auto sheet = rom_.GetGraphicsBin().at(static_graphics_[i]); - current_graphics_sheet_set[i] = sheet; +void OverworldMap::LoadPalette() { + int previousPalId = 0; + int previousSprPalId = 0; + if (index_ > 0) { + previousPalId = rom_[core::overworldMapPalette + parent_ - 1]; + previousSprPalId = rom_[core::overworldSpritePalette + parent_ - 1]; } - all_gfx_ = rom_.GetGraphics8BPP(); + if (area_palette_ >= 0xA3) { + area_palette_ = 0xA3; + } - current_gfx_.reserve(65536); - for (int i = 0; i < 65536; i++) { + uchar pal0 = 0; + + uchar pal1 = + rom_[core::overworldMapPaletteGroup + (area_palette_ * 4)]; // aux1 + uchar pal2 = + rom_[core::overworldMapPaletteGroup + (area_palette_ * 4) + 1]; // aux2 + uchar pal3 = rom_[core::overworldMapPaletteGroup + (area_palette_ * 4) + + 2]; // animated + + uchar pal4 = rom_[core::overworldSpritePaletteGroup + + (sprite_palette_[game_state_] * 2)]; // spr3 + uchar pal5 = rom_[core::overworldSpritePaletteGroup + + (sprite_palette_[game_state_] * 2) + 1]; // spr4 + + gfx::SNESPalette aux1, aux2, main, animated, hud, spr, spr2; + gfx::SNESColor bgr = overworld_GrassPalettes[0]; + + if (pal1 == 255) { + pal1 = rom_[core::overworldMapPaletteGroup + (previousPalId * 4)]; + } + if (pal1 != 255) { + if (pal1 >= 20) { + pal1 = 19; + } + + aux1 = overworld_AuxPalettes[pal1]; + } else { + aux1 = overworld_AuxPalettes[0]; + } + + if (pal2 == 255) { + pal2 = rom_[core::overworldMapPaletteGroup + (previousPalId * 4) + 1]; + } + if (pal2 != 255) { + if (pal2 >= 20) { + pal2 = 19; + } + + aux2 = overworld_AuxPalettes[pal2]; + } else { + aux2 = overworld_AuxPalettes[0]; + } + + if (pal3 == 255) { + pal3 = rom_[core::overworldMapPaletteGroup + (previousPalId * 4) + 2]; + } + + if (parent_ < 0x40) { + // Default LW Palette + pal0 = 0; + + // TODO CHECK ME FOR NECESSITY + // if (OverworldEditor.UseAreaSpecificBgColor) { + // bgr = overworld_BackgroundPalette[parent_]; + // } else { + // bgr = overworld_GrassPalettes[0]; + // } + + if (parent_ == 0x03 || parent_ == 0x05 || parent_ == 0x07) { + pal0 = 2; + } + } else if (parent_ >= 0x40 && parent_ < 0x80) { + // Default DW Palette + pal0 = 1; + // if (OverworldEditor.UseAreaSpecificBgColor) { + // bgr = Palettes.overworld_BackgroundPalette[parent_]; + // } else { + // bgr = Palettes.overworld_GrassPalettes[1]; + // } + + if (parent_ == 0x43 || parent_ == 0x45 || parent_ == 0x47) { + pal0 = 3; + } + } else if (parent_ >= 128 && parent_ < core::kNumOverworldMaps) { + // Default SP Palette + pal0 = 0; + + // if (OverworldEditor.UseAreaSpecificBgColor) { + // bgr = overworld_BackgroundPalette[parent_]; + // } else { + // bgr = overworld_GrassPalettes[2]; + // } + } + + if (parent_ == 0x88) { + pal0 = 4; + } + + if (pal0 != 255) { + main = overworld_MainPalettes[pal0]; + } else { + main = overworld_MainPalettes[0]; + } + + if (pal3 >= 14) { + pal3 = 13; + } + animated = overworld_AnimatedPalettes[(pal3)]; + + hud = HudPalettes[0]; + if (pal4 == 255) { + pal4 = rom_[core::overworldSpritePaletteGroup + + (previousSprPalId * 2)]; // spr3 + } + if (pal4 == 255) { + pal4 = 0; + } + if (pal4 >= 24) { + pal4 = 23; + } + spr = spritesAux3_Palettes[pal4]; + + if (pal5 == 255) { + pal5 = rom_[core::overworldSpritePaletteGroup + (previousSprPalId * 2) + + 1]; // spr3 + } + if (pal5 == 255) { + pal5 = 0; + } + if (pal5 >= 24) { + pal5 = 23; + } + spr2 = spritesAux3_Palettes[pal5]; + + SetColorsPalette(parent_, current_palette_, main, animated, aux1, aux2, hud, bgr, spr, spr2); +} + +absl::Status OverworldMap::BuildTileset() { + all_gfx_ = rom_.GetGraphicsBuffer(); + current_gfx_.reserve(0x10000); + for (int i = 0; i < 0x10000; i++) { current_gfx_.push_back(0x00); } - for (int i = 0; i < 16; i++) { - for (int j = 0; j < 4096; j++) { - current_gfx_[(i * 4096) + j] = all_gfx_[j + (static_graphics_[i] * 4096)]; + for (int i = 0; i < 0x10; i++) { + for (int j = 0; j < 0x1000; j++) { + current_gfx_[(i * 0x1000) + j] = + all_gfx_[j + (static_graphics_[i] * 0x1000)]; } } return absl::OkStatus(); } absl::Status OverworldMap::BuildTiles16Gfx(int count) { - current_blockset_.reserve(0x100000); - for (int i = 0; i < 0x100000; i++) { - current_blockset_.push_back(0x00); - } - auto yy = 0; - auto xx = 0; - - for (auto i = 0; i < count; i++) { - for (auto tile = 0; tile < 0x04; tile++) { - gfx::TileInfo info = tiles16_[i].tiles_info[tile]; - for (auto y = 0; y < 0x08; ++y) { - for (auto x = 0; x < 0x08; ++x) { - CopyTile8bpp8(x, y, xx, yy, tile, info, current_blockset_, - current_gfx_); - } - } - } - - xx += 0x10; - if (xx >= 0x80) { - yy += 0x800; - xx = 0; - } - } - - return absl::OkStatus(); -} - -absl::Status OverworldMap::BuildTiles16GfxV2(int count) { current_blockset_.reserve(0x100000); for (int i = 0; i < 0x100000; i++) { current_blockset_.push_back(0x00); @@ -338,8 +500,8 @@ absl::Status OverworldMap::BuildTiles16GfxV2(int count) { my = 0x07 - y; } - int xpos = ((info.id_ % 16) * 8); - int ypos = (((info.id_ / 16)) * 0x400); + int xpos = ((info.id_ % 0x10) * 0x08); + int ypos = (((info.id_ / 0x10)) * 0x400); int source = ypos + xpos + (x + (y * 0x80)); auto destination = xx + yy + offset + (mx + (my * 0x80)); diff --git a/src/app/zelda3/overworld_map.h b/src/app/zelda3/overworld_map.h index 25dd3161..2029376a 100644 --- a/src/app/zelda3/overworld_map.h +++ b/src/app/zelda3/overworld_map.h @@ -13,6 +13,7 @@ #include "app/core/common.h" #include "app/gfx/bitmap.h" #include "app/gfx/snes_tile.h" +#include "app/zelda3/palettes.h" #include "app/rom.h" namespace yaze { @@ -28,9 +29,9 @@ class OverworldMap { absl::Status BuildMap(int count, int game_state, int world, uchar* map_parent, OWBlockset& world_blockset); - auto GetCurrentGraphicsSet() const { return current_graphics_sheet_set; } auto GetCurrentBlockset() const { return current_blockset_; } auto GetCurrentGraphics() const { return current_gfx_; } + auto GetCurrentPalette() const { return current_palette_; } auto GetBitmapData() const { return bitmap_data_; } auto SetLargeMap(bool is_set) { large_map_ = is_set; } auto IsLargeMap() const { return large_map_; } @@ -40,10 +41,10 @@ class OverworldMap { private: void LoadAreaInfo(); void LoadAreaGraphics(int game_state, int world_index); + void LoadPalette(); absl::Status BuildTileset(); absl::Status BuildTiles16Gfx(int count); - absl::Status BuildTiles16GfxV2(int count); absl::Status BuildBitmap(OWBlockset& world_blockset); int parent_ = 0; @@ -53,6 +54,9 @@ class OverworldMap { int area_graphics_ = 0; int area_palette_ = 0; + // TODO SET ME + int game_state_ = 0; + uchar sprite_graphics_[3]; uchar sprite_palette_[3]; uchar area_music_[4]; @@ -69,8 +73,9 @@ class OverworldMap { Bytes bitmap_data_; OWMapTiles map_tiles_; + gfx::SNESPalette current_palette_; + std::vector tiles16_; - std::unordered_map current_graphics_sheet_set; }; } // namespace zelda3 diff --git a/src/app/zelda3/palettes.h b/src/app/zelda3/palettes.h new file mode 100644 index 00000000..1f1b6e0d --- /dev/null +++ b/src/app/zelda3/palettes.h @@ -0,0 +1,45 @@ +#ifndef YAZE_APP_ZELDA3_PALETTES_H +#define YAZE_APP_ZELDA3_PALETTES_H + +#include + +#include "app/core/common.h" +#include "app/gfx/bitmap.h" +#include "app/gfx/snes_tile.h" +#include "app/rom.h" + +namespace yaze { +namespace app { +namespace zelda3 { +// 32 (0,0) +static gfx::PaletteGroup HudPalettes(2); + +// 35 colors each, 7x5 (0,2 on grid) +static gfx::PaletteGroup overworld_MainPalettes(6); + +// 21 colors each, 7x3 (8,2 and 8,5 on grid) +static gfx::PaletteGroup overworld_AuxPalettes(20); + +// 7 colors each 7x1 (0,7 on grid) +static gfx::PaletteGroup overworld_AnimatedPalettes(14); +static gfx::PaletteGroup globalSprite_Palettes(2); // 60 (1,9) +static gfx::PaletteGroup armors_Palettes(5); // 15 +static gfx::PaletteGroup swords_Palettes(4); // 3 +static gfx::PaletteGroup spritesAux1_Palettes(12); // 7 +static gfx::PaletteGroup spritesAux2_Palettes(11); // 7 +static gfx::PaletteGroup spritesAux3_Palettes(24); // 7 +static gfx::PaletteGroup shields_Palettes(3); // 4 +static gfx::PaletteGroup dungeonsMain_Palettes(20); // 15*6 + +// 8*20 +static gfx::PaletteGroup overworld_BackgroundPalette(core::kNumOverworldMaps); + +// 3 hardcoded grass colors +static gfx::SNESPalette overworld_GrassPalettes(3); +static gfx::PaletteGroup object3D_Palettes(2); // 15*6 +static gfx::PaletteGroup overworld_Mini_Map_Palettes(2); // 16*8 +} // namespace zelda3 +} // namespace app +} // namespace yaze + +#endif \ No newline at end of file