From 521b9a1b1cc0ff7a7359ba2e21bd0a56565d2cf7 Mon Sep 17 00:00:00 2001 From: Justin Scofield <47263509+scawful@users.noreply.github.com> Date: Sat, 3 Sep 2022 22:46:08 -0500 Subject: [PATCH 01/21] experimental map draw --- src/app/zelda3/overworld_map.cc | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/app/zelda3/overworld_map.cc b/src/app/zelda3/overworld_map.cc index b6f16b4d..b7eaf5d0 100644 --- a/src/app/zelda3/overworld_map.cc +++ b/src/app/zelda3/overworld_map.cc @@ -44,6 +44,26 @@ void CopyTile(int x, int y, int xx, int yy, int offset, gfx::TileInfo tile, ow_blockset[p2] = (uchar)(((pixel >> 4) & 0x0F) + tile.palette_ * 16); } +void CopyTile8bpp8(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; + + if (tile.horizontal_mirror_ != 0) { + mx = 3 - x; + } + + if (tile.vertical_mirror_ != 0) { + my = 7 - y; + } + + int tx = ((tile.id_ / 16) * 512) + ((tile.id_ - ((tile.id_ / 16) * 16)) * 4); + auto index = xx + yy + offset + (mx * 2) + (my * 0x80); + auto pixel = current_gfx[tx + (y * 128) + x]; + + ow_blockset[index] = (pixel + (tile.palette_ * 16)); +} + void CopyTile8bpp16(int x, int y, int tile, Bytes& dest, Bytes& src) { int src_pos = ((tile - ((tile / 8) * 8)) * 16) + ((tile / 8) * 2048); int dest_pos = (x + (y * 512)); @@ -235,12 +255,12 @@ absl::Status OverworldMap::BuildTileset() { all_gfx_ = rom_.GetGraphics8BPP(); - current_gfx_.reserve(32768); - for (int i = 0; i < 32768; i++) { + current_gfx_.reserve(65536); + for (int i = 0; i < 65536; i++) { current_gfx_.push_back(0x00); } - for (int i = 0; i < 32; i++) { + 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)]; } @@ -257,22 +277,21 @@ absl::Status OverworldMap::BuildTiles16Gfx(int count) { auto yy = 0; auto xx = 0; - // number of tiles16 3748? for (auto i = 0; i < count; i++) { - // 8x8 tile draw, gfx8 = 4bpp so everyting is /2F for (auto tile = 0; tile < 4; tile++) { gfx::TileInfo info = tiles16_[i].tiles_info[tile]; int offset = offsets[tile]; for (auto y = 0; y < 8; y++) { for (auto x = 0; x < 4; x++) { - CopyTile(x, y, xx, yy, offset, info, current_blockset_, current_gfx_); + CopyTile8bpp8(x, y, xx, yy, offset, info, current_blockset_, + current_gfx_); } } } xx += 16; - if (xx >= 0x80) { + if (xx >= 128) { yy += 2048; xx = 0; } From 2f12ff8f5752809d15def12b793d174bd3bce808 Mon Sep 17 00:00:00 2001 From: scawful Date: Sun, 4 Sep 2022 15:49:55 -0500 Subject: [PATCH 02/21] ow map draw continue --- src/app/zelda3/overworld_map.cc | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/app/zelda3/overworld_map.cc b/src/app/zelda3/overworld_map.cc index b7eaf5d0..dc94adb4 100644 --- a/src/app/zelda3/overworld_map.cc +++ b/src/app/zelda3/overworld_map.cc @@ -50,18 +50,17 @@ void CopyTile8bpp8(int x, int y, int xx, int yy, int offset, gfx::TileInfo tile, int my = y; if (tile.horizontal_mirror_ != 0) { - mx = 3 - x; + mx = 7 - x; } if (tile.vertical_mirror_ != 0) { my = 7 - y; } - int tx = ((tile.id_ / 16) * 512) + ((tile.id_ - ((tile.id_ / 16) * 16)) * 4); - auto index = xx + yy + offset + (mx * 2) + (my * 0x80); - auto pixel = current_gfx[tx + (y * 128) + x]; - - ow_blockset[index] = (pixel + (tile.palette_ * 16)); + int tx = ((tile.id_ / 32) * 1024) + ((tile.id_ - ((tile.id_ / 32) * 32)) * 8); + auto pixel = current_gfx[tx + x + (y * 0x80)]; + auto index = xx + yy + offset + mx + (my * 0x80); + ow_blockset[index] = (uchar)(pixel + (tile.palette_ * 16)); } void CopyTile8bpp16(int x, int y, int tile, Bytes& dest, Bytes& src) { @@ -269,8 +268,8 @@ absl::Status OverworldMap::BuildTileset() { } absl::Status OverworldMap::BuildTiles16Gfx(int count) { - current_blockset_.reserve(1048576); - for (int i = 0; i < 1048576; i++) { + current_blockset_.reserve(1048576 * 2); + for (int i = 0; i < 1048576 * 2; i++) { current_blockset_.push_back(0x00); } int offsets[] = {0, 8, 1024, 1032}; @@ -283,7 +282,7 @@ absl::Status OverworldMap::BuildTiles16Gfx(int count) { int offset = offsets[tile]; for (auto y = 0; y < 8; y++) { - for (auto x = 0; x < 4; x++) { + for (auto x = 0; x < 8; x++) { CopyTile8bpp8(x, y, xx, yy, offset, info, current_blockset_, current_gfx_); } From b9d1c7bf319da771c89d99989ec3d54c43921592 Mon Sep 17 00:00:00 2001 From: Justin Scofield <47263509+scawful@users.noreply.github.com> Date: Sun, 4 Sep 2022 23:12:03 -0500 Subject: [PATCH 03/21] convert numbers in copy functions to hex and adjust bit math --- src/app/zelda3/overworld_map.cc | 50 ++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/app/zelda3/overworld_map.cc b/src/app/zelda3/overworld_map.cc index dc94adb4..36bd7857 100644 --- a/src/app/zelda3/overworld_map.cc +++ b/src/app/zelda3/overworld_map.cc @@ -23,52 +23,59 @@ 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 = 0; + uchar r = 0x00; if (tile.horizontal_mirror_ != 0) { - mx = 3 - x; - r = 1; + mx = 0x03 - x; + r = 0x01; } if (tile.vertical_mirror_ != 0) { - my = 7 - y; + my = 0x07 - y; } - int tx = ((tile.id_ / 16) * 512) + ((tile.id_ - ((tile.id_ / 16) * 16)) * 4); - auto index = xx + yy + offset + (mx * 2) + (my * 0x80); - auto pixel = current_gfx[tx + (y * 64) + x]; + 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_ * 16); + ow_blockset[p1] = (uchar)((pixel & 0x0F) + tile.palette_ * 0x10); auto p2 = index + r; - ow_blockset[p2] = (uchar)(((pixel >> 4) & 0x0F) + tile.palette_ * 16); + ow_blockset[p2] = (uchar)(((pixel >> 0x04) & 0x0F) + tile.palette_ * 0x10); } void CopyTile8bpp8(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 = 7 - x; + mx = 0x07 - x; + r = 0x01; } if (tile.vertical_mirror_ != 0) { - my = 7 - y; + my = 0x07 - y; } - int tx = ((tile.id_ / 32) * 1024) + ((tile.id_ - ((tile.id_ / 32) * 32)) * 8); + int tx = ((tile.id_ / 0x20) * 0x800) + + ((tile.id_ - ((tile.id_ / 0x20) * 0x20)) * 0x08); auto pixel = current_gfx[tx + x + (y * 0x80)]; auto index = xx + yy + offset + mx + (my * 0x80); - ow_blockset[index] = (uchar)(pixel + (tile.palette_ * 16)); + + ow_blockset[index] = (uchar)(pixel + (tile.palette_ * 0x10)); } -void CopyTile8bpp16(int x, int y, int tile, Bytes& dest, Bytes& src) { - int src_pos = ((tile - ((tile / 8) * 8)) * 16) + ((tile / 8) * 2048); - int dest_pos = (x + (y * 512)); - for (int yy = 0; yy < 16; yy++) { - for (int xx = 0; xx < 16; xx++) { - dest[dest_pos + xx + (yy * 512)] = src[src_pos + xx + (yy * 0x80)]; +void CopyTile8bpp16(int x, int y, int tile, Bytes& bitmap, Bytes& blockset) { + int src_pos = + ((tile - ((tile / 0x08) * 0x08)) * 0x10) + ((tile / 0x08) * 2048); + int dest_pos = (x + (y * 0x200)); + for (int yy = 0; yy < 0x10; yy++) { + for (int xx = 0; xx < 0x10; xx++) { + bitmap[dest_pos + xx + (yy * 0x200)] = + blockset[src_pos + xx + (yy * 0x80)]; } } } @@ -268,8 +275,8 @@ absl::Status OverworldMap::BuildTileset() { } absl::Status OverworldMap::BuildTiles16Gfx(int count) { - current_blockset_.reserve(1048576 * 2); - for (int i = 0; i < 1048576 * 2; i++) { + current_blockset_.reserve(1048576); + for (int i = 0; i < 1048576; i++) { current_blockset_.push_back(0x00); } int offsets[] = {0, 8, 1024, 1032}; @@ -280,7 +287,6 @@ absl::Status OverworldMap::BuildTiles16Gfx(int count) { for (auto tile = 0; tile < 4; tile++) { gfx::TileInfo info = tiles16_[i].tiles_info[tile]; int offset = offsets[tile]; - for (auto y = 0; y < 8; y++) { for (auto x = 0; x < 8; x++) { CopyTile8bpp8(x, y, xx, yy, offset, info, current_blockset_, From 32f287d89c608ca3eb8b16d433a0ffbac2dd6a24 Mon Sep 17 00:00:00 2001 From: Justin Scofield <47263509+scawful@users.noreply.github.com> Date: Sun, 4 Sep 2022 23:15:57 -0500 Subject: [PATCH 04/21] hex numbers --- src/app/zelda3/overworld_map.cc | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/app/zelda3/overworld_map.cc b/src/app/zelda3/overworld_map.cc index 36bd7857..3a407696 100644 --- a/src/app/zelda3/overworld_map.cc +++ b/src/app/zelda3/overworld_map.cc @@ -275,29 +275,30 @@ absl::Status OverworldMap::BuildTileset() { } absl::Status OverworldMap::BuildTiles16Gfx(int count) { - current_blockset_.reserve(1048576); - for (int i = 0; i < 1048576; i++) { + current_blockset_.reserve(0x100000); + for (int i = 0; i < 0x100000; i++) { current_blockset_.push_back(0x00); } - int offsets[] = {0, 8, 1024, 1032}; + + int offsets[] = {0x00, 0x08, 0x400, 0x408}; auto yy = 0; auto xx = 0; for (auto i = 0; i < count; i++) { - for (auto tile = 0; tile < 4; tile++) { + for (auto tile = 0; tile < 0x04; tile++) { gfx::TileInfo info = tiles16_[i].tiles_info[tile]; int offset = offsets[tile]; - for (auto y = 0; y < 8; y++) { - for (auto x = 0; x < 8; x++) { + for (auto y = 0; y < 0x08; y++) { + for (auto x = 0; x < 0x08; x++) { CopyTile8bpp8(x, y, xx, yy, offset, info, current_blockset_, current_gfx_); } } } - xx += 16; - if (xx >= 128) { - yy += 2048; + xx += 0x10; + if (xx >= 0x80) { + yy += 0x800; xx = 0; } } From 7daeeea14e4d9e9cb079bb137a5e8b79e8ea845c Mon Sep 17 00:00:00 2001 From: Justin Scofield <47263509+scawful@users.noreply.github.com> Date: Mon, 5 Sep 2022 13:03:05 -0500 Subject: [PATCH 05/21] bug: fix tile16 issue with toint16 method --- src/app/gfx/snes_tile.cc | 14 +++++++------- src/app/gfx/snes_tile.h | 8 ++++---- src/app/rom.h | 6 +++++- src/app/zelda3/overworld.cc | 8 ++++---- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/app/gfx/snes_tile.cc b/src/app/gfx/snes_tile.cc index 6a90226b..3e02f34b 100644 --- a/src/app/gfx/snes_tile.cc +++ b/src/app/gfx/snes_tile.cc @@ -11,15 +11,15 @@ namespace gfx { TileInfo GetTilesInfo(ushort tile) { // vhopppcc cccccccc - ushort o = 0; - ushort v = 0; - ushort h = 0; - auto tid = (ushort)(tile & 0x3FF); + bool o = false; + bool v = false; + bool h = false; + auto tid = (ushort)(tile & core::TileNameMask); auto p = (uchar)((tile >> 10) & 0x07); - o = (ushort)((tile & 0x2000) >> 13); - h = (ushort)((tile & 0x4000) >> 14); - v = (ushort)((tile & 0x8000) >> 15); + o = ((tile & core::TilePriorityBit) == core::TilePriorityBit); + h = ((tile & core::TileHFlipBit) == core::TileHFlipBit); + v = ((tile & core::TileVFlipBit) == core::TileVFlipBit); return TileInfo(tid, p, v, h, o); } diff --git a/src/app/gfx/snes_tile.h b/src/app/gfx/snes_tile.h index 81a5a846..72764333 100644 --- a/src/app/gfx/snes_tile.h +++ b/src/app/gfx/snes_tile.h @@ -23,12 +23,12 @@ using tile8 = struct tile8; class TileInfo { public: ushort id_; - ushort over_; - ushort vertical_mirror_; - ushort horizontal_mirror_; + bool over_; + bool vertical_mirror_; + bool horizontal_mirror_; uchar palette_; TileInfo() = default; - TileInfo(ushort id, uchar palette, ushort v, ushort h, ushort o) + TileInfo(ushort id, uchar palette, bool v, bool h, bool o) : id_(id), over_(o), vertical_mirror_(v), diff --git a/src/app/rom.h b/src/app/rom.h index 128649c0..5db94a1a 100644 --- a/src/app/rom.h +++ b/src/app/rom.h @@ -77,7 +77,7 @@ class ROM { absl::StatusOr DecompressOverworld(int pos, int size); absl::Status LoadAllGraphicsData(); - + absl::StatusOr CreateAllGfxDataRaw(); absl::Status CreateAllGraphicsData(); @@ -117,6 +117,10 @@ class ROM { } const uchar* operator&() { return rom_data_.data(); } + ushort toint16(int offset) { + return (ushort)((rom_data_[offset + 1]) << 8) | rom_data_[offset]; + } + private: long size_ = 0; uchar title[21] = "ROM Not Loaded"; diff --git a/src/app/zelda3/overworld.cc b/src/app/zelda3/overworld.cc index 539f7de9..8894bf76 100644 --- a/src/app/zelda3/overworld.cc +++ b/src/app/zelda3/overworld.cc @@ -88,13 +88,13 @@ void Overworld::AssembleMap32Tiles() { void Overworld::AssembleMap16Tiles() { int tpos = core::map16Tiles; for (int i = 0; i < 4096; i += 1) { - auto t0 = gfx::GetTilesInfo((uintptr_t)(rom_ + tpos)); + auto t0 = gfx::GetTilesInfo((rom_.toint16(tpos))); tpos += 2; - auto t1 = gfx::GetTilesInfo((uintptr_t)(rom_ + tpos)); + auto t1 = gfx::GetTilesInfo((rom_.toint16(tpos))); tpos += 2; - auto t2 = gfx::GetTilesInfo((uintptr_t)(rom_ + tpos)); + auto t2 = gfx::GetTilesInfo((rom_.toint16(tpos))); tpos += 2; - auto t3 = gfx::GetTilesInfo((uintptr_t)(rom_ + tpos)); + auto t3 = gfx::GetTilesInfo((rom_.toint16(tpos))); tpos += 2; tiles16.emplace_back(t0, t1, t2, t3); } From 49cc4e939aa800ced548af80456728f69e076eee Mon Sep 17 00:00:00 2001 From: Justin Scofield <47263509+scawful@users.noreply.github.com> Date: Mon, 5 Sep 2022 13:03:25 -0500 Subject: [PATCH 06/21] more hex nums --- src/app/zelda3/overworld_map.cc | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/app/zelda3/overworld_map.cc b/src/app/zelda3/overworld_map.cc index 3a407696..e500d4ce 100644 --- a/src/app/zelda3/overworld_map.cc +++ b/src/app/zelda3/overworld_map.cc @@ -49,7 +49,7 @@ void CopyTile8bpp8(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; + uchar r = 0; if (tile.horizontal_mirror_ != 0) { mx = 0x07 - x; @@ -60,12 +60,13 @@ void CopyTile8bpp8(int x, int y, int xx, int yy, int offset, gfx::TileInfo tile, my = 0x07 - y; } - int tx = ((tile.id_ / 0x20) * 0x800) + - ((tile.id_ - ((tile.id_ / 0x20) * 0x20)) * 0x08); + // TILE ID ONLY + int tx = ((tile.id_ - ((tile.id_ / 0x20) * 0x20)) * 0x08) + + ((tile.id_ / 0x20) * 0x800); auto pixel = current_gfx[tx + x + (y * 0x80)]; auto index = xx + yy + offset + mx + (my * 0x80); - ow_blockset[index] = (uchar)(pixel + (tile.palette_ * 0x10)); + ow_blockset[index + r] = (uchar)(pixel + (tile.palette_ * 0x10)); } void CopyTile8bpp16(int x, int y, int tile, Bytes& bitmap, Bytes& blockset) { @@ -307,20 +308,20 @@ absl::Status OverworldMap::BuildTiles16Gfx(int count) { } absl::Status OverworldMap::BuildBitmap(OWBlockset& world_blockset) { - bitmap_data_.reserve(262144); - for (int i = 0; i < 262144; i++) { + bitmap_data_.reserve(0x40000); + for (int i = 0; i < 0x40000; i++) { bitmap_data_.push_back(0x00); } - int superY = ((index_ - (world_ * 64)) / 8); - int superX = index_ - (world_ * 64) - (superY * 8); + int superY = ((index_ - (world_ * 0x40)) / 0x08); + int superX = index_ - (world_ * 0x40) - (superY * 0x08); - for (int y = 0; y < 32; y++) { - for (int x = 0; x < 32; x++) { - auto xt = x + (superX * 32); - auto yt = y + (superY * 32); - CopyTile8bpp16((x * 16), (y * 16), world_blockset[xt][yt], bitmap_data_, - current_blockset_); + for (int y = 0; y < 0x20; y++) { + for (int x = 0; x < 0x20; x++) { + auto xt = x + (superX * 0x20); + auto yt = y + (superY * 0x20); + CopyTile8bpp16((x * 0x10), (y * 0x10), world_blockset[xt][yt], + bitmap_data_, current_blockset_); } } return absl::OkStatus(); From 0949fc980f319db0da8cdd48e3a5345f480d6a9a Mon Sep 17 00:00:00 2001 From: scawful Date: Wed, 7 Sep 2022 18:23:42 -0500 Subject: [PATCH 07/21] add set current map function for testing --- src/app/zelda3/overworld.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/zelda3/overworld.h b/src/app/zelda3/overworld.h index 84a0c0b6..16652172 100644 --- a/src/app/zelda3/overworld.h +++ b/src/app/zelda3/overworld.h @@ -34,6 +34,7 @@ class Overworld { return overworld_maps_[current_map_].GetBitmapData(); } auto isLoaded() const { return is_loaded_; } + void SetCurrentMap(int i) { current_map_ = i; } private: const int map32address[4] = {core::map32TilesTL, core::map32TilesTR, From 9865b2ab4944b32a9123be2147eba757fe0f76da Mon Sep 17 00:00:00 2001 From: scawful Date: Wed, 7 Sep 2022 18:24:07 -0500 Subject: [PATCH 08/21] add BuildTiles16GfxV2 --- src/app/zelda3/overworld_map.cc | 82 ++++++++++++++++++++++++++------- src/app/zelda3/overworld_map.h | 1 + 2 files changed, 67 insertions(+), 16 deletions(-) diff --git a/src/app/zelda3/overworld_map.cc b/src/app/zelda3/overworld_map.cc index e500d4ce..5d2e7026 100644 --- a/src/app/zelda3/overworld_map.cc +++ b/src/app/zelda3/overworld_map.cc @@ -45,28 +45,36 @@ void CopyTile(int x, int y, int xx, int yy, int offset, gfx::TileInfo tile, ow_blockset[p2] = (uchar)(((pixel >> 0x04) & 0x0F) + tile.palette_ * 0x10); } -void CopyTile8bpp8(int x, int y, int xx, int yy, int offset, gfx::TileInfo tile, +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; - uchar r = 0; if (tile.horizontal_mirror_ != 0) { mx = 0x07 - x; - r = 0x01; } if (tile.vertical_mirror_ != 0) { my = 0x07 - y; } - // TILE ID ONLY - int tx = ((tile.id_ - ((tile.id_ / 0x20) * 0x20)) * 0x08) + - ((tile.id_ / 0x20) * 0x800); - auto pixel = current_gfx[tx + x + (y * 0x80)]; - auto index = xx + yy + offset + mx + (my * 0x80); + // 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]; - ow_blockset[index + r] = (uchar)(pixel + (tile.palette_ * 0x10)); + // 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) { @@ -123,7 +131,7 @@ absl::Status OverworldMap::BuildMap(int count, int game_state, int world, LoadAreaGraphics(game_state, world_index); RETURN_IF_ERROR(BuildTileset()) - RETURN_IF_ERROR(BuildTiles16Gfx(count)) + RETURN_IF_ERROR(BuildTiles16GfxV2(count)) RETURN_IF_ERROR(BuildBitmap(world_blockset)) built_ = true; return absl::OkStatus(); @@ -280,18 +288,15 @@ absl::Status OverworldMap::BuildTiles16Gfx(int count) { for (int i = 0; i < 0x100000; i++) { current_blockset_.push_back(0x00); } - - int offsets[] = {0x00, 0x08, 0x400, 0x408}; 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]; - int offset = offsets[tile]; - for (auto y = 0; y < 0x08; y++) { - for (auto x = 0; x < 0x08; x++) { - CopyTile8bpp8(x, y, xx, yy, offset, info, current_blockset_, + 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_); } } @@ -307,6 +312,51 @@ absl::Status OverworldMap::BuildTiles16Gfx(int count) { 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); + } + const int offsets[] = {0x00, 0x08, 0x400, 0x408}; + auto yy = 0; + auto xx = 0; + + for (auto i = 0; i < 1; i++) { + for (auto tile = 0; tile < 0x04; tile++) { + gfx::TileInfo info = tiles16_[i].tiles_info[tile]; + int offset = offsets[tile]; + for (auto y = 0; y < 0x08; ++y) { + for (auto x = 0; x < 0x08; ++x) { + int mx = x; + int my = y; + + if (info.horizontal_mirror_ != 0) { + mx = 0x07 - x; + } + + if (info.vertical_mirror_ != 0) { + my = 0x07 - y; + } + + int tile_pos = (info.id_ * 0x40); + auto source = tile_pos + (x + (y * 0x80)); + + auto destination = xx + yy + offset + (mx + (my * 0x80)); + current_blockset_[destination] = current_gfx_[source]; + } + } + } + + xx += 0x10; + if (xx >= 0x80) { + yy += 0x800; + xx = 0; + } + } + + return absl::OkStatus(); +} + absl::Status OverworldMap::BuildBitmap(OWBlockset& world_blockset) { bitmap_data_.reserve(0x40000); for (int i = 0; i < 0x40000; i++) { diff --git a/src/app/zelda3/overworld_map.h b/src/app/zelda3/overworld_map.h index 0def48fe..25dd3161 100644 --- a/src/app/zelda3/overworld_map.h +++ b/src/app/zelda3/overworld_map.h @@ -43,6 +43,7 @@ class OverworldMap { absl::Status BuildTileset(); absl::Status BuildTiles16Gfx(int count); + absl::Status BuildTiles16GfxV2(int count); absl::Status BuildBitmap(OWBlockset& world_blockset); int parent_ = 0; From fd965fecf1613e331cc29be9b82ff2202b083335 Mon Sep 17 00:00:00 2001 From: scawful Date: Wed, 7 Sep 2022 18:24:18 -0500 Subject: [PATCH 09/21] load overworld automatically on rom load --- src/app/editor/overworld_editor.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index b5d0913a..0275fb4c 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -41,6 +41,15 @@ absl::Status OverworldEditor::Update() { if (rom_.isLoaded() && !all_gfx_loaded_) { LoadGraphics(); all_gfx_loaded_ = true; + RETURN_IF_ERROR(overworld_.Load(rom_)) + current_gfx_bmp_.Create(128, 512, 64, overworld_.GetCurrentGraphics()); + rom_.RenderBitmap(¤t_gfx_bmp_); + tile16_blockset_bmp_.Create(128, 8192, 128, + overworld_.GetCurrentBlockset()); + rom_.RenderBitmap(&tile16_blockset_bmp_); + map_blockset_loaded_ = true; + overworld_map_bmp_.Create(512, 512, 512, overworld_.GetCurrentBitmapData()); + rom_.RenderBitmap(&overworld_map_bmp_); } if (overworld_debug_menu_) { From 3cacfce41145c5cf64310d048e719a9d07249f35 Mon Sep 17 00:00:00 2001 From: scawful Date: Wed, 7 Sep 2022 18:27:33 -0500 Subject: [PATCH 10/21] fix test value --- src/app/zelda3/overworld_map.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/zelda3/overworld_map.cc b/src/app/zelda3/overworld_map.cc index 5d2e7026..3d92ee06 100644 --- a/src/app/zelda3/overworld_map.cc +++ b/src/app/zelda3/overworld_map.cc @@ -321,7 +321,7 @@ absl::Status OverworldMap::BuildTiles16GfxV2(int count) { auto yy = 0; auto xx = 0; - for (auto i = 0; i < 1; i++) { + for (auto i = 0; i < count; i++) { for (auto tile = 0; tile < 0x04; tile++) { gfx::TileInfo info = tiles16_[i].tiles_info[tile]; int offset = offsets[tile]; From cf2a10f0d9dd34453ac21b117a656b799afe1b3a Mon Sep 17 00:00:00 2001 From: scawful Date: Thu, 8 Sep 2022 09:18:05 -0500 Subject: [PATCH 11/21] add new DrawBitmap overload to Canvas --- src/gui/canvas.cc | 7 +++++++ src/gui/canvas.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/src/gui/canvas.cc b/src/gui/canvas.cc index 1ac36094..c6e52d93 100644 --- a/src/gui/canvas.cc +++ b/src/gui/canvas.cc @@ -78,6 +78,13 @@ void Canvas::DrawBitmap(const Bitmap &bitmap, int border_offset) { canvas_p0_.y + (bitmap.GetHeight() * 2))); } +void Canvas::DrawBitmap(const Bitmap &bitmap, int x_offset, int y_offset) { + draw_list_->AddImage((void *)bitmap.GetTexture(), + ImVec2(canvas_p0_.x + x_offset, canvas_p0_.y + y_offset), + ImVec2(canvas_p0_.x + x_offset + (bitmap.GetWidth()), + canvas_p0_.y + y_offset + (bitmap.GetHeight()))); +} + void Canvas::DrawGrid(float grid_step) { // Draw grid + all lines in the canvas draw_list_->PushClipRect(canvas_p0_, canvas_p1_, true); diff --git a/src/gui/canvas.h b/src/gui/canvas.h index d81de5b5..bb13c72c 100644 --- a/src/gui/canvas.h +++ b/src/gui/canvas.h @@ -22,6 +22,8 @@ class Canvas { void DrawBackground(ImVec2 canvas_size = ImVec2(0, 0)); void DrawContextMenu(); void DrawBitmap(const Bitmap& bitmap, int border_offset = 0); + void DrawBitmap(const Bitmap& bitmap, int x_offset, int y_offset); + // void DrawLargeBitmap(const Bitmap& tl, const Bitmap& tr, const Bitmap& bl, const Bitmap& br); void DrawGrid(float grid_step = 64.0f); void DrawOverlay(); // last From f2feaa78dac953bdbe39fe7c3826ef000d17cac4 Mon Sep 17 00:00:00 2001 From: scawful Date: Thu, 8 Sep 2022 09:18:24 -0500 Subject: [PATCH 12/21] add Zarby map draw fix --- src/app/zelda3/overworld_map.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/zelda3/overworld_map.cc b/src/app/zelda3/overworld_map.cc index 3d92ee06..7927e5df 100644 --- a/src/app/zelda3/overworld_map.cc +++ b/src/app/zelda3/overworld_map.cc @@ -338,8 +338,9 @@ absl::Status OverworldMap::BuildTiles16GfxV2(int count) { my = 0x07 - y; } - int tile_pos = (info.id_ * 0x40); - auto source = tile_pos + (x + (y * 0x80)); + int xpos = ((info.id_ % 16) * 8); + int ypos = (((info.id_ / 16)) * 0x400); + int source = ypos + xpos + (x + (y * 0x80)); auto destination = xx + yy + offset + (mx + (my * 0x80)); current_blockset_[destination] = current_gfx_[source]; From fb02608c6feb8455963c453255219c73dda089bd Mon Sep 17 00:00:00 2001 From: scawful Date: Thu, 8 Sep 2022 09:19:38 -0500 Subject: [PATCH 13/21] draw all overworld maps on canvas --- src/app/editor/overworld_editor.cc | 46 +++++++++++++++++++----------- src/app/editor/overworld_editor.h | 3 +- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index 0275fb4c..a03cd27c 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -48,8 +48,11 @@ absl::Status OverworldEditor::Update() { overworld_.GetCurrentBlockset()); rom_.RenderBitmap(&tile16_blockset_bmp_); map_blockset_loaded_ = true; - overworld_map_bmp_.Create(512, 512, 512, overworld_.GetCurrentBitmapData()); - rom_.RenderBitmap(&overworld_map_bmp_); + for (int i = 0; i < core::kNumOverworldMaps; ++i) { + overworld_.SetCurrentMap(i); + maps_bmp_[i].Create(512, 512, 512, overworld_.GetCurrentBitmapData()); + rom_.RenderBitmap(&(maps_bmp_[i])); + } } if (overworld_debug_menu_) { @@ -135,10 +138,14 @@ absl::Status OverworldEditor::DrawToolset() { } void OverworldEditor::DrawOverworldMapSettings() { - if (ImGui::BeginTable("#mapSettings", 7, ow_map_flags, ImVec2(0, 0), -1)) { + if (ImGui::BeginTable("#mapSettings", 8, ow_map_flags, ImVec2(0, 0), -1)) { for (const auto &name : kOverworldSettingsColumnNames) ImGui::TableSetupColumn(name.data()); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(50.f); + ImGui::InputInt("Current Map", ¤t_map_); + ImGui::TableNextColumn(); ImGui::SetNextItemWidth(100.f); ImGui::Combo("##world", ¤t_world_, @@ -183,20 +190,29 @@ void OverworldEditor::DrawOverworldMapSettings() { void OverworldEditor::DrawOverworldCanvas() { DrawOverworldMapSettings(); ImGui::Separator(); - overworld_map_canvas_.DrawBackground(); - overworld_map_canvas_.DrawContextMenu(); - if (overworld_.isLoaded()) { - auto map = overworld_.GetOverworldMap(0); - if (map.IsBuilt()) { - if (map.IsLargeMap() && map.IsInitialized()) { - overworld_map_canvas_.DrawBitmap(overworld_map_bmp_, 2); - } else { - overworld_map_canvas_.DrawBitmap(overworld_map_bmp_, 2); + ImGuiID child_id = ImGui::GetID((void *)(intptr_t)7); + if (ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(), true, + ImGuiWindowFlags_AlwaysVerticalScrollbar | + ImGuiWindowFlags_AlwaysHorizontalScrollbar)) { + overworld_map_canvas_.DrawBackground(ImVec2(512 * 8, 512 * 8)); + overworld_map_canvas_.DrawContextMenu(); + if (overworld_.isLoaded()) { + int xx = 0; + int yy = 0; + for (int i = 0; i < 0x40; i++) { + overworld_map_canvas_.DrawBitmap(maps_bmp_[i], (xx * 512), (yy * 512)); + + xx++; + if (xx >= 8) { + yy++; + xx = 0; + } } } + overworld_map_canvas_.DrawGrid(64.f); + overworld_map_canvas_.DrawOverlay(); } - overworld_map_canvas_.DrawGrid(64.f); - overworld_map_canvas_.DrawOverlay(); + ImGui::EndChild(); } void OverworldEditor::DrawTileSelector() { @@ -303,8 +319,6 @@ absl::Status OverworldEditor::DrawOverworldDebugMenu() { overworld_.GetCurrentBlockset()); rom_.RenderBitmap(&tile16_blockset_bmp_); map_blockset_loaded_ = true; - overworld_map_bmp_.Create(512, 512, 512, overworld_.GetCurrentBitmapData()); - rom_.RenderBitmap(&overworld_map_bmp_); } ImGui::End(); diff --git a/src/app/editor/overworld_editor.h b/src/app/editor/overworld_editor.h index f68348a4..c6a39361 100644 --- a/src/app/editor/overworld_editor.h +++ b/src/app/editor/overworld_editor.h @@ -64,6 +64,7 @@ class OverworldEditor { void LoadGraphics(); int current_world_ = 0; + int current_map_ = 0; char map_gfx_[3] = ""; char map_palette_[3] = ""; char spr_gfx_[3] = ""; @@ -86,6 +87,7 @@ class OverworldEditor { std::unordered_map graphics_bin_; std::unordered_map current_graphics_set_; + std::unordered_map maps_bmp_; ROM rom_; zelda3::Overworld overworld_; @@ -94,7 +96,6 @@ class OverworldEditor { gfx::Bitmap tile16_blockset_bmp_; // pointer size 1048576 gfx::Bitmap current_gfx_bmp_; // pointer size 32768 gfx::Bitmap all_gfx_bmp; // pointer size 456704 - gfx::Bitmap overworld_map_bmp_; gui::Canvas overworld_map_canvas_; gui::Canvas current_gfx_canvas_; From 47ca1842923f0ce518c7b92f283ca5eec656f299 Mon Sep 17 00:00:00 2001 From: scawful Date: Fri, 9 Sep 2022 17:10:32 -0500 Subject: [PATCH 14/21] change repeating bytes decompression command --- src/app/rom.cc | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/app/rom.cc b/src/app/rom.cc index 51469bff..4930823d 100644 --- a/src/app/rom.cc +++ b/src/app/rom.cc @@ -528,33 +528,32 @@ absl::StatusOr ROM::Decompress(int offset, int size, int mode) { offset += 1; // Advance 1 byte in the ROM } break; case kCommandRepeatingBytes: { + ushort s1 = ((rom_data_[offset + 1] & kSnesByteMax) << 8); + ushort s2 = ((rom_data_[offset] & kSnesByteMax)); + int addr = (s1 | s2); + if (mode == kNintendoMode1) { // Reversed byte order for overworld maps - auto addr = (rom_data_[offset + 2]) | ((rom_data_[offset + 1]) << 8); - if (addr > offset) { - return absl::InternalError(absl::StrFormat( - "DecompressOverworld: Offset for command copy exceeds " - "current position (Offset : %#04x | Pos : %#06x)\n", - addr, offset)); - } - - if (buffer_pos + length >= size) { - size *= 2; - buffer.resize(size); - } - - memcpy(buffer.data() + buffer_pos, rom_data_.data() + addr, length); - offset += 2; - } else { - ushort s1 = ((rom_data_[offset + 1] & kSnesByteMax) << 8); - ushort s2 = ((rom_data_[offset] & kSnesByteMax)); - auto addr = (s1 | s2); - for (int i = 0; i < length; i++) { - buffer[buffer_pos] = buffer[addr + i]; - buffer_pos++; - } - offset += 2; // Advance 2 bytes in the ROM + addr = (s2 | s1); } + if (addr > offset) { + return absl::InternalError(absl::StrFormat( + "DecompressOverworld: Offset for command copy exceeds " + "current position (Offset : %#04x | Pos : %#06x)\n", + addr, offset)); + } + + if (buffer_pos + length >= size) { + size *= 2; + buffer.resize(size); + } + + for (int i = 0; i < length; i++) { + buffer[buffer_pos] = buffer[addr + i]; + buffer_pos++; + } + offset += 2; // Advance 2 bytes in the ROM + } break; default: { std::cout << absl::StrFormat( From 047dde4e8145019f39cb81f26745dd80f14b3965 Mon Sep 17 00:00:00 2001 From: Justin Scofield <47263509+scawful@users.noreply.github.com> Date: Sat, 10 Sep 2022 09:05:37 -0500 Subject: [PATCH 15/21] add SetPalettecolor routine to Bitmap --- src/app/gfx/bitmap.cc | 6 ++++++ src/app/gfx/bitmap.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/app/gfx/bitmap.cc b/src/app/gfx/bitmap.cc index e1be16f4..db385954 100644 --- a/src/app/gfx/bitmap.cc +++ b/src/app/gfx/bitmap.cc @@ -107,6 +107,12 @@ void Bitmap::ApplyPalette(SNESPalette &palette) { surface_->format->palette = palette.GetSDL_Palette(); } +void Bitmap::SetPaletteColor(int id, gfx::snes_color color) { + surface_->format->palette->colors[id].r = color.red; + surface_->format->palette->colors[id].b = color.blue; + surface_->format->palette->colors[id].g = color.green; +} + // Creates a vector of bitmaps which are individual 8x8 tiles. absl::StatusOr> Bitmap::CreateTiles() { std::vector tiles; diff --git a/src/app/gfx/bitmap.h b/src/app/gfx/bitmap.h index 2afe5b8f..5ca40a6c 100644 --- a/src/app/gfx/bitmap.h +++ b/src/app/gfx/bitmap.h @@ -31,6 +31,7 @@ class Bitmap { void CreateTexture(std::shared_ptr renderer); void ApplyPalette(SNESPalette &palette); + void SetPaletteColor(int id, gfx::snes_color color); absl::StatusOr> CreateTiles(); absl::Status CreateFromTiles(const std::vector &tiles); From 2f9ae83b5744a95ed882ede5ea2457b3e06c4638 Mon Sep 17 00:00:00 2001 From: Justin Scofield <47263509+scawful@users.noreply.github.com> Date: Sat, 10 Sep 2022 09:05:55 -0500 Subject: [PATCH 16/21] cleanup rom and add palette routines --- src/app/rom.cc | 199 +++++++++---------------------------------------- src/app/rom.h | 10 +-- 2 files changed, 40 insertions(+), 169 deletions(-) diff --git a/src/app/rom.cc b/src/app/rom.cc index 4930823d..34c8f918 100644 --- a/src/app/rom.cc +++ b/src/app/rom.cc @@ -533,7 +533,12 @@ absl::StatusOr ROM::Decompress(int offset, int size, int mode) { int addr = (s1 | s2); if (mode == kNintendoMode1) { // Reversed byte order for overworld maps - addr = (s2 | s1); + // addr = (s2 | s1); + addr = (rom_data_[offset + 2]) | ((rom_data_[offset + 1]) << 8); + memcpy(buffer.data() + buffer_pos, rom_data_.data() + offset, length); + buffer_pos += length; + offset += 2; + break; } if (addr > offset) { @@ -577,166 +582,6 @@ absl::StatusOr ROM::DecompressOverworld(int pos, int size) { return Decompress(pos, size, kNintendoMode1); } -absl::StatusOr ROM::CreateAllGfxDataRaw() { - // 0-112 -> compressed 3bpp bgr -> (decompressed each) 0x600 bytes - // 113-114 -> compressed 2bpp -> (decompressed each) 0x800 bytes - // 115-126 -> uncompressed 3bpp sprites -> (each) 0x600 bytes - // 127-217 -> compressed 3bpp sprites -> (decompressed each) 0x600 bytes - // 218-222 -> compressed 2bpp -> (decompressed each) 0x800 bytes - Bytes buffer(0x54A00); - for (int i = 0; i < 0x54A00; ++i) { - buffer.push_back(0x00); - } - int bufferPos = 0; - Bytes data(0x600); - for (int i = 0; i < 0x600; ++i) { - buffer.push_back(0x00); - } - - for (int i = 0; i < 223; i++) { - bool c = true; - if (i >= 0 && i <= 112) // compressed 3bpp bgr - { - isbpp3[i] = true; - } else if (i >= 113 && i <= 114) // compressed 2bpp - { - isbpp3[i] = false; - } else if (i >= 115 && i <= 126) // uncompressed 3bpp sprites - { - isbpp3[i] = true; - c = false; - } else if (i >= 127 && i <= 217) // compressed 3bpp sprites - { - isbpp3[i] = true; - } else if (i >= 218 && i <= 222) // compressed 2bpp - { - isbpp3[i] = false; - } - - if (c) // if data is compressed decompress it - { - auto offset = GetGraphicsAddress(rom_data_.data(), i); - ASSIGN_OR_RETURN(data, Decompress(offset)) - } else { - data.resize(core::Uncompressed3BPPSize); - auto offset = GetGraphicsAddress(rom_data_.data(), i); - for (int j = 0; j < core::Uncompressed3BPPSize; j++) { - data[j] = rom_data_[j + offset]; - } - } - - for (int j = 0; j < data.size(); j++) { - buffer[j + bufferPos] = data[j]; - } - - bufferPos += data.size(); - } - - return buffer; -} - -absl::Status ROM::CreateAllGraphicsData() { - ASSIGN_OR_RETURN(Bytes data, CreateAllGfxDataRaw()) - Bytes newData(0x6F800); - for (int i = 0; i < 0x6F800; i++) { - newData.push_back(0x00); - } - Bytes mask{0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; - int sheetPosition = 0; - - // 8x8 tile - // Per Sheet - for (int s = 0; s < 223; s++) { - // Per Tile Line Y - for (int j = 0; j < 4; j++) { - // Per Tile Line X - for (int i = 0; i < 16; i++) { - // Per Pixel Line - for (int y = 0; y < 8; y++) { - if (isbpp3[s]) { - auto lineBits0 = - data[(y * 2) + (i * 24) + (j * 384) + sheetPosition]; - auto lineBits1 = - data[(y * 2) + (i * 24) + (j * 384) + 1 + sheetPosition]; - auto lineBits2 = - data[(y) + (i * 24) + (j * 384) + 16 + sheetPosition]; - - // Per Pixel X - for (int x = 0; x < 4; x++) { - auto pixdata = 0; - auto pixdata2 = 0; - - if ((lineBits0 & mask[(x * 2)]) == mask[(x * 2)]) { - pixdata += 1; - } - if ((lineBits1 & mask[(x * 2)]) == mask[(x * 2)]) { - pixdata += 2; - } - if ((lineBits2 & mask[(x * 2)]) == mask[(x * 2)]) { - pixdata += 4; - } - - if ((lineBits0 & mask[(x * 2) + 1]) == mask[(x * 2) + 1]) { - pixdata2 += 1; - } - if ((lineBits1 & mask[(x * 2) + 1]) == mask[(x * 2) + 1]) { - pixdata2 += 2; - } - if ((lineBits2 & mask[(x * 2) + 1]) == mask[(x * 2) + 1]) { - pixdata2 += 4; - } - - newData[(y * 64) + (x) + (i * 4) + (j * 512) + (s * 2048)] = - ((pixdata << 4) | pixdata2); - } - } else { - auto lineBits0 = - data[(y * 2) + (i * 16) + (j * 256) + sheetPosition]; - auto lineBits1 = - data[(y * 2) + (i * 16) + (j * 256) + 1 + sheetPosition]; - - // Per Pixel X - for (int x = 0; x < 4; x++) { - auto pixdata = 0; - auto pixdata2 = 0; - - if ((lineBits0 & mask[(x * 2)]) == mask[(x * 2)]) { - pixdata += 1; - } - if ((lineBits1 & mask[(x * 2)]) == mask[(x * 2)]) { - pixdata += 2; - } - - if ((lineBits0 & mask[(x * 2) + 1]) == mask[(x * 2) + 1]) { - pixdata2 += 1; - } - if ((lineBits1 & mask[(x * 2) + 1]) == mask[(x * 2) + 1]) { - pixdata2 += 2; - } - - newData[(y * 64) + (x) + (i * 4) + (j * 512) + (s * 2048)] = - ((pixdata << 4) | pixdata2); - } - } - } - } - } - - if (isbpp3[s]) { - sheetPosition += 0x600; - } else { - sheetPosition += 0x800; - } - } - - graphics_buffer_.reserve(0x6F800); - for (int i = 0; i < 0x6F800; i++) { - graphics_buffer_.push_back(newData[i]); - } - - return absl::OkStatus(); -} - // 0-112 -> compressed 3bpp bgr -> (decompressed each) 0x600 chars // 113-114 -> compressed 2bpp -> (decompressed each) 0x800 chars // 115-126 -> uncompressed 3bpp sprites -> (each) 0x600 chars @@ -770,11 +615,11 @@ absl::Status ROM::LoadAllGraphicsData() { graphics_bin_.at(i).CreateTexture(renderer_); for (int j = 0; j < graphics_bin_.at(i).GetSize(); ++j) { - graphics_8bpp_buffer_.push_back(graphics_bin_.at(i).GetByte(j)); + graphics_buffer_.push_back(graphics_bin_.at(i).GetByte(j)); } } else { for (int j = 0; j < 0x1000; ++j) { - graphics_8bpp_buffer_.push_back(0xFF); + graphics_buffer_.push_back(0xFF); } } } @@ -840,5 +685,33 @@ void ROM::RenderBitmap(gfx::Bitmap* bitmap) const { bitmap->CreateTexture(renderer_); } +gfx::snes_color 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::SNESPalette ROM::ReadPalette(int offset, int num_colors) { + int color_offset = 0; + std::vector colors(num_colors); + + while (color_offset < num_colors) { + 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; + colors[color_offset] = new_color; + color_offset++; + offset += 2; + } + + gfx::SNESPalette palette(colors); + return palette; +} + } // namespace app } // namespace yaze \ No newline at end of file diff --git a/src/app/rom.h b/src/app/rom.h index 5db94a1a..41aaebe9 100644 --- a/src/app/rom.h +++ b/src/app/rom.h @@ -77,22 +77,21 @@ class ROM { absl::StatusOr DecompressOverworld(int pos, int size); absl::Status LoadAllGraphicsData(); - - absl::StatusOr CreateAllGfxDataRaw(); - absl::Status CreateAllGraphicsData(); - absl::Status LoadFromFile(const absl::string_view& filename); absl::Status LoadFromPointer(uchar* data, size_t length); absl::Status LoadFromBytes(const Bytes& data); absl::Status SaveToFile(); + + gfx::snes_color ReadColor(int offset); + gfx::SNESPalette ReadPalette(int offset, int num_colors); + void RenderBitmap(gfx::Bitmap* bitmap) const; auto GetSize() const { return size_; } auto GetTitle() const { return title; } auto GetGraphicsBin() const { return graphics_bin_; } auto GetGraphicsBuffer() const { return graphics_buffer_; } - auto GetGraphics8BPP() const { return graphics_8bpp_buffer_; } void SetupRenderer(std::shared_ptr renderer) { renderer_ = renderer; } @@ -130,7 +129,6 @@ class ROM { Bytes rom_data_; Bytes graphics_buffer_; - Bytes graphics_8bpp_buffer_; std::shared_ptr renderer_; std::unordered_map graphics_bin_; }; From 50b944851c3c1266dd8c1911fabfb8f83e823dc6 Mon Sep 17 00:00:00 2001 From: Justin Scofield <47263509+scawful@users.noreply.github.com> Date: Sat, 10 Sep 2022 09:06:13 -0500 Subject: [PATCH 17/21] remove overworld debug menu --- src/app/editor/master_editor.cc | 3 -- src/app/editor/overworld_editor.cc | 59 ++++++------------------------ src/app/editor/overworld_editor.h | 6 --- 3 files changed, 11 insertions(+), 57 deletions(-) diff --git a/src/app/editor/master_editor.cc b/src/app/editor/master_editor.cc index 6fcb7b6a..e3987b0d 100644 --- a/src/app/editor/master_editor.cc +++ b/src/app/editor/master_editor.cc @@ -236,9 +236,6 @@ void MasterEditor::DrawViewMenu() { ImGui::MenuItem("HEX Editor", nullptr, &show_memory_editor); ImGui::MenuItem("ASM Editor", nullptr, &show_asm_editor); ImGui::MenuItem("ImGui Demo", nullptr, &show_imgui_demo); - if (ImGui::MenuItem("Overworld Debug")) { - overworld_editor_.OverworldDebugMenu(); - } ImGui::Separator(); if (ImGui::BeginMenu("GUI Tools")) { ImGui::MenuItem("Metrics (ImGui)", nullptr, &show_imgui_metrics); diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index a03cd27c..e359d6e9 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -41,13 +41,16 @@ absl::Status OverworldEditor::Update() { if (rom_.isLoaded() && !all_gfx_loaded_) { LoadGraphics(); all_gfx_loaded_ = true; + RETURN_IF_ERROR(overworld_.Load(rom_)) current_gfx_bmp_.Create(128, 512, 64, overworld_.GetCurrentGraphics()); rom_.RenderBitmap(¤t_gfx_bmp_); + tile16_blockset_bmp_.Create(128, 8192, 128, overworld_.GetCurrentBlockset()); rom_.RenderBitmap(&tile16_blockset_bmp_); map_blockset_loaded_ = true; + for (int i = 0; i < core::kNumOverworldMaps; ++i) { overworld_.SetCurrentMap(i); maps_bmp_[i].Create(512, 512, 512, overworld_.GetCurrentBitmapData()); @@ -55,10 +58,6 @@ absl::Status OverworldEditor::Update() { } } - if (overworld_debug_menu_) { - RETURN_IF_ERROR(DrawOverworldDebugMenu()) - } - auto toolset_status = DrawToolset(); RETURN_IF_ERROR(toolset_status) @@ -194,13 +193,14 @@ void OverworldEditor::DrawOverworldCanvas() { if (ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar)) { - overworld_map_canvas_.DrawBackground(ImVec2(512 * 8, 512 * 8)); + overworld_map_canvas_.DrawBackground(ImVec2(0x200 * 8, 0x200 * 8)); overworld_map_canvas_.DrawContextMenu(); if (overworld_.isLoaded()) { int xx = 0; int yy = 0; for (int i = 0; i < 0x40; i++) { - overworld_map_canvas_.DrawBitmap(maps_bmp_[i], (xx * 512), (yy * 512)); + overworld_map_canvas_.DrawBitmap(maps_bmp_[i + (current_world_ * 0x40)], + (xx * 0x200), (yy * 0x200)); xx++; if (xx >= 8) { @@ -249,7 +249,7 @@ void OverworldEditor::DrawTileSelector() { } void OverworldEditor::DrawTile16Selector() { - blockset_canvas_.DrawBackground(ImVec2(256 + 1, (8192 * 2) + 1)); + blockset_canvas_.DrawBackground(ImVec2(0x100 + 1, (8192 * 2) + 1)); blockset_canvas_.DrawContextMenu(); if (map_blockset_loaded_) { blockset_canvas_.DrawBitmap(tile16_blockset_bmp_, 2); @@ -260,19 +260,19 @@ void OverworldEditor::DrawTile16Selector() { void OverworldEditor::DrawTile8Selector() { graphics_bin_canvas_.DrawBackground( - ImVec2(256 + 1, kNumSheetsToLoad * 64 + 1)); + ImVec2(0x100 + 1, kNumSheetsToLoad * 0x40 + 1)); graphics_bin_canvas_.DrawContextMenu(); if (all_gfx_loaded_) { for (const auto &[key, value] : graphics_bin_) { - int offset = 64 * (key + 1); + int offset = 0x40 * (key + 1); int top_left_y = graphics_bin_canvas_.GetZeroPoint().y + 2; if (key >= 1) { - top_left_y = graphics_bin_canvas_.GetZeroPoint().y + 64 * key; + top_left_y = graphics_bin_canvas_.GetZeroPoint().y + 0x40 * key; } graphics_bin_canvas_.GetDrawList()->AddImage( (void *)value.GetTexture(), ImVec2(graphics_bin_canvas_.GetZeroPoint().x + 2, top_left_y), - ImVec2(graphics_bin_canvas_.GetZeroPoint().x + 256, + ImVec2(graphics_bin_canvas_.GetZeroPoint().x + 0x100, graphics_bin_canvas_.GetZeroPoint().y + offset)); } } @@ -282,49 +282,14 @@ void OverworldEditor::DrawTile8Selector() { void OverworldEditor::DrawAreaGraphics() { if (overworld_.isLoaded()) { - static bool set_loaded = false; - if (!set_loaded) { - current_graphics_set_ = - overworld_.GetOverworldMap(0).GetCurrentGraphicsSet(); - set_loaded = true; - } current_gfx_canvas_.DrawBackground(ImVec2(256 + 1, 16 * 64 + 1)); current_gfx_canvas_.DrawContextMenu(); current_gfx_canvas_.DrawBitmap(current_gfx_bmp_); - // for (const auto &[key, value] : current_graphics_set_) { - // int offset = 64 * (key + 1); - // int top_left_y = current_gfx_canvas_.GetZeroPoint().y + 2; - // if (key >= 1) { - // top_left_y = current_gfx_canvas_.GetZeroPoint().y + 64 * key; - // } - // current_gfx_canvas_.GetDrawList()->AddImage( - // (void *)value.GetTexture(), - // ImVec2(current_gfx_canvas_.GetZeroPoint().x + 2, top_left_y), - // ImVec2(current_gfx_canvas_.GetZeroPoint().x + 256, - // current_gfx_canvas_.GetZeroPoint().y + offset)); - // } current_gfx_canvas_.DrawGrid(32.0f); current_gfx_canvas_.DrawOverlay(); } } -absl::Status OverworldEditor::DrawOverworldDebugMenu() { - ImGui::Begin("Overworld Debug Menu"); - - if (ImGui::Button("Load Overworld")) { - RETURN_IF_ERROR(overworld_.Load(rom_)) - current_gfx_bmp_.Create(128, 512, 64, overworld_.GetCurrentGraphics()); - rom_.RenderBitmap(¤t_gfx_bmp_); - tile16_blockset_bmp_.Create(128, 8192, 128, - overworld_.GetCurrentBlockset()); - rom_.RenderBitmap(&tile16_blockset_bmp_); - map_blockset_loaded_ = true; - } - - ImGui::End(); - return absl::OkStatus(); -} - void OverworldEditor::LoadGraphics() { for (int i = 0; i < 8; i++) { current_palette_[i].x = (i * 0.21f); @@ -335,8 +300,6 @@ void OverworldEditor::LoadGraphics() { PRINT_IF_ERROR(rom_.LoadAllGraphicsData()) graphics_bin_ = rom_.GetGraphicsBin(); - - PRINT_IF_ERROR(rom_.CreateAllGraphicsData()) } } // namespace editor diff --git a/src/app/editor/overworld_editor.h b/src/app/editor/overworld_editor.h index c6a39361..cd12e4e0 100644 --- a/src/app/editor/overworld_editor.h +++ b/src/app/editor/overworld_editor.h @@ -48,8 +48,6 @@ class OverworldEditor { absl::Status Copy() { return absl::UnimplementedError("Copy"); } absl::Status Paste() { return absl::UnimplementedError("Paste"); } - void OverworldDebugMenu() { overworld_debug_menu_ = true; } - private: absl::Status DrawToolset(); void DrawOverworldMapSettings(); @@ -58,9 +56,6 @@ class OverworldEditor { void DrawTile16Selector(); void DrawTile8Selector(); void DrawAreaGraphics(); - - absl::Status DrawOverworldDebugMenu(); - void LoadGraphics(); int current_world_ = 0; @@ -75,7 +70,6 @@ class OverworldEditor { bool opt_enable_grid = true; bool all_gfx_loaded_ = false; bool map_blockset_loaded_ = false; - bool overworld_debug_menu_ = false; ImVec4 current_palette_[8]; From 51fdb0603f917b379203531ec1021232d4b977be Mon Sep 17 00:00:00 2001 From: Justin Scofield <47263509+scawful@users.noreply.github.com> Date: Sat, 10 Sep 2022 09:06:31 -0500 Subject: [PATCH 18/21] snes_palette improvements --- src/app/gfx/snes_palette.cc | 16 +++++++++++++--- src/app/gfx/snes_palette.h | 4 ++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/app/gfx/snes_palette.cc b/src/app/gfx/snes_palette.cc index e88a8b2c..625e1918 100644 --- a/src/app/gfx/snes_palette.cc +++ b/src/app/gfx/snes_palette.cc @@ -81,6 +81,10 @@ void SNESColor::setRgb(ImVec4 val) { snes = ConvertRGBtoSNES(col); } +void SNESColor::setRgb(snes_color val) { + snes = ConvertRGBtoSNES(val); +} + void SNESColor::setSNES(uint16_t val) { snes = val; snes_color col = ConvertSNEStoRGB(val); @@ -130,6 +134,15 @@ SNESPalette::SNESPalette(const std::vector& cols) { size_ = cols.size(); } +SNESPalette::SNESPalette(const std::vector& cols) { + for (const auto& each : cols) { + SNESColor scol; + scol.setRgb(each); + colors.push_back(scol); + } + size_ = cols.size(); +} + char* SNESPalette::encode() { auto data = new char[size_ * 2]; for (unsigned int i = 0; i < size_; i++) { @@ -141,7 +154,6 @@ char* SNESPalette::encode() { } SDL_Palette* SNESPalette::GetSDL_Palette() { - std::cout << "Converting SNESPalette to SDL_Palette" << std::endl; auto sdl_palette = std::make_shared(); sdl_palette->ncolors = size_; @@ -154,8 +166,6 @@ SDL_Palette* SNESPalette::GetSDL_Palette() { << " G:" << color[i].g << " B:" << color[i].b << ")" << std::endl; } sdl_palette->colors = color.data(); - colors_.push_back(color); - return sdl_palette.get(); } diff --git a/src/app/gfx/snes_palette.h b/src/app/gfx/snes_palette.h index d25a418a..bd0cdf71 100644 --- a/src/app/gfx/snes_palette.h +++ b/src/app/gfx/snes_palette.h @@ -43,6 +43,7 @@ struct SNESColor { uint16_t snes = 0; ImVec4 rgb; void setRgb(ImVec4); + void setRgb(snes_color); void setSNES(uint16_t); }; @@ -53,14 +54,13 @@ class SNESPalette { explicit SNESPalette(char* snesPal); explicit SNESPalette(const unsigned char* snes_pal); explicit SNESPalette(const std::vector&); + explicit SNESPalette(const std::vector&); char* encode(); SDL_Palette* GetSDL_Palette(); int size_ = 0; std::vector colors; - std::vector colors_arrays_; - std::vector> colors_; }; } // namespace gfx From 2ac0c25ac87620ec40025e86e7324821ba362ac9 Mon Sep 17 00:00:00 2001 From: Justin Scofield <47263509+scawful@users.noreply.github.com> Date: Sat, 10 Sep 2022 09:06:43 -0500 Subject: [PATCH 19/21] add DrawOutline to bitmap --- src/gui/canvas.cc | 17 +++++++++++++---- src/gui/canvas.h | 1 + 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/gui/canvas.cc b/src/gui/canvas.cc index c6e52d93..326dd88e 100644 --- a/src/gui/canvas.cc +++ b/src/gui/canvas.cc @@ -60,6 +60,7 @@ void Canvas::DrawContextMenu() { ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right); if (enable_context_menu_ && drag_delta.x == 0.0f && drag_delta.y == 0.0f) ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight); + if (ImGui::BeginPopup("context")) { if (dragging_select_) points_.resize(points_.size() - 2); dragging_select_ = false; @@ -79,10 +80,18 @@ void Canvas::DrawBitmap(const Bitmap &bitmap, int border_offset) { } void Canvas::DrawBitmap(const Bitmap &bitmap, int x_offset, int y_offset) { - draw_list_->AddImage((void *)bitmap.GetTexture(), - ImVec2(canvas_p0_.x + x_offset, canvas_p0_.y + y_offset), - ImVec2(canvas_p0_.x + x_offset + (bitmap.GetWidth()), - canvas_p0_.y + y_offset + (bitmap.GetHeight()))); + draw_list_->AddImage( + (void *)bitmap.GetTexture(), + ImVec2(canvas_p0_.x + x_offset + scrolling_.x, + canvas_p0_.y + y_offset + scrolling_.y), + ImVec2(canvas_p0_.x + x_offset + scrolling_.x + (bitmap.GetWidth()), + canvas_p0_.y + y_offset + scrolling_.y + (bitmap.GetHeight()))); +} + +void Canvas::DrawOutline(int x, int y, int w, int h) { + ImVec2 origin(x, y); + ImVec2 size(x + w, y + h); + draw_list_->AddRect(origin, size, IM_COL32(255, 255, 255, 255)); } void Canvas::DrawGrid(float grid_step) { diff --git a/src/gui/canvas.h b/src/gui/canvas.h index bb13c72c..1c1bc1f6 100644 --- a/src/gui/canvas.h +++ b/src/gui/canvas.h @@ -24,6 +24,7 @@ class Canvas { void DrawBitmap(const Bitmap& bitmap, int border_offset = 0); void DrawBitmap(const Bitmap& bitmap, int x_offset, int y_offset); // void DrawLargeBitmap(const Bitmap& tl, const Bitmap& tr, const Bitmap& bl, const Bitmap& br); + void DrawOutline(int x, int y, int w, int h); void DrawGrid(float grid_step = 64.0f); void DrawOverlay(); // last 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 20/21] 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 From 1244e6855c49fd8548c2860097cba1eafecea222 Mon Sep 17 00:00:00 2001 From: scawful Date: Sat, 10 Sep 2022 16:33:59 -0500 Subject: [PATCH 21/21] palettes and overworld drawing --- src/app/core/controller.cc | 3 ++ src/app/editor/overworld_editor.cc | 70 ++++++++++++++++------------ src/app/editor/overworld_editor.h | 6 ++- src/app/gfx/bitmap.cc | 14 +++--- src/app/gfx/bitmap.h | 4 +- src/app/gfx/snes_palette.cc | 20 ++++---- src/app/gfx/snes_palette.h | 21 +++++++-- src/app/rom.cc | 75 ++++++++++++++++-------------- src/app/rom.h | 3 +- src/app/zelda3/overworld_map.cc | 75 +++++++++++++----------------- src/app/zelda3/overworld_map.h | 1 - src/app/zelda3/palettes.h | 45 ------------------ src/gui/canvas.cc | 19 ++++---- src/gui/canvas.h | 2 - 14 files changed, 168 insertions(+), 190 deletions(-) delete mode 100644 src/app/zelda3/palettes.h diff --git a/src/app/core/controller.cc b/src/app/core/controller.cc index 9f4c884a..687d663f 100644 --- a/src/app/core/controller.cc +++ b/src/app/core/controller.cc @@ -23,6 +23,7 @@ namespace { void InitializeKeymap() { ImGuiIO &io = ImGui::GetIO(); io.KeyMap[ImGuiKey_Backspace] = SDL_GetScancodeFromKey(SDLK_BACKSPACE); + io.KeyMap[ImGuiKey_LeftShift] = SDL_GetScancodeFromKey(SDLK_LSHIFT); io.KeyMap[ImGuiKey_Enter] = SDL_GetScancodeFromKey(SDLK_RETURN); io.KeyMap[ImGuiKey_UpArrow] = SDL_GetScancodeFromKey(SDLK_UP); io.KeyMap[ImGuiKey_DownArrow] = SDL_GetScancodeFromKey(SDLK_DOWN); @@ -37,6 +38,8 @@ void HandleKeyDown(SDL_Event &event) { case SDLK_DOWN: case SDLK_RETURN: case SDLK_BACKSPACE: + case SDLK_LSHIFT: + case SDLK_LCTRL: case SDLK_TAB: io.KeysDown[event.key.keysym.scancode] = (event.type == SDL_KEYDOWN); break; diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index 94f4852e..86083c2b 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -16,25 +16,26 @@ #include "gui/canvas.h" #include "gui/icons.h" -/** - * Drawing the Overworld - * Tips by Zarby - * - * 1) Find the graphics pointers (constants.h) - * 2) Convert the 3bpp SNES data into PC 4bpp (Hard) - * 3) Get the tiles32 data - * 4) Get the tiles16 data - * 5) Get the map32 data using lz2 variant decompression - * 6) Get the graphics data of the map - * 7) Load 4bpp into Pseudo VRAM for rendering tiles to screen - * 8) Render the tiles to a bitmap with a B&W palette to start - * 9) Get the palette data and find how it's loaded in game - * - */ namespace yaze { namespace app { namespace editor { +namespace { +void UpdateSelectedTile16(int selected, gfx::Bitmap &tile16_blockset, + gfx::Bitmap &selected_tile) { + auto blockset = tile16_blockset.GetData(); + auto bitmap = selected_tile.GetData(); + + int src_pos = ((selected - ((selected / 0x08) * 0x08)) * 0x10) + + ((selected / 0x08) * 2048); + for (int yy = 0; yy < 0x10; yy++) { + for (int xx = 0; xx < 0x10; xx++) { + bitmap[xx + (yy * 0x10)] = blockset[src_pos + xx + (yy * 0x80)]; + } + } +} +} // namespace + void OverworldEditor::SetupROM(ROM &rom) { rom_ = rom; } absl::Status OverworldEditor::Update() { @@ -46,20 +47,40 @@ absl::Status OverworldEditor::Update() { current_gfx_bmp_.Create(128, 512, 64, overworld_.GetCurrentGraphics()); rom_.RenderBitmap(¤t_gfx_bmp_); + auto tile16_palette = overworld_.GetCurrentPalette(); tile16_blockset_bmp_.Create(128, 8192, 128, overworld_.GetCurrentBlockset()); + for (int j = 0; j < tile16_palette.colors.size(); j++) { + tile16_blockset_bmp_.SetPaletteColor(j, tile16_palette.GetColor(j)); + } rom_.RenderBitmap(&tile16_blockset_bmp_); map_blockset_loaded_ = true; - + 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); + for (int j = 0; j < palette.colors.size(); j++) { + maps_bmp_[i].SetPaletteColor(j, palette.GetColor(j)); + } rom_.RenderBitmap(&(maps_bmp_[i])); } } + if (update_selected_tile_ && all_gfx_loaded_) { + if (!selected_tile_loaded_) { + selected_tile_bmp_.Create(16, 16, 64, 256); + } + UpdateSelectedTile16(selected_tile_, tile16_blockset_bmp_, + selected_tile_bmp_); + auto palette = overworld_.GetCurrentPalette(); + for (int j = 0; j < palette.colors.size(); j++) { + selected_tile_bmp_.SetPaletteColor(j, palette.GetColor(j)); + } + rom_.RenderBitmap(&selected_tile_bmp_); + update_selected_tile_ = false; + } + auto toolset_status = DrawToolset(); RETURN_IF_ERROR(toolset_status) @@ -81,7 +102,7 @@ absl::Status OverworldEditor::Update() { } absl::Status OverworldEditor::DrawToolset() { - if (ImGui::BeginTable("OWToolset", 17, toolset_table_flags, ImVec2(0, 0))) { + if (ImGui::BeginTable("OWToolset", 15, toolset_table_flags, ImVec2(0, 0))) { for (const auto &name : kToolsetColumnNames) ImGui::TableSetupColumn(name.data()); @@ -119,19 +140,6 @@ absl::Status OverworldEditor::DrawToolset() { // Music ImGui::TableNextColumn(); ImGui::Button(ICON_MD_MUSIC_NOTE); - ImGui::TableNextColumn(); - ImGui::Text(ICON_MD_MORE_VERT); - - ImGui::TableNextColumn(); - ImGui::Text("Palette:"); - for (int i = 0; i < 8; i++) { - std::string id = "##PaletteColor" + std::to_string(i); - ImGui::SameLine(); - ImGui::ColorEdit4(id.c_str(), ¤t_palette_[i].x, - ImGuiColorEditFlags_NoInputs | - ImGuiColorEditFlags_DisplayRGB | - ImGuiColorEditFlags_DisplayHex); - } ImGui::EndTable(); } diff --git a/src/app/editor/overworld_editor.h b/src/app/editor/overworld_editor.h index cd12e4e0..16471469 100644 --- a/src/app/editor/overworld_editor.h +++ b/src/app/editor/overworld_editor.h @@ -32,7 +32,7 @@ static constexpr absl::string_view kToolsetColumnNames[] = { "#undoTool", "#redoTool", "#drawTool", "#separator2", "#zoomOutTool", "#zoomInTool", "#separator", "#history", "#entranceTool", "#exitTool", "#itemTool", "#spriteTool", - "#transportTool", "#musicTool", "#separator3", "#reloadTool"}; + "#transportTool", "#musicTool" }; static constexpr absl::string_view kOverworldSettingsColumnNames[] = { "##1stCol", "##gfxCol", "##palCol", "##sprgfxCol", @@ -60,6 +60,7 @@ class OverworldEditor { int current_world_ = 0; int current_map_ = 0; + int selected_tile_ = 0; char map_gfx_[3] = ""; char map_palette_[3] = ""; char spr_gfx_[3] = ""; @@ -70,6 +71,8 @@ class OverworldEditor { bool opt_enable_grid = true; bool all_gfx_loaded_ = false; bool map_blockset_loaded_ = false; + bool selected_tile_loaded_ = false; + bool update_selected_tile_ = true; ImVec4 current_palette_[8]; @@ -90,6 +93,7 @@ class OverworldEditor { gfx::Bitmap tile16_blockset_bmp_; // pointer size 1048576 gfx::Bitmap current_gfx_bmp_; // pointer size 32768 gfx::Bitmap all_gfx_bmp; // pointer size 456704 + gfx::Bitmap selected_tile_bmp_; gui::Canvas overworld_map_canvas_; gui::Canvas current_gfx_canvas_; diff --git a/src/app/gfx/bitmap.cc b/src/app/gfx/bitmap.cc index e23c02eb..58844d18 100644 --- a/src/app/gfx/bitmap.cc +++ b/src/app/gfx/bitmap.cc @@ -103,15 +103,17 @@ void Bitmap::CreateTexture(std::shared_ptr renderer) { } // Convert SNESPalette to SDL_Palette for surface. -void Bitmap::ApplyPalette(SNESPalette palette) { +void Bitmap::ApplyPalette(const SNESPalette & palette) { palette_ = palette; - surface_->format->palette = palette_.GetSDL_Palette(); + SDL_SetPaletteColors(surface_->format->palette, + palette_.GetSDL_Palette()->colors, + 0, 256); } -void Bitmap::SetPaletteColor(int id, gfx::snes_color color) { - surface_->format->palette->colors[id].r = color.red; - surface_->format->palette->colors[id].b = color.blue; - surface_->format->palette->colors[id].g = color.green; +void Bitmap::SetPaletteColor(int id, gfx::SNESColor color) { + surface_->format->palette->colors[id].r = color.rgb.x; + surface_->format->palette->colors[id].g = color.rgb.y; + surface_->format->palette->colors[id].b = color.rgb.z; } // Creates a vector of bitmaps which are individual 8x8 tiles. diff --git a/src/app/gfx/bitmap.h b/src/app/gfx/bitmap.h index 4448b74f..43588e65 100644 --- a/src/app/gfx/bitmap.h +++ b/src/app/gfx/bitmap.h @@ -30,8 +30,8 @@ class Bitmap { void CreateTexture(std::shared_ptr renderer); - void ApplyPalette(SNESPalette palette); - void SetPaletteColor(int id, gfx::snes_color color); + void ApplyPalette(const SNESPalette &palette); + void SetPaletteColor(int id, gfx::SNESColor color); absl::StatusOr> CreateTiles(); absl::Status CreateFromTiles(const std::vector &tiles); diff --git a/src/app/gfx/snes_palette.cc b/src/app/gfx/snes_palette.cc index 64ac407e..c3fad32a 100644 --- a/src/app/gfx/snes_palette.cc +++ b/src/app/gfx/snes_palette.cc @@ -64,7 +64,11 @@ 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(snes_color val) { + rgb.x = val.red; + rgb.y = val.blue; + rgb.z = val.green; +} SNESColor::SNESColor(ImVec4 val) : rgb(val) { snes_color col; @@ -83,7 +87,9 @@ void SNESColor::setRgb(ImVec4 val) { snes = ConvertRGBtoSNES(col); } -void SNESColor::setRgb(snes_color val) { snes = ConvertRGBtoSNES(val); } +void SNESColor::setSNES(snes_color val) { + rgb = ImVec4(val.red, val.green, val.blue, 1.f); +} void SNESColor::setSNES(uint16_t val) { snes = val; @@ -137,7 +143,7 @@ SNESPalette::SNESPalette(const std::vector& cols) { SNESPalette::SNESPalette(const std::vector& cols) { for (const auto& each : cols) { SNESColor scol; - scol.setRgb(each); + scol.setSNES(each); colors.push_back(scol); } size_ = cols.size(); @@ -151,7 +157,7 @@ SNESPalette::SNESPalette(const std::vector& cols) { } void SNESPalette::Create(const std::vector& cols) { - for (const auto& each : cols) { + for (const auto each : cols) { colors.push_back(each); } size_ = cols.size(); @@ -176,6 +182,7 @@ SDL_Palette* SNESPalette::GetSDL_Palette() { color[i].r = (uint8_t)colors[i].rgb.x * 100; color[i].g = (uint8_t)colors[i].rgb.y * 100; color[i].b = (uint8_t)colors[i].rgb.z * 100; + color[i].a = 0; std::cout << "Color " << i << " added (R:" << color[i].r << " G:" << color[i].g << " B:" << color[i].b << ")" << std::endl; } @@ -183,10 +190,7 @@ SDL_Palette* SNESPalette::GetSDL_Palette() { return sdl_palette.get(); } -PaletteGroup::PaletteGroup(uint8_t mSize) { - size = mSize; - palettes.reserve(size); -} +PaletteGroup::PaletteGroup(uint8_t mSize) : size(mSize) {} } // namespace gfx } // namespace app diff --git a/src/app/gfx/snes_palette.h b/src/app/gfx/snes_palette.h index 8bd4332b..bee951a9 100644 --- a/src/app/gfx/snes_palette.h +++ b/src/app/gfx/snes_palette.h @@ -41,11 +41,13 @@ struct SNESColor { SNESColor(); explicit SNESColor(ImVec4); explicit SNESColor(snes_color); + + void setRgb(ImVec4); + void setSNES(snes_color); + void setSNES(uint16_t); + uint16_t snes = 0; ImVec4 rgb; - void setRgb(ImVec4); - void setRgb(snes_color); - void setSNES(uint16_t); }; class SNESPalette { @@ -59,7 +61,7 @@ class SNESPalette { explicit SNESPalette(const std::vector&); void Create(const std::vector&); - + void AddColor(SNESColor color) { colors.push_back(color); } auto GetColor(int i) const { return colors[i]; } SNESColor operator[](int i) { @@ -80,6 +82,17 @@ class SNESPalette { struct PaletteGroup { PaletteGroup() = default; explicit PaletteGroup(uint8_t mSize); + void AddPalette(SNESPalette pal) { + palettes.emplace_back(pal); + size = palettes.size(); + } + void AddColor(SNESColor color) { + if (size == 0) { + SNESPalette empty_pal; + palettes.emplace_back(empty_pal); + } + palettes[0].AddColor(color); + } SNESPalette operator[](int i) { if (i > size) { std::cout << "PaletteGroup: Index out of bounds" << std::endl; diff --git a/src/app/rom.cc b/src/app/rom.cc index 36992d92..8b67fa68 100644 --- a/src/app/rom.cc +++ b/src/app/rom.cc @@ -19,7 +19,6 @@ #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 @@ -535,8 +534,8 @@ absl::StatusOr ROM::Decompress(int offset, int size, int mode) { if (mode == kNintendoMode1) { // Reversed byte order for overworld maps // addr = (s2 | s1); - addr = (rom_data_[offset + 2]) | ((rom_data_[offset + 1]) << 8); - memcpy(buffer.data() + buffer_pos, rom_data_.data() + offset, length); + addr = (rom_data_[offset + 1]) | ((rom_data_[offset]) << 8); + memcpy(buffer.data() + buffer_pos, buffer.data() + addr, length); buffer_pos += length; offset += 2; break; @@ -699,7 +698,7 @@ gfx::SNESColor ROM::ReadColor(int offset) { gfx::SNESPalette ROM::ReadPalette(int offset, int num_colors) { int color_offset = 0; - std::vector colors(num_colors); + std::vector colors(num_colors); while (color_offset < num_colors) { short color = (short)((rom_data_[offset + 1] << 8) + rom_data_[offset]); @@ -707,7 +706,7 @@ gfx::SNESPalette ROM::ReadPalette(int offset, int num_colors) { new_color.red = (color & 0x1F) * 8; new_color.green = ((color >> 5) & 0x1F) * 8; new_color.blue = ((color >> 10) & 0x1F) * 8; - colors[color_offset] = new_color; + colors[color_offset].setSNES(new_color); color_offset++; offset += 2; } @@ -719,66 +718,70 @@ gfx::SNESPalette ROM::ReadPalette(int offset, int num_colors) { 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); + palette_groups_["ow_main"].AddPalette( + 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); + palette_groups_["ow_aux"].AddPalette( + 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); + palette_groups_["ow_animated"].AddPalette( + 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); + palette_groups_["hud"].AddPalette( + ReadPalette(core::hudPalettes + (i * 64), 32)); } - zelda3::globalSprite_Palettes[0] = - ReadPalette(core::globalSpritePalettesLW, 60); - zelda3::globalSprite_Palettes[1] = - ReadPalette(core::globalSpritePalettesDW, 60); + palette_groups_["global_sprites"].AddPalette( + ReadPalette(core::globalSpritePalettesLW, 60)); + palette_groups_["global_sprites"].AddPalette( + ReadPalette(core::globalSpritePalettesDW, 60)); + for (int i = 0; i < 5; i++) { - zelda3::armors_Palettes[i] = - ReadPalette(core::armorPalettes + (i * 30), 15); + palette_groups_["armors"].AddPalette( + ReadPalette(core::armorPalettes + (i * 30), 15)); } for (int i = 0; i < 4; i++) { - zelda3::swords_Palettes[i] = ReadPalette(core::swordPalettes + (i * 6), 3); + palette_groups_["swords"].AddPalette( + ReadPalette(core::swordPalettes + (i * 6), 3)); } for (int i = 0; i < 3; i++) { - zelda3::shields_Palettes[i] = - ReadPalette(core::shieldPalettes + (i * 8), 4); + palette_groups_["shields"].AddPalette( + ReadPalette(core::shieldPalettes + (i * 8), 4)); } for (int i = 0; i < 12; i++) { - zelda3::spritesAux1_Palettes[i] = - ReadPalette(core::spritePalettesAux1 + (i * 14), 7); + palette_groups_["sprites_aux1"].AddPalette( + ReadPalette(core::spritePalettesAux1 + (i * 14), 7)); } for (int i = 0; i < 11; i++) { - zelda3::spritesAux2_Palettes[i] = - ReadPalette(core::spritePalettesAux2 + (i * 14), 7); + palette_groups_["sprites_aux2"].AddPalette( + ReadPalette(core::spritePalettesAux2 + (i * 14), 7)); } for (int i = 0; i < 24; i++) { - zelda3::spritesAux3_Palettes[i] = - ReadPalette(core::spritePalettesAux3 + (i * 14), 7); + palette_groups_["sprites_aux3"].AddPalette( + ReadPalette(core::spritePalettesAux3 + (i * 14), 7)); } for (int i = 0; i < 20; i++) { - zelda3::dungeonsMain_Palettes[i] = - ReadPalette(core::dungeonMainPalettes + (i * 180), 90); + palette_groups_["dungeon_main"].AddPalette( + 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); + palette_groups_["grass"].AddColor(ReadColor(core::hardcodedGrassLW)); + palette_groups_["grass"].AddColor(ReadColor(core::hardcodedGrassDW)); + palette_groups_["grass"].AddColor(ReadColor(core::hardcodedGrassSpecial)); - zelda3::object3D_Palettes[0] = ReadPalette(core::triforcePalette, 8); - zelda3::object3D_Palettes[1] = ReadPalette(core::crystalPalette, 8); + palette_groups_["3d_object"].AddPalette( + ReadPalette(core::triforcePalette, 8)); + palette_groups_["3d_object"].AddPalette(ReadPalette(core::crystalPalette, 8)); for (int i = 0; i < 2; i++) { - zelda3::overworld_Mini_Map_Palettes[i] = - ReadPalette(core::overworldMiniMapPalettes + (i * 256), 128); + palette_groups_["ow_mini_map"].AddPalette( + ReadPalette(core::overworldMiniMapPalettes + (i * 256), 128)); } // TODO: check for the paletts in the empty bank space that kan will allocate diff --git a/src/app/rom.h b/src/app/rom.h index aa490797..5f2b79ba 100644 --- a/src/app/rom.h +++ b/src/app/rom.h @@ -20,7 +20,6 @@ #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) @@ -94,6 +93,7 @@ class ROM { auto GetTitle() const { return title; } auto GetGraphicsBin() const { return graphics_bin_; } auto GetGraphicsBuffer() const { return graphics_buffer_; } + auto GetPaletteGroup(std::string group) { return palette_groups_[group]; } void SetupRenderer(std::shared_ptr renderer) { renderer_ = renderer; } @@ -133,6 +133,7 @@ class ROM { Bytes graphics_buffer_; std::shared_ptr renderer_; std::unordered_map graphics_bin_; + std::unordered_map palette_groups_; }; } // namespace app diff --git a/src/app/zelda3/overworld_map.cc b/src/app/zelda3/overworld_map.cc index 6a91bb88..85283d92 100644 --- a/src/app/zelda3/overworld_map.cc +++ b/src/app/zelda3/overworld_map.cc @@ -31,11 +31,11 @@ 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) { +void SetColorsPalette(ROM& rom, 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 @@ -88,7 +88,7 @@ void SetColorsPalette(int index, gfx::SNESPalette& current, gfx::SNESPalette mai 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++]; + new_palette[x + (16 * y)] = rom.GetPaletteGroup("sprites_aux1")[1][k++]; } } @@ -96,7 +96,7 @@ void SetColorsPalette(int index, gfx::SNESPalette& current, gfx::SNESPalette mai 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++]; + new_palette[x + (16 * y)] = rom.GetPaletteGroup("sprites_aux3")[0][k++]; } } @@ -104,7 +104,7 @@ void SetColorsPalette(int index, gfx::SNESPalette& current, gfx::SNESPalette mai 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++]; + new_palette[x + (16 * y)] = rom.GetPaletteGroup("global_sprites")[0][k++]; } } @@ -128,7 +128,7 @@ void SetColorsPalette(int index, gfx::SNESPalette& current, gfx::SNESPalette mai 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++]; + new_palette[x + (16 * y)] = rom.GetPaletteGroup("armors")[0][k++]; } } @@ -345,8 +345,14 @@ void OverworldMap::LoadPalette() { 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]; + gfx::SNESPalette aux1; + gfx::SNESPalette aux2; + gfx::SNESPalette main; + gfx::SNESPalette animated; + gfx::SNESPalette hud; + gfx::SNESPalette spr; + gfx::SNESPalette spr2; + gfx::SNESColor bgr = rom_.GetPaletteGroup("grass")[0].GetColor(0); if (pal1 == 255) { pal1 = rom_[core::overworldMapPaletteGroup + (previousPalId * 4)]; @@ -356,9 +362,9 @@ void OverworldMap::LoadPalette() { pal1 = 19; } - aux1 = overworld_AuxPalettes[pal1]; + aux1 = rom_.GetPaletteGroup("ow_aux")[pal1]; } else { - aux1 = overworld_AuxPalettes[0]; + aux1 = rom_.GetPaletteGroup("ow_aux")[0]; } if (pal2 == 255) { @@ -369,9 +375,9 @@ void OverworldMap::LoadPalette() { pal2 = 19; } - aux2 = overworld_AuxPalettes[pal2]; + aux2 = rom_.GetPaletteGroup("ow_aux")[pal2]; } else { - aux2 = overworld_AuxPalettes[0]; + aux2 = rom_.GetPaletteGroup("ow_aux")[0]; } if (pal3 == 255) { @@ -382,37 +388,20 @@ void OverworldMap::LoadPalette() { // 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]; - // } - + bgr = rom_.GetPaletteGroup("grass")[0].GetColor(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]; - // } + bgr = rom_.GetPaletteGroup("grass")[0].GetColor(2); } if (parent_ == 0x88) { @@ -420,17 +409,17 @@ void OverworldMap::LoadPalette() { } if (pal0 != 255) { - main = overworld_MainPalettes[pal0]; + main = rom_.GetPaletteGroup("ow_main")[pal0]; } else { - main = overworld_MainPalettes[0]; + main = rom_.GetPaletteGroup("ow_main")[0]; } if (pal3 >= 14) { pal3 = 13; } - animated = overworld_AnimatedPalettes[(pal3)]; + animated = rom_.GetPaletteGroup("ow_animated")[(pal3)]; - hud = HudPalettes[0]; + hud = rom_.GetPaletteGroup("hud")[0]; if (pal4 == 255) { pal4 = rom_[core::overworldSpritePaletteGroup + (previousSprPalId * 2)]; // spr3 @@ -441,7 +430,7 @@ void OverworldMap::LoadPalette() { if (pal4 >= 24) { pal4 = 23; } - spr = spritesAux3_Palettes[pal4]; + spr = rom_.GetPaletteGroup("sprites_aux3")[pal4]; if (pal5 == 255) { pal5 = rom_[core::overworldSpritePaletteGroup + (previousSprPalId * 2) + @@ -453,9 +442,10 @@ void OverworldMap::LoadPalette() { if (pal5 >= 24) { pal5 = 23; } - spr2 = spritesAux3_Palettes[pal5]; + spr2 = rom_.GetPaletteGroup("sprites_aux3")[pal5]; - SetColorsPalette(parent_, current_palette_, main, animated, aux1, aux2, hud, bgr, spr, spr2); + SetColorsPalette(rom_, parent_, current_palette_, main, animated, aux1, aux2, + hud, bgr, spr, spr2); } absl::Status OverworldMap::BuildTileset() { @@ -505,7 +495,8 @@ absl::Status OverworldMap::BuildTiles16Gfx(int count) { int source = ypos + xpos + (x + (y * 0x80)); auto destination = xx + yy + offset + (mx + (my * 0x80)); - current_blockset_[destination] = current_gfx_[source]; + current_blockset_[destination] = + current_gfx_[source] + (info.palette_ * 0x10); } } } diff --git a/src/app/zelda3/overworld_map.h b/src/app/zelda3/overworld_map.h index 2029376a..a2d2a955 100644 --- a/src/app/zelda3/overworld_map.h +++ b/src/app/zelda3/overworld_map.h @@ -13,7 +13,6 @@ #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 { diff --git a/src/app/zelda3/palettes.h b/src/app/zelda3/palettes.h deleted file mode 100644 index 1f1b6e0d..00000000 --- a/src/app/zelda3/palettes.h +++ /dev/null @@ -1,45 +0,0 @@ -#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 diff --git a/src/gui/canvas.cc b/src/gui/canvas.cc index 326dd88e..c7be1208 100644 --- a/src/gui/canvas.cc +++ b/src/gui/canvas.cc @@ -37,15 +37,14 @@ void Canvas::DrawContextMenu() { io.MousePos.y - origin.y); // Add first and second point - if (is_hovered && !dragging_select_ && - ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { - points_.push_back(mouse_pos_in_canvas); - points_.push_back(mouse_pos_in_canvas); - dragging_select_ = true; - } - if (dragging_select_) { - points_.back() = mouse_pos_in_canvas; - if (!ImGui::IsMouseDown(ImGuiMouseButton_Left)) dragging_select_ = false; + if (is_hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { + ImVec2 draw_tile_outline_pos; + draw_tile_outline_pos.x = std::round((double)mouse_pos_in_canvas.x / 32) * 32; + draw_tile_outline_pos.y = std::round((double)mouse_pos_in_canvas.y / 32) * 32; + + points_.push_back(draw_tile_outline_pos); + points_.push_back( + ImVec2(draw_tile_outline_pos.x + 32, draw_tile_outline_pos.y + 32)); } // Pan (we use a zero mouse threshold when there's no context menu) @@ -62,8 +61,6 @@ void Canvas::DrawContextMenu() { ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight); if (ImGui::BeginPopup("context")) { - if (dragging_select_) points_.resize(points_.size() - 2); - dragging_select_ = false; if (ImGui::MenuItem("Remove all", nullptr, false, points_.Size > 0)) { points_.clear(); } diff --git a/src/gui/canvas.h b/src/gui/canvas.h index 1c1bc1f6..4789ec3d 100644 --- a/src/gui/canvas.h +++ b/src/gui/canvas.h @@ -23,7 +23,6 @@ class Canvas { void DrawContextMenu(); void DrawBitmap(const Bitmap& bitmap, int border_offset = 0); void DrawBitmap(const Bitmap& bitmap, int x_offset, int y_offset); - // void DrawLargeBitmap(const Bitmap& tl, const Bitmap& tr, const Bitmap& bl, const Bitmap& br); void DrawOutline(int x, int y, int w, int h); void DrawGrid(float grid_step = 64.0f); void DrawOverlay(); // last @@ -38,7 +37,6 @@ class Canvas { private: bool enable_grid_ = true; bool enable_context_menu_ = true; - bool dragging_select_ = false; bool custom_canvas_size_ = false; ImDrawList* draw_list_;