From 3ada9988aacc9fcbacec1715ea854fdbd04cf658 Mon Sep 17 00:00:00 2001 From: scawful Date: Sun, 25 Jun 2023 10:08:01 -0400 Subject: [PATCH] Begin LoadSprites, LoadChests, housekeeping --- src/app/core/controller.cc | 2 +- src/app/core/controller.h | 2 +- src/app/editor/master_editor.cc | 51 +++++------- src/app/editor/master_editor.h | 3 + src/app/editor/overworld_editor.cc | 42 ++++++++-- src/app/editor/overworld_editor.h | 7 +- src/app/editor/palette_editor.cc | 32 ++++---- src/app/gfx/snes_palette.h | 22 ++++- src/app/rom.cc | 36 ++++++++- src/app/rom.h | 5 ++ src/app/zelda3/dungeon/room.cc | 19 ++++- src/app/zelda3/dungeon/room.h | 4 +- src/app/zelda3/overworld.cc | 126 +++++++++-------------------- src/app/zelda3/overworld.h | 5 +- src/app/zelda3/overworld_map.cc | 4 +- src/app/zelda3/overworld_map.h | 8 +- src/app/zelda3/sprite/sprite.cc | 71 +++++++++++----- src/app/zelda3/sprite/sprite.h | 72 +++++++++-------- 18 files changed, 301 insertions(+), 210 deletions(-) diff --git a/src/app/core/controller.cc b/src/app/core/controller.cc index 5ee1496a..2b0a6b20 100644 --- a/src/app/core/controller.cc +++ b/src/app/core/controller.cc @@ -190,7 +190,7 @@ absl::Status Controller::CreateRenderer() { return absl::OkStatus(); } -absl::Status Controller::CreateGuiContext() { +absl::Status Controller::CreateGuiContext() const { ImGui::CreateContext(); // Initialize ImGui for SDL diff --git a/src/app/core/controller.h b/src/app/core/controller.h index e74cc8f7..9aabbbc7 100644 --- a/src/app/core/controller.h +++ b/src/app/core/controller.h @@ -38,7 +38,7 @@ class Controller { absl::Status CreateWindow(); absl::Status CreateRenderer(); - absl::Status CreateGuiContext(); + absl::Status CreateGuiContext() const; void CloseWindow() { active_ = false; } friend int ::main(int argc, char **argv); diff --git a/src/app/editor/master_editor.cc b/src/app/editor/master_editor.cc index be01d3ea..02055b20 100644 --- a/src/app/editor/master_editor.cc +++ b/src/app/editor/master_editor.cc @@ -14,11 +14,11 @@ #include "app/editor/overworld_editor.h" #include "app/gfx/snes_palette.h" #include "app/gfx/snes_tile.h" -#include "app/rom.h" #include "app/gui/canvas.h" #include "app/gui/icons.h" #include "app/gui/input.h" #include "app/gui/widgets.h" +#include "app/rom.h" namespace yaze { namespace app { @@ -54,22 +54,6 @@ bool BeginCentered(const char *name) { return ImGui::Begin(name, nullptr, flags); } -void DisplayStatus(absl::Status &status) { - if (BeginCentered("StatusWindow")) { - ImGui::Text("%s", status.ToString().c_str()); - ImGui::Spacing(); - ImGui::NextColumn(); - ImGui::Columns(1); - ImGui::Separator(); - ImGui::NewLine(); - ImGui::SameLine(270); - if (ImGui::Button("OK", ImVec2(200, 0))) { - status = absl::OkStatus(); - } - ImGui::End(); - } -} - } // namespace void MasterEditor::SetupScreen(std::shared_ptr renderer) { @@ -114,7 +98,24 @@ void MasterEditor::DrawFileDialog() { void MasterEditor::DrawStatusPopup() { if (!status_.ok()) { - DisplayStatus(status_); + show_status_ = true; + prev_status_ = status_; + } + + if (show_status_) { + if (BeginCentered("StatusWindow")) { + ImGui::Text("%s", prev_status_.ToString().c_str()); + ImGui::Spacing(); + ImGui::NextColumn(); + ImGui::Columns(1); + ImGui::Separator(); + ImGui::NewLine(); + ImGui::SameLine(270); + if (ImGui::Button("OK", ImVec2(200, 0))) { + show_status_ = false; + } + ImGui::End(); + } } } @@ -167,23 +168,13 @@ void MasterEditor::DrawFileMenu() { ".sfc,.smc", "."); } - MENU_ITEM2("Save", "Ctrl+S") { status_ = rom_.SaveToFile(true); } + MENU_ITEM2("Save", "Ctrl+S") { status_ = rom_.SaveToFile(backup_rom_); } MENU_ITEM("Save As..") {} ImGui::Separator(); - // TODO: Make these options matter if (ImGui::BeginMenu("Options")) { - static bool enabled = true; - ImGui::MenuItem("Enabled", "", &enabled); - ImGui::BeginChild("child", ImVec2(0, 60), true); - for (int i = 0; i < 10; i++) ImGui::Text("Scrolling Text %d", i); - ImGui::EndChild(); - static float f = 0.5f; - static int n = 0; - ImGui::SliderFloat("Value", &f, 0.0f, 1.0f); - ImGui::InputFloat("Input", &f, 0.1f); - ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0"); + ImGui::MenuItem("Backup ROM", "", &backup_rom_); ImGui::EndMenu(); } ImGui::EndMenu(); diff --git a/src/app/editor/master_editor.h b/src/app/editor/master_editor.h index c929aeff..eda39893 100644 --- a/src/app/editor/master_editor.h +++ b/src/app/editor/master_editor.h @@ -52,9 +52,12 @@ class MasterEditor { bool about_ = false; bool rom_info_ = false; + bool backup_rom_ = true; + bool show_status_ = false; std::shared_ptr sdl_renderer_; absl::Status status_; + absl::Status prev_status_; AssemblyEditor assembly_editor_; DungeonEditor dungeon_editor_; diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index 22245993..3e00b004 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -13,10 +13,10 @@ #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" #include "app/gfx/snes_tile.h" -#include "app/rom.h" -#include "app/zelda3/overworld.h" #include "app/gui/canvas.h" #include "app/gui/icons.h" +#include "app/rom.h" +#include "app/zelda3/overworld.h" namespace yaze { namespace app { @@ -88,8 +88,8 @@ void OverworldEditor::DrawOverworldMapSettings() { ImGui::TableSetupColumn(name.data()); ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(50.f); - ImGui::InputInt("Current Map", ¤t_map_); + ImGui::SetNextItemWidth(100.f); + ImGui::Combo("##world", &game_state_, "Part 0\0Part 1\0Part 2\0"); ImGui::TableNextColumn(); ImGui::SetNextItemWidth(100.f); @@ -161,7 +161,25 @@ void OverworldEditor::DrawOverworldMaps() { yy++; xx = 0; } - DrawOverworldEntrances(); + } +} + +// ---------------------------------------------------------------------------- + +void OverworldEditor::DrawOverworldSprites() { + for (const auto &sprite : overworld_.Sprites(game_state_)) { + // Get the sprite's bitmap and real X and Y positions + auto id = sprite.id(); + const gfx::Bitmap &sprite_bitmap = sprite_previews_[id]; + int realX = sprite.GetRealX(); + int realY = sprite.GetRealY(); + + // Draw the sprite's bitmap onto the canvas at its real X and Y positions + ow_map_canvas_.DrawBitmap(sprite_bitmap, realX, realY); + ow_map_canvas_.DrawRect(realX, realY, sprite.Width(), sprite.Height(), + ImVec4(255, 0, 0, 150)); + std::string str = absl::StrFormat("%s", sprite.Name()); + ow_map_canvas_.DrawText(str, realX - 4, realY - 2); } } @@ -192,6 +210,8 @@ void OverworldEditor::DrawOverworldCanvas() { ow_map_canvas_.DrawContextMenu(); if (overworld_.isLoaded()) { DrawOverworldMaps(); + DrawOverworldEntrances(); + DrawOverworldSprites(); // User has selected a tile they want to draw from the blockset. if (!blockset_canvas_.Points().empty()) { int x = blockset_canvas_.Points().front().x / 32; @@ -358,6 +378,18 @@ absl::Status OverworldEditor::LoadGraphics() { rom_.RenderBitmap(&(maps_bmp_[i])); } + // Render the sprites for each Overworld map + // for (int i = 0; i < 3; i++) + // for (auto &sprite : overworld_.Sprites(i)) { + // int width = sprite.Width(); + // int height = sprite.Height(); + // int depth = 0x40; + // auto spr_gfx = sprite.PreviewGraphics().data(); + // sprite_previews_[sprite.id()].Create(width, height, depth, spr_gfx); + // sprite_previews_[sprite.id()].ApplyPalette(palette_); + // rom_.RenderBitmap(&(sprite_previews_[sprite.id()])); + // } + return absl::OkStatus(); } diff --git a/src/app/editor/overworld_editor.h b/src/app/editor/overworld_editor.h index e90cdae0..f5690484 100644 --- a/src/app/editor/overworld_editor.h +++ b/src/app/editor/overworld_editor.h @@ -14,10 +14,11 @@ #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" #include "app/gfx/snes_tile.h" -#include "app/rom.h" -#include "app/zelda3/overworld.h" #include "app/gui/canvas.h" #include "app/gui/icons.h" +#include "app/rom.h" +#include "app/zelda3/overworld.h" + namespace yaze { namespace app { @@ -56,6 +57,7 @@ class OverworldEditor { void DrawOverworldEntrances(); void DrawOverworldMaps(); + void DrawOverworldSprites(); void DrawOverworldEdits(); void DrawOverworldCanvas(); @@ -69,6 +71,7 @@ class OverworldEditor { int current_map_ = 0; int current_tile16_ = 0; int selected_tile_ = 0; + int game_state_ = 0; char map_gfx_[3] = ""; char map_palette_[3] = ""; char spr_gfx_[3] = ""; diff --git a/src/app/editor/palette_editor.cc b/src/app/editor/palette_editor.cc index f234d4ab..3e9e373d 100644 --- a/src/app/editor/palette_editor.cc +++ b/src/app/editor/palette_editor.cc @@ -40,6 +40,16 @@ using namespace ImGui; } // namespace +absl::Status PaletteEditor::Update() { + for (int i = 0; i < kNumPalettes; ++i) { + if (ImGui::TreeNode(kPaletteCategoryNames[i].data())) { + DrawPaletteGroup(i); + ImGui::TreePop(); + } + } + return absl::OkStatus(); +} + void PaletteEditor::DrawPaletteGroup(int i) { auto size = rom_.GetPaletteGroup(kPaletteGroupNames[i].data()).size(); auto palettes = rom_.GetPaletteGroup(kPaletteGroupNames[i].data()); @@ -61,7 +71,7 @@ void PaletteEditor::DrawPaletteGroup(int i) { palette_button_flags)) current_color_ = ImVec4(palette[n].rgb.x, palette[n].rgb.y, palette[n].rgb.z, - palette[n].rgb.w); // Preserve alpha! + palette[n].rgb.w); // Prese rve alpha! } if (ImGui::BeginPopupContextItem(popupId.c_str())) { @@ -69,11 +79,8 @@ void PaletteEditor::DrawPaletteGroup(int i) { if (ImGui::ColorEdit4( "Edit Color", col, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha)) { - // palette[n].rgb.x = current_color_rgba.x; - // palette[n].rgb.y = current_color_rgba.y; - // palette[n].rgb.z = current_color_rgba.z; - // rom_.UpdatePaletteColor(kPaletteGroupNames[groupIndex].data(), j, - // n, palette[n]); + rom_.UpdatePaletteColor(kPaletteGroupNames[i].data(), j, n, + palette[n]); } if (Button("Copy as..", ImVec2(-1, 0))) OpenPopup("Copy"); if (BeginPopup("Copy")) { @@ -100,16 +107,6 @@ void PaletteEditor::DrawPaletteGroup(int i) { } } -absl::Status PaletteEditor::Update() { - for (int i = 0; i < kNumPalettes; ++i) { - if (ImGui::TreeNode(kPaletteCategoryNames[i].data())) { - DrawPaletteGroup(i); - ImGui::TreePop(); - } - } - return absl::OkStatus(); -} - void PaletteEditor::DisplayPalette(gfx::SNESPalette& palette, bool loaded) { static ImVec4 color = ImVec4(0, 0, 0, 255.f); ImGuiColorEditFlags misc_flags = ImGuiColorEditFlags_AlphaPreview | @@ -150,7 +147,6 @@ void PaletteEditor::DisplayPalette(gfx::SNESPalette& palette, bool loaded) { ImGui::Text("Previous"); if (ImGui::Button("Update Map Palette")) { - } ImGui::ColorButton( @@ -165,7 +161,7 @@ void PaletteEditor::DisplayPalette(gfx::SNESPalette& palette, bool loaded) { ImVec2(60, 40))) color = backup_color; - // List of Colors in Overworld Palette + // List of Colors in Overworld Palette ImGui::Separator(); ImGui::Text("Palette"); for (int n = 0; n < IM_ARRAYSIZE(saved_palette_); n++) { diff --git a/src/app/gfx/snes_palette.h b/src/app/gfx/snes_palette.h index e213e52e..59b1610a 100644 --- a/src/app/gfx/snes_palette.h +++ b/src/app/gfx/snes_palette.h @@ -49,7 +49,7 @@ struct SNESColor { auto RGB() { return ImVec4(rgb.x / 255, rgb.y / 255, rgb.z / 255, rgb.w); } - float* ToFloatArray() const { + float* ToFloatArray() { static std::vector colorArray(4); colorArray[0] = rgb.x / 255.0f; colorArray[1] = rgb.y / 255.0f; @@ -86,6 +86,26 @@ class SNESPalette { return colors[i]; } + void operator()(int i, const SNESColor& color) { + if (i >= size_) { + std::cout << "SNESPalette: Index out of bounds" << std::endl; + return; + } + colors[i] = color; + } + + void operator()(int i, const ImVec4& color) { + if (i >= size_) { + std::cout << "SNESPalette: Index out of bounds" << std::endl; + return; + } + colors[i].rgb.x = color.x; + colors[i].rgb.y = color.y; + colors[i].rgb.z = color.z; + colors[i].rgb.w = color.w; + colors[i].modified = true; + } + char* encode(); SDL_Palette* GetSDL_Palette(); diff --git a/src/app/rom.cc b/src/app/rom.cc index 09a902c0..8661951f 100644 --- a/src/app/rom.cc +++ b/src/app/rom.cc @@ -538,7 +538,7 @@ absl::StatusOr ROM::Decompress(int offset, int size, int mode) { } break; case kCommandRepeatingBytes: { ushort s1 = ((rom_data_[offset + 1] & kSnesByteMax) << 8); - ushort s2 = ((rom_data_[offset] & kSnesByteMax)); + ushort s2 = (rom_data_[offset] & kSnesByteMax); int addr = (s1 | s2); if (mode == kNintendoMode1) { // Reversed byte order for overworld maps addr = (rom_data_[offset + 1] & kSnesByteMax) | @@ -766,6 +766,35 @@ void ROM::LoadAllPalettes() { // ============================================================================ +void ROM::UpdatePaletteColor(const std::string& groupName, size_t paletteIndex, + size_t colorIndex, + const gfx::SNESColor& newColor) { + // Check if the groupName exists in the palette_groups_ map + if (palette_groups_.find(groupName) != palette_groups_.end()) { + // Check if the paletteIndex is within the range of available palettes in + // the group + if (paletteIndex < palette_groups_[groupName].size()) { + // Check if the colorIndex is within the range of available colors in the + // palette + if (colorIndex < palette_groups_[groupName][paletteIndex].size()) { + // Update the color value in the palette + palette_groups_[groupName][paletteIndex][colorIndex] = newColor; + } else { + std::cerr << "Error: Invalid color index in UpdatePaletteColor." + << std::endl; + } + } else { + std::cerr << "Error: Invalid palette index in UpdatePaletteColor." + << std::endl; + } + } else { + std::cerr << "Error: Invalid group name in UpdatePaletteColor." + << std::endl; + } +} + +// ============================================================================ + void ROM::SaveAllPalettes() { // Iterate through all palette_groups_ for (auto& [groupName, palettes] : palette_groups_) { @@ -776,7 +805,6 @@ void ROM::SaveAllPalettes() { // Iterate through all colors in the palette for (size_t j = 0; j < palette.size(); ++j) { gfx::SNESColor color = palette[j]; - // If the color is modified, save the color to the ROM if (color.modified) { WriteColor(GetPaletteAddress(groupName, i, j), color); @@ -790,6 +818,10 @@ void ROM::SaveAllPalettes() { // ============================================================================ absl::Status ROM::SaveToFile(bool backup) { + if (rom_data_.empty()) { + return absl::InternalError("ROM data is empty."); + } + // Check if backup is enabled if (backup) { // Create a backup file with timestamp in its name diff --git a/src/app/rom.h b/src/app/rom.h index 16148815..205f8602 100644 --- a/src/app/rom.h +++ b/src/app/rom.h @@ -26,6 +26,7 @@ #include "app/core/common.h" #include "app/core/constants.h" #include "app/gfx/bitmap.h" +#include "app/gfx/snes_palette.h" #define BUILD_HEADER(command, length) (command << 5) + (length - 1) @@ -137,7 +138,10 @@ class ROM { absl::Status LoadFromBytes(const Bytes& data); void LoadAllPalettes(); + // Save functions absl::Status SaveToFile(bool backup); + void UpdatePaletteColor(const std::string& groupName, size_t paletteIndex, + size_t colorIndex, const gfx::SNESColor& newColor); void SaveAllPalettes(); gfx::SNESColor ReadColor(int offset); @@ -157,6 +161,7 @@ class ROM { gfx::BitmapTable GetGraphicsBin() const { return graphics_bin_; } auto GetGraphicsBuffer() const { return graphics_buffer_; } + auto GetPaletteGroup(const std::string& group) { return palette_groups_[group]; } diff --git a/src/app/zelda3/dungeon/room.cc b/src/app/zelda3/dungeon/room.cc index ae074b15..6ff52c39 100644 --- a/src/app/zelda3/dungeon/room.cc +++ b/src/app/zelda3/dungeon/room.cc @@ -4,8 +4,8 @@ #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" #include "app/gfx/snes_tile.h" -#include "app/rom.h" #include "app/gui/canvas.h" +#include "app/rom.h" namespace yaze { namespace app { @@ -74,7 +74,22 @@ bool Room::SaveGroupsToROM() { return false; } -void Room::LoadChests() {} +void Room::LoadChests() { + // ChestList.Clear(); + + // int cpos = rom_.Read24(core::constants::chests_data_pointer1).SNEStoPC(); + // int clength = rom_.Read16(core::constants::chests_length_pointer); + + // for (int i = 0; i < clength; i += 3) { + // ushort roomid = (ushort)(rom_.Read16(cpos) & 0x7FFF); + // cpos += 2; + // uchar item = rom_[cpos++]; // get now so cpos is incremented too + + // if (roomid == RoomID) { + // ChestList.Add(new DungeonChestItem(ItemReceipt.GetTypeFromID(item))); + // } + // } +} void Room::LoadBlocks() {} diff --git a/src/app/zelda3/dungeon/room.h b/src/app/zelda3/dungeon/room.h index 8b02f115..1dffb1b8 100644 --- a/src/app/zelda3/dungeon/room.h +++ b/src/app/zelda3/dungeon/room.h @@ -2,11 +2,12 @@ #define YAZE_APP_ZELDA3_DUNGEON_ROOM_H #include "app/core/common.h" +#include "app/core/constants.h" #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" #include "app/gfx/snes_tile.h" -#include "app/rom.h" #include "app/gui/canvas.h" +#include "app/rom.h" namespace yaze { namespace app { @@ -122,6 +123,7 @@ class Room { uchar Floor2Graphics; uchar Layer2Mode; std::array blocks; + std::array ChestList; uint8_t mainGfx[37][8]; uint8_t roomGfx[82][4]; diff --git a/src/app/zelda3/overworld.cc b/src/app/zelda3/overworld.cc index 2228043d..9758581c 100644 --- a/src/app/zelda3/overworld.cc +++ b/src/app/zelda3/overworld.cc @@ -39,7 +39,6 @@ absl::Status Overworld::Load(ROM &rom) { FetchLargeMaps(); LoadEntrances(); - LoadSprites(); auto size = tiles16.size(); std::vector> futures; @@ -66,6 +65,8 @@ absl::Status Overworld::Load(ROM &rom) { } } + LoadSprites(); + is_loaded_ = true; return absl::OkStatus(); } @@ -555,107 +556,60 @@ void Overworld::LoadEntrances() { // ---------------------------------------------------------------------------- void Overworld::LoadSprites() { - // LW[0] = RainState 0 to 63 there's no data for DW - // LW[1] = ZeldaState 0 to 128 ; Contains LW and DW <128 or 144 wtf - // LW[2] = AgahState 0 to ?? ;Contains data for LW and DW - for (int i = 0; i < 3; i++) { - all_sprites_.emplace_back(std::vector()); + all_sprites_.emplace_back(); } for (int i = 0; i < 64; i++) { - if (map_parent_[i] == i) { - // Beginning Sprites - int ptrPos = core::overworldSpritesBegining + (i * 2); - int spriteAddress = core::SnesToPc((0x09 << 0x10) + rom_.toint16(ptrPos)); - while (true) { - uchar b1 = rom_[spriteAddress]; - uchar b2 = rom_[spriteAddress + 1]; - uchar b3 = rom_[spriteAddress + 2]; - if (b1 == 0xFF) { - break; - } - - int mapY = (i / 8); - int mapX = (i % 8); - - int realX = ((b2 & 0x3F) * 16) + mapX * 512; - int realY = ((b1 & 0x3F) * 16) + mapY * 512; - - all_sprites_[0].emplace_back(overworld_maps_[i].AreaGraphics(), - (uchar)i, b3, (uchar)(b2 & 0x3F), - (uchar)(b1 & 0x3F), realX, realY); - - spriteAddress += 3; - } - } + all_sprites_[0].emplace_back(); } for (int i = 0; i < 144; i++) { - if (map_parent_[i] == i) { - // Zelda Saved Sprites - int ptrPos = core::overworldSpritesZelda + (i * 2); - int spriteAddress = core::SnesToPc((0x09 << 0x10) + rom_.toint16(ptrPos)); - while (true) { - uchar b1 = rom_[spriteAddress]; - uchar b2 = rom_[spriteAddress + 1]; - uchar b3 = rom_[spriteAddress + 2]; - if (b1 == 0xFF) { - break; - } + all_sprites_[1].emplace_back(); + } - int editorMapIndex = i; - if (editorMapIndex >= 128) { - editorMapIndex = i - 128; - } else if (editorMapIndex >= 64) { - editorMapIndex = i - 64; - } + for (int i = 0; i < 144; i++) { + all_sprites_[2].emplace_back(); + } - int mapY = (editorMapIndex / 8); - int mapX = (editorMapIndex % 8); + LoadSpritesFromMap(core::overworldSpritesBegining, 64, 0); + LoadSpritesFromMap(core::overworldSpritesZelda, 144, 1); + LoadSpritesFromMap(core::overworldSpritesAgahnim, 144, 2); +} - int realX = ((b2 & 0x3F) * 16) + mapX * 512; - int realY = ((b1 & 0x3F) * 16) + mapY * 512; +// ---------------------------------------------------------------------------- - all_sprites_[1].emplace_back(overworld_maps_[i].AreaGraphics(), - (uchar)i, b3, (uchar)(b2 & 0x3F), - (uchar)(b1 & 0x3F), realX, realY); +void Overworld::LoadSpritesFromMap(int spriteStart, int spriteCount, + int spriteIndex) { + for (int i = 0; i < spriteCount; i++) { + if (map_parent_[i] != i) continue; - spriteAddress += 3; - } - } + int ptrPos = spriteStart + (i * 2); + int spriteAddress = core::SnesToPc((0x09 << 0x10) + rom_.toint16(ptrPos)); + while (true) { + uchar b1 = rom_[spriteAddress]; + uchar b2 = rom_[spriteAddress + 1]; + uchar b3 = rom_[spriteAddress + 2]; + if (b1 == 0xFF) break; - // Agahnim Dead Sprites - if (map_parent_[i] == i) { - int ptrPos = core::overworldSpritesAgahnim + (i * 2); - int spriteAddress = core::SnesToPc((0x09 << 0x10) + rom_.toint16(ptrPos)); - while (true) { - uchar b1 = rom_[spriteAddress]; - uchar b2 = rom_[spriteAddress + 1]; - uchar b3 = rom_[spriteAddress + 2]; - if (b1 == 0xFF) { - break; - } + int editorMapIndex = i; + if (editorMapIndex >= 128) + editorMapIndex -= 128; + else if (editorMapIndex >= 64) + editorMapIndex -= 64; - int editorMapIndex = i; - if (editorMapIndex >= 128) { - editorMapIndex = i - 128; - } else if (editorMapIndex >= 64) { - editorMapIndex = i - 64; - } + int mapY = (editorMapIndex / 8); + int mapX = (editorMapIndex % 8); - int mapY = (editorMapIndex / 8); - int mapX = (editorMapIndex % 8); + int realX = ((b2 & 0x3F) * 16) + mapX * 512; + int realY = ((b1 & 0x3F) * 16) + mapY * 512; + auto graphics_bytes = overworld_maps_[i].AreaGraphics(); + all_sprites_[spriteIndex][i].InitSprite(graphics_bytes, (uchar)i, b3, + (uchar)(b2 & 0x3F), + (uchar)(b1 & 0x3F), realX, realY); + all_sprites_[spriteIndex][i].Draw(); - int realX = ((b2 & 0x3F) * 16) + mapX * 512; - int realY = ((b1 & 0x3F) * 16) + mapY * 512; - - all_sprites_[2].emplace_back(overworld_maps_[i].AreaGraphics(), - (uchar)i, b3, (uchar)(b2 & 0x3F), - (uchar)(b1 & 0x3F), realX, realY); - - spriteAddress += 3; - } + spriteAddress += 3; } } } diff --git a/src/app/zelda3/overworld.h b/src/app/zelda3/overworld.h index 61e42f06..21227b63 100644 --- a/src/app/zelda3/overworld.h +++ b/src/app/zelda3/overworld.h @@ -3,9 +3,9 @@ #include +#include #include #include -#include #include "absl/status/status.h" #include "app/core/constants.h" @@ -78,7 +78,7 @@ class Overworld { auto GetTiles16() const { return tiles16; } auto GetOverworldMap(uint index) { return overworld_maps_[index]; } auto GetOverworldMaps() const { return overworld_maps_; } - auto Sprites() const { return all_sprites_[game_state_]; } + auto Sprites(int state) const { return all_sprites_[state]; } auto AreaGraphics() const { return overworld_maps_[current_map_].AreaGraphics(); } @@ -115,6 +115,7 @@ class Overworld { void FetchLargeMaps(); void LoadEntrances(); void LoadSprites(); + void LoadSpritesFromMap(int spriteStart, int spriteCount, int spriteIndex); void LoadOverworldMap(); diff --git a/src/app/zelda3/overworld_map.cc b/src/app/zelda3/overworld_map.cc index 97c6772d..39e4cefd 100644 --- a/src/app/zelda3/overworld_map.cc +++ b/src/app/zelda3/overworld_map.cc @@ -109,8 +109,8 @@ void SetColorsPalette(ROM& rom, int index, gfx::SNESPalette& current, k = 0; for (int y = 9; y < 13; y++) { for (int x = 1; x < 16; x++) { - new_palette[x + (16 * y)] = - rom.GetPaletteGroup("global_sprites")[0][k]; k++; + new_palette[x + (16 * y)] = rom.GetPaletteGroup("global_sprites")[0][k]; + k++; } } diff --git a/src/app/zelda3/overworld_map.h b/src/app/zelda3/overworld_map.h index d862cceb..742d0000 100644 --- a/src/app/zelda3/overworld_map.h +++ b/src/app/zelda3/overworld_map.h @@ -12,8 +12,8 @@ #include "absl/status/status.h" #include "app/core/common.h" #include "app/gfx/bitmap.h" -#include "app/gfx/snes_tile.h" #include "app/gfx/snes_palette.h" +#include "app/gfx/snes_tile.h" #include "app/rom.h" namespace yaze { @@ -50,10 +50,9 @@ class OverworldMap { void LoadPalette(); - - void ProcessGraphicsBuffer(int index, int static_graphics_offset, int size); - gfx::SNESPalette GetPalette(const std::string& group, int index, int previousIndex, int limit); + gfx::SNESPalette GetPalette(const std::string& group, int index, + int previousIndex, int limit); absl::Status BuildTileset(); absl::Status BuildTiles16Gfx(int count); @@ -86,6 +85,7 @@ class OverworldMap { OWMapTiles map_tiles_; gfx::SNESPalette current_palette_; + // std::vector sprite_graphics_; std::vector tiles16_; }; diff --git a/src/app/zelda3/sprite/sprite.cc b/src/app/zelda3/sprite/sprite.cc index 52774d58..96257a39 100644 --- a/src/app/zelda3/sprite/sprite.cc +++ b/src/app/zelda3/sprite/sprite.cc @@ -4,8 +4,15 @@ namespace yaze { namespace app { namespace zelda3 { -Sprite::Sprite(Bytes src, uchar mapid, uchar id, uchar x, uchar y, int map_x, - int map_y) { +Sprite::Sprite() { + preview_gfx_.reserve(64 * 64); + for (int i = 0; i < 64 * 64; i++) { + preview_gfx_.push_back(0xFF); + } +} + +void Sprite::InitSprite(Bytes& src, uchar mapid, uchar id, uchar x, uchar y, + int map_x, int map_y) { current_gfx_ = src; overworld_ = true; map_id_ = mapid; @@ -17,12 +24,34 @@ Sprite::Sprite(Bytes src, uchar mapid, uchar id, uchar x, uchar y, int map_x, name_ = core::kSpriteDefaultNames[id]; map_x_ = map_x; map_y_ = map_y; +} + +Sprite::Sprite(Bytes src, uchar mapid, uchar id, uchar x, uchar y, int map_x, + int map_y) + : current_gfx_(src), + map_id_(mapid), + id_(id), + x_(x), + y_(y), + nx_(x), + ny_(y), + map_x_(map_x), + map_y_(map_y) { + current_gfx_ = src; + overworld_ = true; + + name_ = core::kSpriteDefaultNames[id]; preview_gfx_.reserve(64 * 64); for (int i = 0; i < 64 * 64; i++) { preview_gfx_.push_back(0xFF); } } +void Sprite::updateCoordinates(int map_x, int map_y) { + map_x_ = map_x; + map_y_ = map_y; +} + void Sprite::updateBBox() { lowerX_ = 1; lowerY_ = 1; @@ -30,10 +59,9 @@ void Sprite::updateBBox() { higherY_ = 15; } -void Sprite::Draw(bool picker) { +void Sprite::Draw() { uchar x = nx_; uchar y = ny_; - picker_ = picker; if (overlord_ == 0x07) { if (id_ == 0x1A) { @@ -288,11 +316,11 @@ void Sprite::Draw(bool picker) { DrawSpriteTile((x * 16), (y * 16), 14, 22, 10); } /* -else if (id_== 0x33) // Pull for rupees -{ + else if (id_== 0x33) // Pull for rupees + { -} -*/ + } + */ else if (id_ == 0x34) // Npcs { DrawSpriteTile((x * 16), (y * 16), 14, 22, 10); @@ -304,11 +332,11 @@ else if (id_== 0x33) // Pull for rupees DrawSpriteTile((x * 16), (y * 16), 14, 22, 10); } /* -else if (id_== 0x37) // Waterfall -{ -DrawSpriteTile((x*16), (y *16), 14, 6, 10); -} -*/ + else if (id_== 0x37) // Waterfall + { + DrawSpriteTile((x*16), (y *16), 14, 6, 10); + } + */ else if (id_ == 0x38) // Arrowtarget { DrawSpriteTile((x * 16), (y * 16), 14, 22, 10); @@ -602,9 +630,6 @@ DrawSpriteTile((x*16), (y *16), 14, 6, 10); } else if (id_ == 0x79) // Bee { DrawSpriteTile((x * 16), (y * 16), 4, 14, 11, false, false, 1, 1); - } else if (id_ == 0x7A) { - DrawSpriteTile((x * 16), (y * 16) - 16, 2, 24, 12, false, false, 2, 4); - DrawSpriteTile((x * 16) + 16, (y * 16) - 16, 2, 24, 12, true, false, 2, 4); } else if (id_ == 0x7C) // Skull head { DrawSpriteTile((x * 16), (y * 16), 0, 16, 10); @@ -808,7 +833,7 @@ DrawSpriteTile((x*16), (y *16), 14, 6, 10); DrawSpriteTile((x * 16), (y * 16), 12, 10, 10); } else if (id_ == 0xBA) { DrawSpriteTile((x * 16), (y * 16), 14, 14, 6); - } else if (id_ == 0xC1) { + } else if (id_ == 0xC1 || id_ == 0x7A) { DrawSpriteTile((x * 16), (y * 16) - 16, 2, 24, 12, false, false, 2, 4); DrawSpriteTile((x * 16) + 16, (y * 16) - 16, 2, 24, 12, true, false, 2, 4); } else if (id_ == 0xC3) { @@ -871,7 +896,6 @@ DrawSpriteTile((x*16), (y *16), 14, 6, 10); } else if (id_ == 0xF4) { DrawSpriteTile((x * 16), (y * 16), 12, 28, 5, false, false, 4, 4); } else { - // stringtodraw.Add(new SpriteName(x, (y *16), sprites_name.name[id])); DrawSpriteTile((x * 16), (y * 16), 4, 4, 5); } @@ -882,8 +906,13 @@ DrawSpriteTile((x*16), (y *16), 14, 6, 10); } void Sprite::DrawSpriteTile(int x, int y, int srcx, int srcy, int pal, - bool mirror_x, bool mirror_y, int sizex, int sizey, - bool iskey) { + bool mirror_x, bool mirror_y, int sizex, + int sizey) { + if (current_gfx_.empty()) { + std::cout << "No gfx loaded" << std::endl; + return; + } + x += 16; y += 16; int drawid_ = (srcx + (srcy * 16)) + 512; @@ -896,7 +925,7 @@ void Sprite::DrawSpriteTile(int x, int y, int srcx, int srcy, int pal, mx = (((sizex * 8) / 2) - 1) - xl; } if (mirror_y) { - my = (((sizey * 8)) - 1) - yl; + my = ((sizey * 8) - 1) - yl; } // Formula information to get tile index position in the array diff --git a/src/app/zelda3/sprite/sprite.h b/src/app/zelda3/sprite/sprite.h index aeb3308e..c8646820 100644 --- a/src/app/zelda3/sprite/sprite.h +++ b/src/app/zelda3/sprite/sprite.h @@ -20,45 +20,53 @@ namespace zelda3 { class Sprite { public: - uchar x_, y_, id_; - uchar nx_, ny_; - uchar layer_ = 0; - uchar subtype_ = 0; + Sprite(); + Sprite(Bytes src, uchar mapid, uchar id, uchar x, uchar y, int map_x, + int map_y); + void InitSprite(Bytes& src, uchar mapid, uchar id, uchar x, uchar y, + int map_x, int map_y); + void updateBBox(); + + void Draw(); + void DrawSpriteTile(int x, int y, int srcx, int srcy, int pal, + bool mirror_x = false, bool mirror_y = false, + int sizex = 2, int sizey = 2); + + // New methods + void updateCoordinates(int map_x, int map_y); + + auto PreviewGraphics() const { return preview_gfx_; } + auto GetRealX() const { return bounding_box_.x; } + auto GetRealY() const { return bounding_box_.y; } + auto id() const { return id_; } + + auto Width() const { return bounding_box_.w; } + auto Height() const { return bounding_box_.h; } + std::string Name() const { return name_; } + + private: + Bytes current_gfx_; + bool overworld_; + uchar map_id_; + uchar id_; + uchar x_; + uchar y_; + uchar nx_; + uchar ny_; uchar overlord_ = 0; std::string name_; - uchar keyDrop_ = 0; - int sizeMap_ = 512; - bool overworld_ = false; - bool preview_ = false; - uchar map_id_ = 0; - int map_x_ = 0; - int map_y_ = 0; - short room_id_ = 0; - bool picker_ = false; - bool selected_ = false; + int map_x_; + int map_y_; + Bytes preview_gfx_; + uchar lowerX_; + uchar lowerY_; + uchar higherX_; + uchar higherY_; SDL_Rect bounding_box_; - Bytes current_gfx_; - Bytes preview_gfx_; - - int lowerX_ = 32; - int lowerY_ = 32; - int higherX_ = 0; - int higherY_ = 0; int width_ = 16; int height_ = 16; - Sprite(Bytes src, uchar mapid, uchar id, uchar x, uchar y, int map_x, - int map_y); - void updateBBox(); - - void Draw(bool picker = false); - - void DrawSpriteTile(int x, int y, int srcx, int srcy, int pal, - bool mirror_x = false, bool mirror_y = false, - int sizex = 2, int sizey = 2, bool iskey = false); - - auto PreviewGraphics() { return preview_gfx_; } }; } // namespace zelda3